Original by Tachtler.
From the Advanced Routing Howto.
Can be used at the start of the script.
# Flush tables iptables -F iptables -X iptables -t nat -F iptables -t nat -X iptables -t mangle -F iptables -t mangle -X
# Block w00tw00t iptables -A INPUT -p tcp --dport 80 -m string --to 70 --algo bm --string 'GET /w00tw00t.at.ISC.SANS.' -j DROP # Block DNS ANY iptables -A INPUT -p udp --dport 53 -m string --from 50 --algo bm --hex-string '|0000FF0001|' -m recent --set --name dnsanyquery iptables -A INPUT -p udp --dport 53 -m string --from 50 --algo bm --hex-string '|0000FF0001|' -m recent --name dnsanyquery --rcheck --seconds 10 --hitcount 3 -j DROP
## Reject packets from RFC1918 class networks (i.e., spoofed) ## Your internal network should be commented, any unused classes ## should be blocked by removing the comment. #iptables -A INPUT -s 169.254.0.0/16 -j DROP #iptables -A INPUT -s 192.168.0.0/16 -j DROP #iptables -A INPUT -s 172.16.0.0/12 -j DROP #iptables -A INPUT -s 127.0.0.0/8 -j DROP iptables -A INPUT -s 224.0.0.0/4 -j DROP iptables -A INPUT -d 224.0.0.0/4 -j DROP iptables -A INPUT -s 240.0.0.0/5 -j DROP iptables -A INPUT -d 240.0.0.0/5 -j DROP #iptables -A INPUT -s 0.0.0.0/8 -j DROP #iptables -A INPUT -d 0.0.0.0/8 -j DROP iptables -A INPUT -d 239.255.255.0/24 -j DROP #iptables -A INPUT -d 255.255.255.255 -j DROP
The following rules should block and limit most packet-related attacks.
# NEW TCP packets must have SYN iptables -A INPUT -p tcp -m state --state NEW ! --syn -j DROP # Block SYN-flood iptables -A INPUT -p tcp -m state --state NEW -m limit --limit 2/second --limit-burst 2 -j ACCEPT # Packet fragments (Teardrop, etc...) iptables -A INPUT --fragment -j DROP # Block Smurf iptables -A INPUT -p icmp -m icmp --icmp-type address-mask-request -j DROP iptables -A INPUT -p icmp -m icmp --icmp-type timestamp-request -j DROP # Ping of Death iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 3/s -m length --length 60:65535 -j ACCEPT iptables -A INPUT -p tcp -m tcp --tcp-flags RST RST -m limit --limit 2/second --limit-burst 2 -j ACCEPT # Block Fraggle iptables -A INPUT -p udp -m pkttype --pkt-type broadcast -j DROP iptables -A INPUT -p udp -m limit --limit 3/s -j ACCEPT # Drop bad TCP flags (XMAS, NULL) iptables -A INPUT -p tcp --tcp-flags ACK,FIN FIN -j DROP iptables -A INPUT -p tcp --tcp-flags ACK,PSH PSH -j DROP iptables -A INPUT -p tcp --tcp-flags ACK,URG URG -j DROP iptables -A INPUT -p tcp --tcp-flags FIN,RST FIN,RST -j DROP iptables -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP iptables -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP iptables -A INPUT -p tcp --tcp-flags ALL FIN,PSH,URG -j DROP iptables -A INPUT -p tcp --tcp-flags ALL SYN,FIN,PSH,URG -j DROP iptables -A INPUT -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP # Drop all invalid packets iptables -A INPUT -m state --state INVALID -j DROP iptables -A FORWARD -m state --state INVALID -j DROP iptables -A OUTPUT -m state --state INVALID -j DROP
You can also increase the recent table size (in this case, to 1000 entries), since on Linux it is fixed to 100 entries:
cat >> /etc/modprobe.d/xt_recent.conf << EOF options xt_recent ip_pkt_list_tot=1000 ip_list_tot=1000 EOF
Brute-force authentication attacks should be mitigated using sshguard that dynamically bans offending connections for most common services. The rule below can be used to limit connections to service ports that do not necessarily involve authentication.
# SERVICE_PORT, SERVICE_CONNECTION_RATE, SERVICE_CONNECTION_RATE_BURST, SERVICE_NAME, EXPIRE_TIME # have to be substituted. Some reasonable values are given in the table below. iptables -t mangle -A PREROUTING -p SERVICE_PROTOCOL --dport SERVICE_PORT -m state --state NEW \ -m hashlimit --hashlimit-above SERVICE_CONNECTION_RATE --hashlimit-burst SERVICE_CONNECTION_RATE_BURST \ --hashlimit-htable-expire EXPIRE_TIME --hashlimit-name SERVICE_NAME --hashlimit-mode srcip -j DROP
Here is a reference of some decent settings:
SERVICE_PORT | SERVICE_PROTOCOL | SERVICE_CONNECTION_RATE | SERVICE_CONNECTION_RATE_BURST | SERVICE_NAME |
---|---|---|---|---|
80 | tcp | 45/sec | 60 | http |
22 | tcp | 5/sec | 7 | ssh |
1723 | tcp | 5/sec | 10 | pptp |
25 | tcp | 5/minute | 10 | smtp |
Note that EXPIRE_TIME
has to be defined and represents the time in milliseconds after which the entries expire.
The reason to perform checking in mangle
on the PREROUTING
chain is that these limits will be enforced before any nat
-ing rules apply. Otherwise if we were to perform the same on the INPUT
chain, only the packets with the current machine as destination would be limited.
For reference, hashlimit
match has the following possible parameters:
--hashlimit-upto max average match rate [Packets per second unless followed by /sec /minute /hour /day postfixes] –hashlimit-above min average match rate –hashlimit-mode mode is a comma-separated list of dstip,srcip,dstport,srcport (or none) –hashlimit-srcmask source address grouping prefix length –hashlimit-dstmask destination address grouping prefix length –hashlimit-name name for /proc/net/ipt_hashlimit –hashlimit-burst number to match in a burst, default 5 –hashlimit-htable-size number of hashtable buckets –hashlimit-htable-max number of hashtable entries –hashlimit-htable-gcinterval interval between garbage collection runs –hashlimit-htable-expire after which time are idle entries expired?
iptables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -o EXTERNAL_IF -j TCPMSS --clamp-mss-to-pmtu iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
where EXTERNAL_IF
should be the external, outbound interface.
NAT
can be detected by ISPs by measuring the TTL
of packets on the network. Every gateway along the path decreases the TTL
so it is easy to determine that NAT
is being used if packets coming from a network have a different TTL
value.
The following rule clamps the TTL to 128
on the OUTPUT
chain:
iptables -t mangle -A OUTPUT -j TTL --ttl-set 128
The string
matcher from iptables
can be used:
iptables -I INPUT 1 -p udp -m string --algo bm --hex-string '|FF FF FF FF FF FF|' -j LOG --log-prefix '[WOL]' --log-level DEBUG
The rule can be made stronger by extending the hex-string with the actual MAC address of the destination machine.
Remember, WOL packets are meant to be received by the machine when it is powered off and that iptables
only works when the machine is powered on. More details about Wake-On-Lan can be found on the wake on lan page.
The TARPIT
target of iptables
(as an analogy to moats around castles) captures and holds incoming TCP connections using no local resources. Connections are accepted and then switched to the persist state (0
byte window) in which the remote side stops sending data and asks to continue every 60
to 270
seconds. Attempts from the remote side to close a connection are ignored wich forces the remote connection to timeout in 12
to 24
minutes.
For example, to tarpit all incoming connections from 134.45.233.16
, you would issue:
iptables -A INPUT -p tcp -s 134.45.233.16 -j TARPIT
Suppose that you have a beachhead on a server with a VPN service on the server that uses an interface and that you would like to restrict any traffic from that interface to the other end of your VPN to a set of users.
A sketch of what you would like to achieve is the following:
where:
Suppose that the interface on the beachhead server is tap0
and that you would like to allow traffic from the beachhead server to your server for the users having the UID (from /etc/passwd
) 0
(root), 1000
(some user), 1001
(some other user).
In that case, we can use ipt_owner
. First, append ipt_owner
to /etc/modules
and then create the following iptables
rules:
iptables -N OUT_TAP0 iptables -A OUTPUT -o tap0 -m owner --uid-owner 0 -j OUT_TAP0 iptables -A OUTPUT -o tap0 -m owner --uid-owner 1000 -j OUT_TAP0 iptables -A OUTPUT -o tap0 -m owner --uid-owner 1001 -j OUT_TAP0 iptables -A OUT_TAP0 -j ACCEPT iptables -A OUTPUT -o tap0 ! -p icmp -j DROP
The rules create a jump table on the OUTPUT
chain that accepts traffic from the processes with UID 0
, 1000
, 1001
and drops all other traffic through tap0
except ICMP
(useful for testing).
The following script pulls a fresh lists of hosts to block from Emerging Threats and adds firewall rules to block the retrieved IPs. The script is re-entry safe - so, suitable to be run via cron. You can drop the script in the /etc/cron.daily
folder and it will recreate the block list every day.
The script relies on the following tools:
ipset
,curl
,egrep
all of which should be available to install via the distribution's package manager.
#!/usr/bin/env bash ########################################################################### ## Copyright (C) Wizardry and Steamworks 2020 - License: GNU GPLv3 ## ########################################################################### # Downloads from emergingthreats.net and adds all the networks to ipset. ## ########################################################################### ## Possible firewall configuration: ## Delete all the old rules. #I=`/sbin/iptables-save | grep -- "-A INPUT -j EMERGING-THREATS"` #O=`/sbin/iptables-save | grep -- "-A OUTPUT -j EMERGING-THREATS"` #if [ ! -z "$I" ] || [ ! -z "$O" ]; then # /sbin/iptables -F EMERGING-THREATS # /sbin/iptables -X EMERGING-THREATS #fi #if [ ! -z "$I" ]; then # /sbin/iptables -D INPUT -j EMERGING-THREATS #fi #if [ ! -z "$O" ]; then # /sbin/iptables -D OUTPUT -j EMERGING-THREATS #fi ## Create the chain again and add all the new rules. #/sbin/iptables -N EMERGING-THREATS #/sbin/iptables -I INPUT 1 -j EMERGING-THREATS #/sbin/iptables -I OUTPUT 1 -j EMERGING-THREATS #/sbin/iptables -A EMERGING-THREATS -p all -m set --match-set EMERGING-THREATS src,dst -j DROP ## Continue with the rest. #/sbin/iptables -A EMERGING-THREATS -j RETURN ########################################################################### `ipset list EMERGING-THREATS 2>/dev/null >/dev/null` if [ $? = 1 ]; then ipset create EMERGING-THREATS hash:net family inet fi ipset flush EMERGING-THREATS for net in `curl -s http://rules.emergingthreats.net/fwrules/emerging-Block-IPs.txt | \ egrep '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/*[0-9]{0,2}'`; do ipset add EMERGING-THREATS $net done
To use, simply copy the script to /etc/cron.hourly
and then insert the iptables
rules at the top into the existing firewall.
The FireHOL level 1 list is a general purpose list that can be used to block various flavours of attacks including ransomeware reported IP addresses. Contrary to the emerging threats list, The FireHOL level 1 list is updated on average every half an hour such that the script presented here is best placed in /etc/cron.hourly
.
The script will additionally filter the FireHOL level 1 list of IPs and networks through a list of private and reserved IPs in order to not block local networks. It uses ipsets for speed and creates a separate chain to keep the iptables rules well organized.
The script relies on the following tools:
ipset
,curl
egrep
,awk
#!/usr/bin/env bash ########################################################################### ## Copyright (C) Wizardry and Steamworks 2020 - License: GNU GPLv3 ## ########################################################################### # Downloads the FireHOL level 1 list and adds all networks to an IP set. ## ########################################################################### ## Possible firewall configuration: ## Delete all the old rules. #I=`/sbin/iptables-save | grep -- "-A INPUT -j FIREHOL-LEVEL1"` #O=`/sbin/iptables-save | grep -- "-A OUTPUT -j FIREHOL-LEVEL1"` #if [ ! -z "$I" ] || [ ! -z "$O" ]; then # /sbin/iptables -F FIREHOL-LEVEL1 # /sbin/iptables -X FIREHOL-LEVEL1 #fi #if [ ! -z "$I" ]; then # /sbin/iptables -D INPUT -j FIREHOL-LEVEL1 #fi #if [ ! -z "$O" ]; then # /sbin/iptables -D OUTPUT -j FIREHOL-LEVEL1 #fi ## Create the chain again and add all the new rules. #/sbin/iptables -N FIREHOL-LEVEL1 #/sbin/iptables -I INPUT 1 -j FIREHOL-LEVEL1 #/sbin/iptables -I OUTPUT 1 -j FIREHOL-LEVEL1 #/sbin/iptables -A FIREHOL-LEVEL1 -p all -m set --match-set FIREHOL-LEVEL1 src,dst -j DROP ## Continue with the rest. #/sbin/iptables -A FIREHOL-LEVEL1 -j RETURN ########################################################################### # Cleanup routine to delete bogon and firehol list on termination. trap '{ # Delete the temporary bogon and firehol lists. for i in $BOGONS_LIST $FIREHOL_LIST; do if [ -f $i ]; then rm $i fi done }' KILL QUIT TERM EXIT INT HUP # Delete current set. `ipset list FIREHOL-LEVEL1 2>/dev/null >/dev/null` if [ $? = 1 ]; then # Create the set. ipset create FIREHOL-LEVEL1 hash:net family inet fi # Flush the existing IPs. ipset flush FIREHOL-LEVEL1 # Generate a list of private subnet IP addresses defined by # RFC 1918, RFC 5735, and RFC 6598. BOGONS_LIST=`mktemp` cat > $BOGONS_LIST <<EOF 0.0.0.0/8 10.0.0.0/8 100.64.0.0/10 127.0.0.0/8 169.254.0.0/16 172.16.0.0/12 192.0.0.0/24 192.0.2.0/24 192.168.0.0/16 198.18.0.0/15 198.51.100.0/24 203.0.113.0/24 224.0.0.0/3 EOF # Download the firehol netset level 1 FIREHOL_LIST=`mktemp` # Force curl to fail for anything other than HTTP 200 curl -q -f -s 'https://iplists.firehol.org/files/firehol_level1.netset' > $FIREHOL_LIST 2>/dev/null # Check that curl completed successfully and that the list is not empty. if [ $? != 0 ] || [ -z $FIREHOL_LIST ]; then echo 'FireHOL Level 1 Netset list could not be downloaded.' exit fi # Filter the firehol netset through the bogon list and also filter out valid # IP and net blocks. Add the results to the created IP set. for net in `awk '{if (f==1) { r[$0] } else if (! ($0 in r)) { print $0 } } ' f=1 $BOGONS_LIST f=2 $FIREHOL_LIST | \ egrep '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/*[0-9]{0,2}'`; do ipset add FIREHOL-LEVEL1 $net done
To use, simply copy the script to /etc/cron.hourly
and then insert the iptables
rules at the top into the existing firewall.
Greensnow is a service that monitors attacks on various services across the internet and updates a list of offenders in real time. The script provided generates an ipset from the IP addresses provided by GreenSnow. The script can be saved to /etc/cron.hourly
in order to update the list of offending IP addresses every hour.
#!/usr/bin/env bash ########################################################################### ## Copyright (C) Wizardry and Steamworks 2024 - License: GNU GPLv3 ## ########################################################################### # Downloads GreenSnow attack IP list and adds all the networks to ipset. ## ########################################################################### ## Possible firewall configuration: ## Delete all the old rules. #I=`/sbin/iptables-save | grep -- "-A INPUT -j GREENSNOW"` #O=`/sbin/iptables-save | grep -- "-A OUTPUT -j GREENSNOW"` #if [ ! -z "$I" ] || [ ! -z "$O" ]; then # /sbin/iptables -F GREENSNOW # /sbin/iptables -X GREENSNOW #fi #if [ ! -z "$I" ]; then # /sbin/iptables -D INPUT -j GREENSNOW #fi #if [ ! -z "$O" ]; then # /sbin/iptables -D OUTPUT -j GREENSNOW #fi ## Create the chain again and add all the new rules. #/sbin/iptables -N GREENSNOW #/sbin/iptables -I INPUT 1 -j GREENSNOW #/sbin/iptables -I OUTPUT 1 -j GREENSNOW #/sbin/iptables -A GREENSNOW -p all -m set --match-set GREENSNOW src,dst -j DROP ## Continue with the rest. #/sbin/iptables -A GREENSNOW -j RETURN ########################################################################### `ipset list GREENSNOW 2>/dev/null >/dev/null` if [ $? = 1 ]; then ipset create GREENSNOW hash:net maxelem 262144 family inet fi ipset flush GREENSNOW while read LINE; do grep -E -vq "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}$" <<< "${LINE}" if [ $? -eq 0 ]; then continue fi printf %s "add GREENSNOW ${LINE}" | ipset restore -exist done <<< $(curl -s -L https://blocklist.greensnow.co/greensnow.txt) </code> ====== Block BotScout Bots ====== [[https://botscout.com/|BotScout]] is an online service that tracks bots that automatically register accounts on various websites or post spam messages. The script below can be copied to ''/etc/cron.hourly'' in order to generate an ipset of all the IP addresses reported by BotScout. <file bash create-botscout-ipset> #!/usr/bin/env bash ########################################################################### ## Copyright (C) Wizardry and Steamworks 2024 - License: GNU GPLv3 ## ########################################################################### # Downloads botscout IP list and adds all the networks to ipset. ## ########################################################################### ## Possible firewall configuration: ## Delete all the old rules. #I=`/sbin/iptables-save | grep -- "-A INPUT -j BOTSCOUT"` #O=`/sbin/iptables-save | grep -- "-A OUTPUT -j BOTSCOUT"` #if [ ! -z "$I" ] || [ ! -z "$O" ]; then # /sbin/iptables -F BOTSCOUT # /sbin/iptables -X BOTSCOUT #fi #if [ ! -z "$I" ]; then # /sbin/iptables -D INPUT -j BOTSCOUT #fi #if [ ! -z "$O" ]; then # /sbin/iptables -D OUTPUT -j BOTSCOUT #fi ## Create the chain again and add all the new rules. #/sbin/iptables -N BOTSCOUT #/sbin/iptables -I INPUT 1 -j BOTSCOUT #/sbin/iptables -I OUTPUT 1 -j BOTSCOUT #/sbin/iptables -A BOTSCOUT -p all -m set --match-set BOTSCOUT src,dst -j DROP ## Continue with the rest. #/sbin/iptables -A BOTSCOUT -j RETURN ########################################################################### `ipset list BOTSCOUT 2>/dev/null >/dev/null` if [ $? = 1 ]; then ipset create BOTSCOUT hash:net maxelem 262144 family inet fi ipset flush BOTSCOUT while read LINE; do grep -E -vq "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}$" <<< "${LINE}" if [ $? -eq 0 ]; then continue fi printf %s "add BOTSCOUT ${LINE}" | ipset restore -exist done <<< $(curl -s -L https://iplists.firehol.org/files/botscout.ipset)
A single rule can be deleted by specifying either:
using the -D
parameter passed to iptables
.
For instance, to remove the IP address 199.233.85.0
contained inside the EMERGING
chain, issue:
iptables -L -n --line-numbers | grep 199.233.85.0 | awk '{ print $1 }' | xargs iptables -D EMERGING
The command will:
iptables
rules (-L
),-n
),–line-numbers
and will then match the IP address 199.233.85.0
and filter out the first number (which will be the rule number) via awk
. The number is then piped into xargs
that will make iptables
delete the rule corresponding to the passed number inside the EMERGING
chain.
A longer variant that lets you specify the IP address on the command line and then takes care to remove that IP address from all the chains is the following procedure:
IP=83.141.2.155
iptables -n -L --line-numbers | \ grep -oP "((?<=Chain\s)(.+?)\s)|(^[0-9]+(?=.+?$IP))" | \ xargs | \ grep -oP '([^\s]+?)\s([0-9]+)' | \ xargs -l sh -c 'iptables -D $0 $1'
Leveraging the pure shell JSON parser, a script can be placed in crontab in order to maintain country IP lists in the form of IP sets.
#!/usr/bin/env bash ########################################################################### ## Copyright (C) Wizardry and Steamworks 2020 - License: GNU GPLv3 ## ########################################################################### # Downloads the IP blocks for selected countries and creates IP sets. ## ########################################################################### ########################################################################### ## CONFIGURATION ## ########################################################################### # Generate IP sets for the following country codes. COUNTRY_CODES=( sv ) ########################################################################### ## INTERNALS ## ########################################################################### JSON_BASH_PARSER=$(cat <<EOF cigpIHsgaWYgWyAtdCAwIF07IHRoZW4gYj0kKHN0dHkgLWcpOyBzdHR5IC1pY2Fub24gLWVjaG8g bWluIDEgdGltZSAwOyBmaTsgYz0kKGRkIGJzPTEgY291bnQ9MSBjb252PW5vZXJyb3Isc3luYyAy Pi9kZXYvbnVsbCk7IGlmIFsgLXQgMCBdOyB0aGVuIHN0dHkgIiRiIjsgZmk7IH07IGUoKSB7IGVj aG8gIiQxPSQyIjsgfTsgYSgpIHsgbG9jYWwgZD0iJHsxOiskMS59JDIiOyBsb2NhbCBmPSJ1Ijsg bG9jYWwgZz0wOyB3aGlsZSBbICIkaCIgLWx0ICIkaiIgXTsgZG8gWyAiJGkiID0gIjAiIF0gJiYg aD0kKChoICsgMSkpICYmIHIgYzsgaT0wOyBjPSR7YzotJyAnfTsgY2FzZSAiJGYiIGluICJ1Iikg Y2FzZSAiJGMiIGluICd7JykgbyAiJGQiICIkZyI7IGY9ImwiOyA7OyAnXScpIHJldHVybjsgOzsg W1widGZURlwtMC05XSkgaT0xOyB2ICIkZCIgIiRnIjsgaT0xOyBmPSJsIjsgOzsgZXNhYyA7OyAi bCIpIFsgIiRjIiA9ICIsIiBdICYmIGc9JCgoZyArIDEpKSAmJiBmPSJ1IjsgWyAiJGMiID0gIl0i IF0gJiYgcmV0dXJuOyA7OyBlc2FjIGRvbmUgfTsgdigpIHsgbG9jYWwgZD0iJHsxOiskMS59JDIi OyBsb2NhbCBmPSJ1Ijsgd2hpbGUgWyAiJGgiIC1sdCAiJGoiIF07IGRvIFsgIiRpIiA9ICIwIiBd ICYmIGg9JCgoaCArIDEpKSAmJiByIGM7IGk9MDsgYz0ke2M6LScgJ307IGNhc2UgIiRmIiBpbiAi dSIpIGNhc2UgIiRjIiBpbiAnIicpIGY9InoiOyBrPSIiOyA7OyBbXC0wLTldKSBmPSJ5Ijsgaz0i JGMiOyA7OyBbdGZURl0pIGY9IngiOyBrPSIkYyI7IDs7ICJbIikgYSAiIiAiJGQiOyByZXR1cm47 IDs7ICJ7IikgbyAiIiAiJGQiOyByZXR1cm47IDs7IGVzYWMgOzsgInoiKSBjYXNlICIkYyIgaW4g JyInKSBbICIkbSIgPSAiMCIgXSAmJiBlICIkZCIgIiRrIiAmJiByZXR1cm47IFsgIiRtIiA9ICIx IiBdICYmIGs9IiRrJGMiICYmIG09MDsgOzsgJ1wnKSBbICIkbSIgPSAiMSIgXSAmJiBrPSIkayRj IjsgbT0kKCgxIC0gbSkpOyA7OyAqKSBtPTA7IGs9IiRrJGMiOyA7OyBlc2FjIDs7ICJ5IikgY2Fz ZSAiJGMiIGluIFssXF19XSkgZSAiJGQiICIkayI7IGk9MTsgcmV0dXJuIDs7IFtcLTAtOS5dKSBr PSIkayRjIjsgOzsgZXNhYyA7OyAieCIpIGNhc2UgIiRjIiBpbiBbLFxdfV0pIGUgIiRkIiAiJGsi OyBpPTE7IHJldHVybjsgOzsgW2EtekEtWl0pIGs9IiRrJGMiOyA7OyBlc2FjIDs7IGVzYWMgZG9u ZSB9OyBvKCkgeyBsb2NhbCBkPSIkezE6KyQxLn0kMiI7IGxvY2FsIGY9InUiOyB3aGlsZSBbICIk aCIgLWx0ICIkaiIgXTsgZG8gWyAiJGkiID0gIjAiIF0gJiYgaD0kKChoICsgMSkpICYmIHIgYzsg aT0wOyBjPSR7YzotJyAnfTsgY2FzZSAiJGYiIGluICJ1IikgWyAiJGMiID0gIn0iIF0gJiYgcmV0 dXJuOyBbICIkYyIgPSAiXCIiIF0gJiYgZj0idyIgJiYgbj0iIiAmJiBtPTA7IDs7ICJ3IikgY2Fz ZSAiJGMiIGluICciJykgWyAiJG0iID0gIjAiIF0gJiYgZj0icCI7IFsgIiRtIiA9ICIxIiBdICYm IG49IiRuJGMiICYmIG09MDsgOzsgJ1wnKSBtPSQoKDEgLSBtKSk7IG49IiRuJGMiOyA7OyAqKSBt PTA7IG49IiRuJGMiOyA7OyBlc2FjIDs7ICJwIikgWyAiJGMiID0gIjoiIF0gJiYgdiAiJGQiICIk biIgJiYgZj0icSI7IDs7ICJxIikgWyAiJGMiID0gJywnIF0gJiYgZj0idSI7IFsgIiRjIiA9ICd9 JyBdICYmIHJldHVybjsgOzsgZXNhYyBkb25lIH07IHMoKSB7IGg9MDsgaT0wOyB3aGlsZSBbICIk aCIgLWx0ICIkaiIgXTsgZG8gciBjOyBjPSR7YzotJyAnfTsgaD0kKChoICsgMSkpOyBbICIkYyIg PSAieyIgXSAmJiBvICIiICIiICYmIHJldHVybjsgWyAiJGMiID0gIlsiIF0gJiYgYSAiIiAiIiAm JiByZXR1cm47IGRvbmUgfTsganNvbigpIHsgaWYgWyAteiAiJEAiIF07IHRoZW4gdD0kKGNhdCAt KTsgZWxzZSB0PSQoZWNobyAiJEAiKTsgZmk7IGo9IiR7I3R9IjsgZWNobyAiJHt0fSIgfCBzOyB9 Cgo= EOF ) eval `printf '%s\n' "$JSON_BASH_PARSER" | base64 -d` for i in ${!COUNTRY_CODES[*]}; do COUNTRY=${COUNTRY_CODES[$i]} # Create or purge IPv4/6 for configured countries. for FAMILY in inet inet6; do SET_NAME=$COUNTRY"-"$FAMILY `ipset list $SET_NAME 2>/dev/null >/dev/null` if [ $? = 1 ]; then ipset create $SET_NAME hash:net family $FAMILY fi ipset flush $SET_NAME done curl -s -o - 'https://stat.ripe.net/data/country-resource-list/data.json?v4_format=prefix;resource='$COUNTRY | \ json | \ while read LINE; do K=$(echo $LINE | awk -F'=' '{ print $1 }') V=$(echo $LINE | awk -F'=' '{ print $2 }') if [ "$K" = "status" ] && [ "$V" != "ok" ]; then for FAMILY in inet inet6; do ipset destroy $COUNTRY"-"$FAMILY 2>/dev/null >/dev/null done continue fi case $( echo "$K" | cut -c 1-19 ) in "data.resources.ipv4") ipset add $COUNTRY"-inet" $V ;; "data.resources.ipv6") ipset add $COUNTRY"-inet6" $V ;; esac done done
The generate-country-ip-sets.sh
script presented above will create 8 separate lists, 2 lists per country for both IPv4 and IPv6 using a list of countries COUNTRY_CODES
adjustable in the configuration section of the script.
PeerBlock is a list of agencies dealing with copyright protection. The following script can be used to create an IP set and batch-block all of them.
#!/usr/bin/env bash ########################################################################### ## Copyright (C) Wizardry and Steamworks 2023 - License: GNU GPLv3 ## ########################################################################### # Downloads peerblock level 1 and adds all the networks to ipset. ## ########################################################################### ## Possible firewall configuration: ## Delete all the old rules. #I=`/sbin/iptables-save | grep -- "-A INPUT -j PEERBLOCK-LEVEL1"` #O=`/sbin/iptables-save | grep -- "-A OUTPUT -j PEERBLOCK-LEVEL1"` #if [ ! -z "$I" ] || [ ! -z "$O" ]; then # /sbin/iptables -F PEERBLOCK-LEVEL1 # /sbin/iptables -X PEERBLOCK-LEVEL1 #fi #if [ ! -z "$I" ]; then # /sbin/iptables -D INPUT -j PEERBLOCK-LEVEL1 #fi #if [ ! -z "$O" ]; then # /sbin/iptables -D OUTPUT -j PEERBLOCK-LEVEL1 #fi ## Create the chain again and add all the new rules. #/sbin/iptables -N PEERBLOCK-LEVEL1 #/sbin/iptables -I INPUT 1 -j PEERBLOCK-LEVEL1 #/sbin/iptables -I OUTPUT 1 -j PEERBLOCK-LEVEL1 #/sbin/iptables -A PEERBLOCK-LEVEL1 -p all -m set --match-set PEERBLOCK-LEVEL1 src,dst -j DROP ## Continue with the rest. #/sbin/iptables -A PEERBLOCK-LEVEL1 -j RETURN ########################################################################### `ipset list PEERBLOCK-LEVEL1 2>/dev/null >/dev/null` if [ $? = 1 ]; then ipset create PEERBLOCK-LEVEL1 hash:net maxelem 262144 family inet fi ipset flush PEERBLOCK-LEVEL1 curl -s -L "http://list.iblocklist.com/?list=bt_level1&fileformat=p2p&archiveformat=gz" -o - | gunzip | cut -d: -f2 | grep -E "^[-0-9.]+$" | awk '{print "add PEERBLOCK-LEVEL1 "$1}' | ipset restore -exist
Ideally, this script could be placed in /etc/cron.daily
in order to daily refresh the set of IPs.
On Debian, the procedure to obtain the geoip
iptables
module is to install the packages:
xtables-addons-dkms
,xtables-addons-common
,libtext-csv-xs-perl
With the packages installed, there are some tools under /usr/lib/exec/xtables-addons
that can be used to both download a geoip database as well as create the necessary mappings in order to be able to block countries. The tools are the following:
xt_geoip_dl
,xt_geoip_build
and:
xt_geoip_dl_maxmind
,xt_geoip_build_maxmind
and can be used in pairs in order to generate a database for iptables
. The procedure is to first issue:
xt_geoip_dl
in order to download a database, followed by:
xt_geoip_build
in order to build the lookup table for the iptables
geoip
module.
Note that xt_geoip_dl_maxmind
will require a license file to be supplies as the first parameter in order to download the MaxMind database.
The last command, xt_geoip_build
will generate iv4
and iv6
files in the current directory and they will have to be moved into /usr/share/xt_geoip/
:
mkdir -p /usr/share/xt_geoip/ mv *.iv4 *.iv6 /usr/share/xt_geoip