host_firewall: drop bruteforceblocker, vxvault and cybercrime, only firehol level1 and level2 ban

This commit is contained in:
2026-11-05 16:51:45 +00:00
parent 6a1e7b77e7
commit 1d10f2be39
4 changed files with 27 additions and 37 deletions
+4 -6
View File
@@ -93,7 +93,7 @@ firewall:
# Lets the kernel log the nft log statements of container network # Lets the kernel log the nft log statements of container network
# namespaces (LXC guests) into the host kernel log. # namespaces (LXC guests) into the host kernel log.
all_netns: false all_netns: false
# Shared by the Spamhaus (fw-spamhaus-in: , fw-spamhaus-out: ), FireHOL (fw-firehol-in: , fw-firehol-out: ), bruteforceblocker (fw-bruteforceblocker-in: ) and scanner (fw-scanners-in: ) chains, # Shared by the Spamhaus (fw-spamhaus-in: , fw-spamhaus-out: ), FireHOL (fw-firehol-in: , fw-firehol-out: ) and scanner (fw-scanners-in: ) chains,
# one limit each. # one limit each.
spamhaus_rate: "6/minute burst 10 packets" spamhaus_rate: "6/minute burst 10 packets"
# Spamhaus DROP, DROPv6 and ASN-DROP: traffic from the listed networks drops # Spamhaus DROP, DROPv6 and ASN-DROP: traffic from the listed networks drops
@@ -101,11 +101,9 @@ firewall:
# are refreshed daily by nft-host-spamhaus. # are refreshed daily by nft-host-spamhaus.
spamhaus: true spamhaus: true
# FireHOL lists (IPv4 only, FireHOL has no IPv6 lists), from github.com/firehol/blocklist-ipsets: # FireHOL lists (IPv4 only, FireHOL has no IPv6 lists), from github.com/firehol/blocklist-ipsets:
# - level1 and level2 (level2 includes GreenSnow) and the malware set (vxvault and cybercrime): treated like the # level1 and level2 (level2 includes GreenSnow): treated like the Spamhaus lists, with the prefixes fw-firehol-in:
# Spamhaus lists, with the prefixes fw-firehol-in: and fw-firehol-out: and the same log limit. # and fw-firehol-out: and the same log limit.
# - bruteforceblocker: inbound new connections from the listed hosts drop, outbound traffic is not filtered. Log # Entries in private or reserved space and ones holding an address of the host are left out. Both sets are refreshed
# prefix fw-bruteforceblocker-in: with its own limit, which CrowdSec whitelists.
# Entries in private or reserved space and ones holding an address of the host are left out. All sets are refreshed
# daily by nft-host-firehol. # daily by nft-host-firehol.
firehol: true firehol: true
# Internet-wide scanners (Censys, Shodan, ONYPHE, Shadowserver, ...), IPv4 # Internet-wide scanners (Censys, Shodan, ONYPHE, Shadowserver, ...), IPv4
+2 -4
View File
@@ -23,13 +23,11 @@ BASE_URL = "https://raw.githubusercontent.com/firehol/blocklist-ipsets/master/"
USER_AGENT = "ruekov-host-firewall (nft-host-firehol)" USER_AGENT = "ruekov-host-firewall (nft-host-firehol)"
# set name -> (lists merged into it, lower bound for their entries together that # set name -> (lists merged into it, lower bound for their entries together that
# catches an empty or truncated answer; the lists hold about 4700 (level1), # catches an empty or truncated answer; the lists hold about 4700 (level1) and
# 18700 (level2), 500 (bruteforceblocker) and 70 + 500 (vxvault, cybercrime)). # 18700 (level2)).
SETS = { SETS = {
"firehol_v4": (["firehol_level1.netset"], 1000), "firehol_v4": (["firehol_level1.netset"], 1000),
"firehol_level2_v4": (["firehol_level2.netset"], 5000), "firehol_level2_v4": (["firehol_level2.netset"], 5000),
"bruteforceblocker_v4": (["bruteforceblocker.ipset"], 100),
"malware_v4": (["vxvault.ipset", "cybercrime.ipset"], 200),
} }
# A prefix this wide is a parse error, not a bad network. # A prefix this wide is a parse error, not a bad network.
MIN_PREFIXLEN = 8 MIN_PREFIXLEN = 8
+21 -3
View File
@@ -183,17 +183,26 @@
dest: /usr/local/sbin/nft-host-firehol dest: /usr/local/sbin/nft-host-firehol
mode: "0755" mode: "0755"
# The rule set includes this file and uses all of its sets, so a missing file or set would fail the load at boot. # The rule set includes this file and uses both sets, so a missing file or set would fail the load at boot.
- name: Look for the FireHOL sets - name: Look for the FireHOL sets
ansible.builtin.command: grep -cE 'set (firehol_v4|firehol_level2_v4|bruteforceblocker_v4|malware_v4) ' /etc/nftables.d/host-firehol.nft ansible.builtin.command: grep -cE 'set (firehol_v4|firehol_level2_v4) ' /etc/nftables.d/host-firehol.nft
register: firewall_firehol_sets register: firewall_firehol_sets
changed_when: false changed_when: false
failed_when: false failed_when: false
check_mode: false check_mode: false
# Sets of removed lists are unused by the new rule set, which nft accepts, but the deployed one still uses them:
# a rebuild before the new rule set is confirmed would fail its reload. The rebuild at the end of the role drops them.
- name: Look for sets of removed FireHOL lists
ansible.builtin.command: grep -cE 'set (bruteforceblocker_v4|malware_v4) ' /etc/nftables.d/host-firehol.nft
register: firewall_firehol_stale
changed_when: false
failed_when: false
check_mode: false
- name: Build the FireHOL sets when missing - name: Build the FireHOL sets when missing
ansible.builtin.command: /usr/local/sbin/nft-host-firehol ansible.builtin.command: /usr/local/sbin/nft-host-firehol
when: firewall_firehol_sets.stdout != '4' when: firewall_firehol_sets.stdout != '2'
- name: Read the FireHOL sets file - name: Read the FireHOL sets file
ansible.builtin.stat: ansible.builtin.stat:
@@ -400,3 +409,12 @@
ansible.builtin.systemd: ansible.builtin.systemd:
daemon_reload: true daemon_reload: true
when: firewall_greensnow_files is changed when: firewall_greensnow_files is changed
# The sets file keeps sets of removed FireHOL lists until the rule set without them is confirmed (see above).
- name: Drop sets of removed FireHOL lists
ansible.builtin.command: /usr/local/sbin/nft-host-firehol
when:
- firewall.firehol
- firewall_firehol_sets.stdout == '2'
- (firewall_firehol_stale.stdout | default('0') | int) > 0
- not ansible_check_mode
-24
View File
@@ -171,7 +171,6 @@ table inet host {
{% if firewall.firehol %} {% if firewall.firehol %}
ip saddr @firehol_v4 jump firehol_in ip saddr @firehol_v4 jump firehol_in
ip saddr @firehol_level2_v4 jump firehol_in ip saddr @firehol_level2_v4 jump firehol_in
ip saddr @malware_v4 jump firehol_in
{% endif %} {% endif %}
{% endif %} {% endif %}
@@ -191,12 +190,6 @@ table inet host {
ip saddr @scanners_v4 jump scanners_in ip saddr @scanners_v4 jump scanners_in
ip6 saddr @scanners_v6 jump scanners_in ip6 saddr @scanners_v6 jump scanners_in
{% endif %}
{% if firewall.firehol %}
# After the established rule: only inbound connections of bruteforceblocker hosts drop.
ip saddr @bruteforceblocker_v4 jump bruteforceblocker_in
{% endif %} {% endif %}
ct state invalid jump drop_log ct state invalid jump drop_log
iif lo accept iif lo accept
@@ -360,16 +353,6 @@ table inet host {
drop drop
} }
{% endif %} {% endif %}
{% if firewall.firehol %}
# Own limit and prefix, so bruteforceblocker hits use up neither the fw-in-drop budget
# nor the one of the blocklists. CrowdSec whitelists the prefix: the listed
# hosts are known and need no decision.
chain bruteforceblocker_in {
limit rate {{ firewall.log.spamhaus_rate }} log prefix "fw-bruteforceblocker-in: "
drop
}
{% endif %}
{% if firewall.block_smtp_out or blocklists %} {% if firewall.block_smtp_out or blocklists %}
# Outbound mail goes through the mail host only. Loopback stays open for a # Outbound mail goes through the mail host only. Loopback stays open for a
@@ -385,7 +368,6 @@ table inet host {
ip daddr @firehol_v4 jump firehol_out ip daddr @firehol_v4 jump firehol_out
ip daddr @firehol_level2_v4 jump firehol_out ip daddr @firehol_level2_v4 jump firehol_out
ip daddr @malware_v4 jump firehol_out
{% endif %} {% endif %}
{% if firewall.block_smtp_out %} {% if firewall.block_smtp_out %}
@@ -474,18 +456,12 @@ table inet host {
ip daddr @firehol_v4 jump firehol_out ip daddr @firehol_v4 jump firehol_out
ip saddr @firehol_level2_v4 jump firehol_in ip saddr @firehol_level2_v4 jump firehol_in
ip daddr @firehol_level2_v4 jump firehol_out ip daddr @firehol_level2_v4 jump firehol_out
ip saddr @malware_v4 jump firehol_in
ip daddr @malware_v4 jump firehol_out
{% endif %} {% endif %}
{% if firewall.scanners %} {% if firewall.scanners %}
ct state new ip saddr @scanners_v4 jump scanners_in ct state new ip saddr @scanners_v4 jump scanners_in
ct state new ip6 saddr @scanners_v6 jump scanners_in ct state new ip6 saddr @scanners_v6 jump scanners_in
{% endif %} {% endif %}
{% if firewall.firehol %}
ct state new ip saddr @bruteforceblocker_v4 jump bruteforceblocker_in
{% endif %}
{% for guard in forward_guard %} {% for guard in forward_guard %}
# {{ guard.key }} # {{ guard.key }}