roles/common: rework firewall
Use firehol instead of all the others. AbuseIPDB.com can't be upd- ated automatically, Abuse.ch is no longer maintained, and Spamhaus is already in firehol.
This commit is contained in:
parent
5312dc6bd5
commit
5b1530fa91
File diff suppressed because it is too large
Load Diff
@ -1,5 +0,0 @@
|
||||
#!/usr/sbin/nft -f
|
||||
|
||||
define ABUSEIPDB_IPV6 = {
|
||||
fd21:3523:74e0:7301::
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# aggregate-cidr-addresses - combine a list of CIDR address blocks
|
||||
# Copyright (C) 2001,2007 Mark Suter <suter@zwitterion.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see L<http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# [MJS 22 Oct 2001] Aggregate CIDR addresses
|
||||
# [MJS 9 Oct 2007] Overlap idea from Anthony Ledesma at theplanet dot com.
|
||||
# [MJS 16 Feb 2012] Prompted to clarify license by Alexander Talos-Zens - at at univie dot ac dot at
|
||||
# [MJS 21 Feb 2012] IPv6 fixes by Alexander Talos-Zens
|
||||
# [MJS 21 Feb 2012] Split ranges into prefixes (fixes a 10+ year old bug)
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use English qw( -no_match_vars );
|
||||
use Net::IP;
|
||||
|
||||
## Read in all the IP addresses
|
||||
my @addrs = map { Net::IP->new($_) or die "$PROGRAM_NAME: Not an IP: \"$_\"."; }
|
||||
map { / \A \s* (.+?) \s* \Z /msix and $1; } <>;
|
||||
|
||||
## Split any ranges into prefixes
|
||||
@addrs = map {
|
||||
defined $_->prefixlen ? $_ : map { Net::IP->new($_) }
|
||||
$_->find_prefixes
|
||||
} @addrs;
|
||||
|
||||
## Sort the IP addresses
|
||||
@addrs = sort { $a->version <=> $b->version or $a->bincomp( 'lt', $b ) ? -1 : $a->bincomp( 'gt', $b ) ? 1 : 0 } @addrs;
|
||||
|
||||
## Handle overlaps
|
||||
my $count = 0;
|
||||
my $current = $addrs[0];
|
||||
foreach my $next ( @addrs[ 1 .. $#addrs ] ) {
|
||||
my $r = $current->overlaps($next);
|
||||
if ( $current->version != $next->version or $r == $IP_NO_OVERLAP ) {
|
||||
$current = $next;
|
||||
$count++;
|
||||
}
|
||||
elsif ( $r == $IP_A_IN_B_OVERLAP ) {
|
||||
$current = $next;
|
||||
splice @addrs, $count, 1;
|
||||
}
|
||||
elsif ( $r == $IP_B_IN_A_OVERLAP or $r == $IP_IDENTICAL ) {
|
||||
splice @addrs, $count + 1, 1;
|
||||
}
|
||||
else {
|
||||
die "$PROGRAM_NAME: internal error - overlaps() returned an unexpected value!\n";
|
||||
}
|
||||
}
|
||||
|
||||
## Keep aggregating until we don't change anything
|
||||
my $change = 1;
|
||||
while ($change) {
|
||||
$change = 0;
|
||||
my @new_addrs = ();
|
||||
$current = $addrs[0];
|
||||
foreach my $next ( @addrs[ 1 .. $#addrs ] ) {
|
||||
if ( my $total = $current->aggregate($next) ) {
|
||||
$current = $total;
|
||||
$change = 1;
|
||||
}
|
||||
else {
|
||||
push @new_addrs, $current;
|
||||
$current = $next;
|
||||
}
|
||||
}
|
||||
push @new_addrs, $current;
|
||||
@addrs = @new_addrs;
|
||||
}
|
||||
|
||||
## Print out the IP addresses
|
||||
foreach (@addrs) {
|
||||
print $_->prefix(), "\n";
|
||||
}
|
||||
|
||||
# $Id: aggregate-cidr-addresses,v 1.9 2012/02/21 10:14:22 suter Exp suter $
|
@ -1,5 +1,5 @@
|
||||
#!/usr/sbin/nft -f
|
||||
|
||||
define SPAMHAUS_IPV4 = {
|
||||
define FIREHOL_LEVEL1_IPV4 = {
|
||||
192.168.254.254/32
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
#!/usr/sbin/nft -f
|
||||
|
||||
define SPAMHAUS_IPV6 = {
|
||||
fd21:3523:74e0:7301::/64
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
[Unit]
|
||||
Description=Update Abuse.ch SSL Blacklist IPs
|
||||
# This service will fail if nftables is not running so we use Requires to make
|
||||
# sure that nftables is started.
|
||||
Requires=nftables.service
|
||||
# Make sure the network is up and nftables is started
|
||||
After=network-online.target nftables.service
|
||||
Wants=network-online.target update-abusech-nftables.timer
|
||||
|
||||
[Service]
|
||||
# https://www.ctrl.blog/entry/systemd-service-hardening.html
|
||||
# Doesn't need access to /home or /root
|
||||
ProtectHome=true
|
||||
# Possibly only works on Ubuntu 18.04+
|
||||
ProtectKernelTunables=true
|
||||
ProtectSystem=full
|
||||
# Newer systemd can use ReadWritePaths to list files, but this works everywhere
|
||||
ReadWriteDirectories=/etc/nftables
|
||||
PrivateTmp=true
|
||||
WorkingDirectory=/var/tmp
|
||||
|
||||
SyslogIdentifier=update-abusech-nftables
|
||||
ExecStart=/usr/bin/flock -x update-abusech-nftables.lck \
|
||||
/usr/local/bin/update-abusech-nftables.sh
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
@ -1,63 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# update-abuseipdb-nftables.sh v0.0.1
|
||||
#
|
||||
# Download IP addresses seen using a blacklisted SSL certificate and load them
|
||||
# into nftables sets. As of 2021-07-28 these appear to only be IPv4.
|
||||
#
|
||||
# See: https://sslbl.abuse.ch/blacklist
|
||||
#
|
||||
# Copyright (C) 2021 Alan Orth
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
# Exit on first error
|
||||
set -o errexit
|
||||
|
||||
abusech_ipv4_set_path=/etc/nftables/abusech-ipv4.nft
|
||||
abusech_list_temp=$(mktemp)
|
||||
|
||||
echo "Downloading Abuse.sh SSL Blacklist IPs"
|
||||
|
||||
abusech_response=$(curl -s -G -w "%{http_code}\n" https://sslbl.abuse.ch/blacklist/sslipblacklist.txt --output "$abusech_list_temp")
|
||||
|
||||
if [[ $abusech_response -ne 200 ]]; then
|
||||
echo "Abuse.ch responded: HTTP $abusech_response"
|
||||
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -f "$abusech_list_temp" ]]; then
|
||||
echo "Processing IPv4 list"
|
||||
|
||||
abusech_ipv4_list_temp=$(mktemp)
|
||||
abusech_ipv4_set_temp=$(mktemp)
|
||||
|
||||
# Remove comments, DOS carriage returns, and IPv6 addresses (even though
|
||||
# Abuse.ch seems to only have IPv4 addresses, let's not break our shit on
|
||||
# that assumption some time down the line).
|
||||
sed -e '/#/d' -e 's/
//' -e '/:/d' "$abusech_list_temp" > "$abusech_ipv4_list_temp"
|
||||
|
||||
echo "Building abusech-ipv4 set"
|
||||
cat << NFT_HEAD > "$abusech_ipv4_set_temp"
|
||||
#!/usr/sbin/nft -f
|
||||
|
||||
define ABUSECH_IPV4 = {
|
||||
NFT_HEAD
|
||||
|
||||
while read -r network; do
|
||||
# nftables doesn't mind if the last element in the set has a trailing
|
||||
# comma so we don't need to do anything special here.
|
||||
echo "$network," >> "$abusech_ipv4_set_temp"
|
||||
done < $abusech_ipv4_list_temp
|
||||
|
||||
echo "}" >> "$abusech_ipv4_set_temp"
|
||||
|
||||
install -m 0600 "$abusech_ipv4_set_temp" "$abusech_ipv4_set_path"
|
||||
|
||||
rm -f "$abusech_list_temp" "$abusech_ipv4_list_temp" "$abusech_ipv4_set_temp"
|
||||
fi
|
||||
|
||||
echo "Reloading nftables"
|
||||
# The abusech nftables sets are included by nftables.conf
|
||||
/usr/sbin/nft -f /etc/nftables.conf
|
@ -1,12 +0,0 @@
|
||||
[Unit]
|
||||
Description=Update Abuse.ch SSL Blacklist IPs
|
||||
|
||||
[Timer]
|
||||
# Once a day at midnight
|
||||
OnCalendar=*-*-* 00:00:00
|
||||
# Add a random delay of 0–3600 seconds
|
||||
RandomizedDelaySec=3600
|
||||
Persistent=true
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
@ -1,11 +1,11 @@
|
||||
[Unit]
|
||||
Description=Update Spamhaus lists
|
||||
Description=Update FireHOL lists
|
||||
# This service will fail if nftables is not running so we use Requires to make
|
||||
# sure that nftables is started.
|
||||
Requires=nftables.service
|
||||
# Make sure the network is up and nftables is started
|
||||
After=network-online.target nftables.service
|
||||
Wants=network-online.target update-spamhaus-nftables.timer
|
||||
Wants=network-online.target update-firehol-nftables.timer
|
||||
|
||||
[Service]
|
||||
# https://www.ctrl.blog/entry/systemd-service-hardening.html
|
||||
@ -19,9 +19,9 @@ ReadWriteDirectories=/etc/nftables
|
||||
PrivateTmp=true
|
||||
WorkingDirectory=/var/tmp
|
||||
|
||||
SyslogIdentifier=update-spamhaus-nftables
|
||||
ExecStart=/usr/bin/flock -x update-spamhaus-nftables.lck \
|
||||
/usr/local/bin/update-spamhaus-nftables.sh
|
||||
SyslogIdentifier=update-firehol-nftables
|
||||
ExecStart=/usr/bin/flock -x update-firehol-nftables.lck \
|
||||
/usr/local/bin/update-firehol-nftables.sh
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
@ -1,5 +1,5 @@
|
||||
[Unit]
|
||||
Description=Update Spamhaus lists
|
||||
Description=Update FireHOL lists
|
||||
|
||||
[Timer]
|
||||
# Once a day at midnight
|
@ -1,91 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# update-spamhaus-nftables.sh v0.0.1
|
||||
#
|
||||
# Download Spamhaus DROP lists and load them into nftables sets.
|
||||
#
|
||||
# See: https://www.spamhaus.org/drop/
|
||||
#
|
||||
# Copyright (C) 2021 Alan Orth
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
# Exit on first error
|
||||
set -o errexit
|
||||
|
||||
spamhaus_ipv4_set_path=/etc/nftables/spamhaus-ipv4.nft
|
||||
spamhaus_ipv6_set_path=/etc/nftables/spamhaus-ipv6.nft
|
||||
|
||||
function download() {
|
||||
echo "Downloading $1"
|
||||
wget -q -O - "https://www.spamhaus.org/drop/$1" > "$1"
|
||||
}
|
||||
|
||||
download drop.txt
|
||||
download edrop.txt
|
||||
download dropv6.txt
|
||||
|
||||
if [[ -f "drop.txt" && -f "edrop.txt" ]]; then
|
||||
echo "Processing IPv4 DROP lists"
|
||||
|
||||
spamhaus_ipv4_list_temp=$(mktemp)
|
||||
spamhaus_ipv4_set_temp=$(mktemp)
|
||||
|
||||
# Extract all networks from drop.txt and edrop.txt, skipping blank lines and
|
||||
# comments. Use aggregate-cidr-addresses.pl to merge overlapping IPv4 CIDR
|
||||
# ranges to work around a firewalld bug.
|
||||
#
|
||||
# See: https://bugzilla.redhat.com/show_bug.cgi?id=1836571
|
||||
cat drop.txt edrop.txt | sed -e '/^$/d' -e '/^;.*/d' -e 's/[[:space:]];[[:space:]].*//' | aggregate-cidr-addresses.pl > "$spamhaus_ipv4_list_temp"
|
||||
|
||||
echo "Building spamhaus-ipv4 set"
|
||||
cat << NFT_HEAD > "$spamhaus_ipv4_set_temp"
|
||||
#!/usr/sbin/nft -f
|
||||
|
||||
define SPAMHAUS_IPV4 = {
|
||||
NFT_HEAD
|
||||
|
||||
while read -r network; do
|
||||
# nftables doesn't mind if the last element in the set has a trailing
|
||||
# comma so we don't need to do anything special here.
|
||||
echo "$network," >> "$spamhaus_ipv4_set_temp"
|
||||
done < $spamhaus_ipv4_list_temp
|
||||
|
||||
echo "}" >> "$spamhaus_ipv4_set_temp"
|
||||
|
||||
install -m 0600 "$spamhaus_ipv4_set_temp" "$spamhaus_ipv4_set_path"
|
||||
|
||||
rm -f "$spamhaus_ipv4_list_temp" "$spamhaus_ipv4_set_temp"
|
||||
fi
|
||||
|
||||
if [[ -f "dropv6.txt" ]]; then
|
||||
echo "Processing IPv6 DROP lists"
|
||||
|
||||
spamhaus_ipv6_list_temp=$(mktemp)
|
||||
spamhaus_ipv6_set_temp=$(mktemp)
|
||||
|
||||
sed -e '/^$/d' -e '/^;.*/d' -e 's/[[:space:]];[[:space:]].*//' dropv6.txt > "$spamhaus_ipv6_list_temp"
|
||||
|
||||
echo "Building spamhaus-ipv6 set"
|
||||
cat << NFT_HEAD > "$spamhaus_ipv6_set_temp"
|
||||
#!/usr/sbin/nft -f
|
||||
|
||||
define SPAMHAUS_IPV6 = {
|
||||
NFT_HEAD
|
||||
|
||||
while read -r network; do
|
||||
echo "$network," >> "$spamhaus_ipv6_set_temp"
|
||||
done < $spamhaus_ipv6_list_temp
|
||||
|
||||
echo "}" >> "$spamhaus_ipv6_set_temp"
|
||||
|
||||
install -m 0600 "$spamhaus_ipv6_set_temp" "$spamhaus_ipv6_set_path"
|
||||
|
||||
rm -f "$spamhaus_ipv6_list_temp" "$spamhaus_ipv6_set_temp"
|
||||
fi
|
||||
|
||||
echo "Reloading nftables"
|
||||
# The spamhaus nftables sets are included by nftables.conf
|
||||
/usr/sbin/nft -f /etc/nftables.conf
|
||||
|
||||
rm -v drop.txt edrop.txt dropv6.txt
|
@ -5,47 +5,18 @@
|
||||
|
||||
flush ruleset
|
||||
|
||||
# Lists updated daily by update-spamhaus-nftables.sh
|
||||
include "/etc/nftables/spamhaus-ipv4.nft"
|
||||
include "/etc/nftables/spamhaus-ipv6.nft"
|
||||
|
||||
# Lists updated monthly (manually)
|
||||
include "/etc/nftables/abuseipdb-ipv4.nft"
|
||||
include "/etc/nftables/abuseipdb-ipv6.nft"
|
||||
|
||||
# Lists updated daily by update-abusech-nftables.sh
|
||||
include "/etc/nftables/abusech-ipv4.nft"
|
||||
# List updated daily by update-firehol-nftables.sh
|
||||
include "/etc/nftables/firehol_level1-ipv4.nft"
|
||||
|
||||
# Notes:
|
||||
# - tables hold chains, chains hold rules
|
||||
# - inet is for both ipv4 and ipv6
|
||||
table inet filter {
|
||||
set spamhaus-ipv4 {
|
||||
set firehol_level1-ipv4 {
|
||||
type ipv4_addr
|
||||
# if the set contains prefixes we need to use the interval flag
|
||||
flags interval
|
||||
elements = $SPAMHAUS_IPV4
|
||||
}
|
||||
|
||||
set spamhaus-ipv6 {
|
||||
type ipv6_addr
|
||||
flags interval
|
||||
elements = $SPAMHAUS_IPV6
|
||||
}
|
||||
|
||||
set abusech-ipv4 {
|
||||
type ipv4_addr
|
||||
elements = $ABUSECH_IPV4
|
||||
}
|
||||
|
||||
set abuseipdb-ipv4 {
|
||||
type ipv4_addr
|
||||
elements = $ABUSEIPDB_IPV4
|
||||
}
|
||||
|
||||
set abuseipdb-ipv6 {
|
||||
type ipv6_addr
|
||||
elements = $ABUSEIPDB_IPV6
|
||||
elements = $FIREHOL_LEVEL1_IPV4
|
||||
}
|
||||
|
||||
chain input {
|
||||
@ -55,13 +26,7 @@ table inet filter {
|
||||
|
||||
ct state invalid counter drop comment "Early drop of invalid connections"
|
||||
|
||||
ip saddr @spamhaus-ipv4 counter drop comment "Early drop of incoming packets matching spamhaus-ipv4 list"
|
||||
ip6 saddr @spamhaus-ipv6 counter drop comment "Early drop of incoming packets matching spamhaus-ipv6 list"
|
||||
|
||||
ip saddr @abusech-ipv4 counter drop comment "Early drop of packets matching abusech-ipv4 list"
|
||||
|
||||
ip saddr @abuseipdb-ipv4 counter drop comment "Early drop of incoming packets matching abuseipdb-ipv4 list"
|
||||
ip6 saddr @abuseipdb-ipv6 counter drop comment "Early drop of incoming packets matching abuseipdb-ipv6 list"
|
||||
ip saddr @firehol_level1-ipv4 counter drop comment "Early drop of incoming packets matching firehol_level1-ipv4 list"
|
||||
|
||||
iifname lo accept comment "Allow from loopback"
|
||||
|
||||
@ -105,12 +70,6 @@ table inet filter {
|
||||
chain output {
|
||||
type filter hook output priority 0;
|
||||
|
||||
ip daddr @spamhaus-ipv4 counter drop comment "Drop outgoing packets matching spamhaus-ipv4 list"
|
||||
ip6 daddr @spamhaus-ipv6 counter drop comment "Drop outgoing packets matching spamhaus-ipv6 list"
|
||||
|
||||
ip daddr @abusech-ipv4 counter drop comment "Drop outgoing packets matching abusech-ipv4 list"
|
||||
|
||||
ip daddr @abuseipdb-ipv4 counter drop comment "Drop outgoing packets matching abuseipdb-ipv4 list"
|
||||
ip6 daddr @abuseipdb-ipv6 counter drop comment "Drop outgoing packets matching abuseipdb-ipv6 list"
|
||||
ip daddr @firehol_level1-ipv4 counter drop comment "Drop outgoing packets matching firehol_level1-ipv4 list"
|
||||
}
|
||||
}
|
||||
|
67
roles/common/templates/update-firehol-nftables.sh.j2
Executable file
67
roles/common/templates/update-firehol-nftables.sh.j2
Executable file
@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# update-firehol-nftables.sh v0.0.1
|
||||
#
|
||||
# Download FireHOL lists and load them into nftables sets.
|
||||
#
|
||||
# See: https://iplists.firehol.org/
|
||||
#
|
||||
# Copyright (C) 2025 Alan Orth
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
# Exit on first error
|
||||
set -o errexit
|
||||
|
||||
firehol_level1_ipv4_set_path=/etc/nftables/firehol_level1-ipv4.nft
|
||||
|
||||
function download() {
|
||||
echo "Downloading $1"
|
||||
wget -q -O - "https://iplists.firehol.org/files/$1" > "$1"
|
||||
}
|
||||
|
||||
download firehol_level1.netset
|
||||
|
||||
if [[ -f "firehol_level1.netset" ]]; then
|
||||
echo "Processing FireHOL Level 1 list"
|
||||
|
||||
firehol_level1_ipv4_list_temp=$(mktemp)
|
||||
firehol_level1_ipv4_set_temp=$(mktemp)
|
||||
|
||||
# Filter blank lines and comments
|
||||
cat firehol_level1.netset \
|
||||
| sed \
|
||||
-e '/^$/d' \
|
||||
-e '/^#.*/d' \
|
||||
> "$firehol_level1_ipv4_list_temp"
|
||||
|
||||
echo "Building firehol_level1-ipv4 set"
|
||||
cat << NFT_HEAD > "$firehol_level1_ipv4_set_temp"
|
||||
#!/usr/sbin/nft -f
|
||||
|
||||
define FIREHOL_LEVEL1_IPV4 = {
|
||||
NFT_HEAD
|
||||
|
||||
while read -r network; do
|
||||
# nftables doesn't mind if the last element in the set has a trailing
|
||||
# comma so we don't need to do anything special here.
|
||||
echo "$network," >> "$firehol_level1_ipv4_set_temp"
|
||||
done < $firehol_level1_ipv4_list_temp
|
||||
|
||||
echo "}" >> "$firehol_level1_ipv4_set_temp"
|
||||
|
||||
install -m 0600 "$firehol_level1_ipv4_set_temp" "$firehol_level1_ipv4_set_path"
|
||||
|
||||
rm -f "$firehol_level1_ipv4_list_temp" "$firehol_level1_ipv4_set_temp"
|
||||
fi
|
||||
|
||||
echo "Reloading nftables"
|
||||
{% if ansible_distribution == 'Ubuntu' and ansible_distribution_version is version('20.04', '<=') %}
|
||||
{% set systemctl_bin = '/bin/systemctl' %}
|
||||
{% else %}
|
||||
{% set systemctl_bin = '/usr/bin/systemctl' %}
|
||||
{% endif -%}
|
||||
|
||||
{{ systemctl_bin }} reload nftables.service
|
||||
|
||||
rm -v firehol_level1.netset
|
Loading…
x
Reference in New Issue
Block a user