roles/common: Use Abuse.ch's SSL Blacklist in nftables
This adds Abuse.sh's list of IPs using blacklisted SSL certificates to nftables. These IPs are high confidence indicators of compromise and we should not route them. The list is updated daily by a systemd timer. See: https://sslbl.abuse.ch/blacklist/
This commit is contained in:
parent
cba2a7a996
commit
8dd7663b3c
5
roles/common/files/abusech-ipv4.nft
Normal file
5
roles/common/files/abusech-ipv4.nft
Normal file
@ -0,0 +1,5 @@
|
||||
#!/usr/sbin/nft -f
|
||||
|
||||
define ABUSECH_IPV4 = {
|
||||
192.168.254.254
|
||||
}
|
27
roles/common/files/update-abusech-nftables.service
Normal file
27
roles/common/files/update-abusech-nftables.service
Normal file
@ -0,0 +1,27 @@
|
||||
[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
|
63
roles/common/files/update-abusech-nftables.sh
Executable file
63
roles/common/files/update-abusech-nftables.sh
Executable file
@ -0,0 +1,63 @@
|
||||
#!/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
|
12
roles/common/files/update-abusech-nftables.timer
Normal file
12
roles/common/files/update-abusech-nftables.timer
Normal file
@ -0,0 +1,12 @@
|
||||
[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
|
@ -39,6 +39,7 @@
|
||||
loop:
|
||||
- spamhaus-ipv4.nft
|
||||
- spamhaus-ipv6.nft
|
||||
- abusech-ipv4.nft
|
||||
notify:
|
||||
- reload nftables
|
||||
|
||||
@ -102,20 +103,23 @@
|
||||
loop:
|
||||
- update-spamhaus-nftables.sh
|
||||
- aggregate-cidr-addresses.pl
|
||||
- update-abusech-nftables.sh
|
||||
|
||||
- name: Copy Spamhaus nftables systemd units
|
||||
- name: Copy nftables systemd units
|
||||
when: ansible_distribution_version is version('11', '>=')
|
||||
copy: src={{ item }} dest=/etc/systemd/system/{{ item }} mode=0644 owner=root group=root
|
||||
loop:
|
||||
- update-spamhaus-nftables.service
|
||||
- update-spamhaus-nftables.timer
|
||||
register: spamhaus_nftables_systemd_units
|
||||
- update-abusech-nftables.service
|
||||
- update-abusech-nftables.timer
|
||||
register: nftables_systemd_units
|
||||
|
||||
# need to reload to pick up service/timer/environment changes
|
||||
- name: Reload systemd daemon
|
||||
systemd: daemon_reload=yes
|
||||
when: spamhaus_firewalld_systemd_units is changed or
|
||||
spamhaus_nftables_systemd_units is changed
|
||||
nftables_systemd_units is changed
|
||||
|
||||
- name: Start and enable Spamhaus firewalld update timer
|
||||
when: ansible_distribution_version is version('10', '<=')
|
||||
@ -123,9 +127,12 @@
|
||||
notify:
|
||||
- restart firewalld
|
||||
|
||||
- name: Start and enable Spamhaus nftables update timer
|
||||
- name: Start and enable nftables update timers
|
||||
when: ansible_distribution_version is version('11', '>=')
|
||||
systemd: name=update-spamhaus-nftables.timer state=started enabled=yes
|
||||
systemd: name={{ item }} state=started enabled=yes
|
||||
loop:
|
||||
- update-spamhaus-nftables.timer
|
||||
- update-abusech-nftables.timer
|
||||
|
||||
- name: Start and enable nftables
|
||||
when: ansible_distribution_major_version is version('11', '>=')
|
||||
|
@ -45,6 +45,7 @@
|
||||
loop:
|
||||
- spamhaus-ipv4.nft
|
||||
- spamhaus-ipv6.nft
|
||||
- abusech-ipv4.nft
|
||||
notify:
|
||||
- reload nftables
|
||||
|
||||
@ -81,26 +82,29 @@
|
||||
- update-spamhaus-lists.timer
|
||||
register: spamhaus_firewalld_systemd_units
|
||||
|
||||
- name: Copy Spamhaus nftables update scripts
|
||||
- name: Copy nftables update scripts
|
||||
when: ansible_distribution_version is version('20.04', '>=')
|
||||
copy: src={{ item }} dest=/usr/local/bin/{{ item }} mode=0755 owner=root group=root
|
||||
loop:
|
||||
- update-spamhaus-nftables.sh
|
||||
- aggregate-cidr-addresses.pl
|
||||
- update-abusech-nftables.sh
|
||||
|
||||
- name: Copy Spamhaus nftables systemd units
|
||||
- name: Copy nftables systemd units
|
||||
when: ansible_distribution_version is version('20.04', '>=')
|
||||
copy: src={{ item }} dest=/etc/systemd/system/{{ item }} mode=0644 owner=root group=root
|
||||
loop:
|
||||
- update-spamhaus-nftables.service
|
||||
- update-spamhaus-nftables.timer
|
||||
register: spamhaus_nftables_systemd_units
|
||||
- update-abusech-nftables.service
|
||||
- update-abusech-nftables.timer
|
||||
register: nftables_systemd_units
|
||||
|
||||
# need to reload to pick up service/timer/environment changes
|
||||
- name: Reload systemd daemon
|
||||
systemd: daemon_reload=yes
|
||||
when: spamhaus_firewalld_systemd_units is changed or
|
||||
spamhaus_nftables_systemd_units is changed
|
||||
nftables_systemd_units is changed
|
||||
|
||||
- name: Start and enable Spamhaus firewalld update timer
|
||||
when: ansible_distribution_version is version('18.04', '<=')
|
||||
@ -108,9 +112,12 @@
|
||||
notify:
|
||||
- restart firewalld
|
||||
|
||||
- name: Start and enable Spamhaus nftables update timer
|
||||
- name: Start and enable nftables update timers
|
||||
when: ansible_distribution_version is version('20.04', '>=')
|
||||
systemd: name=update-spamhaus-nftables.timer state=started enabled=yes
|
||||
systemd: name={{ item }} state=started enabled=yes
|
||||
loop:
|
||||
- update-spamhaus-nftables.timer
|
||||
- update-abusech-nftables.timer
|
||||
|
||||
- name: Start and enable nftables
|
||||
when: ansible_distribution_version is version('20.04', '>=')
|
||||
|
@ -9,6 +9,9 @@ flush ruleset
|
||||
include "/etc/nftables/spamhaus-ipv4.nft"
|
||||
include "/etc/nftables/spamhaus-ipv6.nft"
|
||||
|
||||
# Lists updated daily by update-abusech-nftables.sh
|
||||
include "/etc/nftables/abusech-ipv4.nft"
|
||||
|
||||
# Notes:
|
||||
# - tables hold chains, chains hold rules
|
||||
# - inet is for both ipv4 and ipv6
|
||||
@ -26,6 +29,11 @@ table inet filter {
|
||||
elements = $SPAMHAUS_IPV6
|
||||
}
|
||||
|
||||
set abusech-ipv4 {
|
||||
type ipv4_addr
|
||||
elements = $ABUSECH_IPV4
|
||||
}
|
||||
|
||||
chain input {
|
||||
type filter hook input priority 0;
|
||||
|
||||
@ -39,6 +47,9 @@ table inet filter {
|
||||
ip saddr @spamhaus-ipv4 counter drop
|
||||
ip6 saddr @spamhaus-ipv6 counter drop
|
||||
|
||||
# Drop packets matching the abusech set early.
|
||||
ip saddr @abusech-ipv4 counter drop
|
||||
|
||||
# Allow loopback traffic.
|
||||
iifname lo accept
|
||||
|
||||
@ -83,5 +94,8 @@ table inet filter {
|
||||
# Drop outgoing packets matching the spamhaus sets too
|
||||
ip daddr @spamhaus-ipv4 counter drop
|
||||
ip6 daddr @spamhaus-ipv6 counter drop
|
||||
|
||||
# Drop outgoing packets matching the abusech sets too
|
||||
ip daddr @abusech-ipv4 counter drop
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user