Insane Iptables examples that make nearly everything possible

Image: Pixabay

While trying to create my Docker compatible Iptables firewall sptables, I have realized the power of Iptables once again.

Iptables, with its extensions, is powerful enough to handle “most of” the complex situations that any Iptables wrapper can handle, including any daemons that inspect syslog and do some magical stuff. Solutions to many pre-defined issues could be easily implemented using just pure Iptables rules.

I have implemented my own Docker compatible Iptables rules that include some pre-defined protection patterns and examples including DoS/DDoS mitigation, connection limiting (even some kind of ssh bruteforce protection), port scanning protection, ping limitation, detecting port knocking patterns, blacklisting with timeout support etc… These are all implemented with pure Iptables rules.

Especially I have been impressed alot after seeing that, port scanning, or even port knocking can be implemented with pure Iptables. No need for an always running script, no need for a daemon. Long live Iptables!

Writing rules for Iptables was just like writing code. The following quotes are configuration snippets from sptables, explaining some example situations. The following snippets and sptables are licensed under the 2-Clause BSD License, given at the link.

Limit ping requests per IP:

# Allow & rate limit Ping. Limit IP to 3 echo-request packets per 2 seconds.
-A ICMP -p icmp --icmp-type echo-request -m recent --update --seconds 2 --hitcount 3 -j DROP
-A ICMP -p icmp --icmp-type echo-request -m recent --set -j RETURN

This is the real per IP ping limitation in exchange for some recent module resource usage. Unlike some recommendations could be found on various forums, “limit” module is not the way to go unless you need a global limit.

Block portscan with pure Iptables:

# Block portscan attempts. Detect IP trying to connect more than 6 different ports in one minute, 
# add IP to blacklist if limit is exceeded. (Change --hashlimit-srcmask from 32 to 24 to limit the full Class C network)
# This portscan protection consists of two hashlimit parameters and one blacklist ipset. 
# Even the first hashlimit part could be rewritten with ipset, but the project have 4 basic ipsets and I do not want to sacrifice simplicity currently.
# Besides, instead of assigning resources to port scanners with hashlimit, you can also consider using alternative solutions of various situations (like preventing SSH port with IP limitation etc...)

-A INPUT-FILTERS -m conntrack --ctstate NEW -m hashlimit ! --hashlimit-above 1/minute --hashlimit-burst 1 --hashlimit-mode srcip,dstport --hashlimit-name scanport --hashlimit-srcmask 32 --hashlimit-htable-expire 60000 -m hashlimit --hashlimit-above 1/minute --hashlimit-burst 6 --hashlimit-mode srcip --hashlimit-name portscanner --hashlimit-srcmask 32 --hashlimit-htable-expire 60000 -j PORTSCAN
-A PORTSCAN -j SET --add-set blacklist src --exist --timeout 3600
-A PORTSCAN -m limit --limit 3/minute --limit-burst 5 -j LOG --log-prefix "sptables:PORTSCAN:" --log-level 4
-A PORTSCAN -j DROP

Limit the number of parallel connections per IP for HTTP and HTTPS ports:

# Limit the number of parallel connections per IP for HTTP and HTTPS ports, 
# add IP to blacklist if limit is exceeded. Limit IP for 100 parallel connections, blacklist for 3600 seconds. (Change --connlimit-mask from 32 to 24 to limit the full Class C network)

-A INPUT-FILTERS -p tcp -m multiport --dports 80,443 -m connlimit --connlimit-above 100 --connlimit-mask 32 -j SET --add-set blacklist src --exist --timeout 3600 
-A INPUT-FILTERS -p tcp -m multiport --dports 80,443 -m connlimit --connlimit-above 100 --connlimit-mask 32 -m limit --limit 3/minute --limit-burst 5 -j LOG --log-prefix "sptables:CONNLIMIT:" --log-level 4
-A INPUT-FILTERS -p tcp -m multiport --dports 80,443 -m connlimit --connlimit-above 100 --connlimit-mask 32 -j DROP

Limit the number of new connection attempts per IP for SSH port:

# Limit the number of new connection attempts per IP for SSH port, add IP to blacklist if limit is exceeded (recent module example). 
# Limit IP for 10 new SSH connections per 60 seconds, blacklist for 3600 seconds.

-A INPUT-FILTERS -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --update --name ssh1 --reap --seconds 60 --hitcount 10 -j NEWCONN
-A INPUT-FILTERS -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --set --name ssh1
-A NEWCONN -j SET --add-set blacklist src --exist --timeout 3600
-A NEWCONN -m limit --limit 3/minute --limit-burst 5 -j LOG --log-prefix "sptables:NEWCONN:" --log-level 4
-A NEWCONN -j DROP

Limit the number of new connection attempts per IP for SSH port:

(This is the example of the same thing with hashlimit module)

# Limit the number of new connection attempts per IP for SSH port, add IP to blacklist if limit is exceeded (hashlimit module example). Limit IP for 10 new SSH connections per minute, blacklist for 3600 seconds. 
# (Change --hashlimit-srcmask from 32 to 24 to limit the full Class C network)

-A INPUT-FILTERS -p tcp --dport 22 -m conntrack --ctstate NEW -m hashlimit --hashlimit-name ssh1 --hashlimit-above 10/minute --hashlimit-burst 5 --hashlimit-mode srcip --hashlimit-srcmask 32 -j NEWCONN
-A NEWCONN -j SET --add-set blacklist src --exist --timeout 3600
-A NEWCONN -m limit --limit 3/minute --limit-burst 5 -j LOG --log-prefix "sptables:NEWCONN:" --log-level 4
-A NEWCONN -j DROP

Limit the number of new connection attempts per IP for HTTP, HTTPS ports:

# Limit the number of new connection attempts per IP for HTTP, HTTPS port, add IP to blacklist if limit is exceeded (hashlimit module example). Limit IP for 100 new HTTP, HTTPS connections per minute, blacklist for 3600 seconds. 
# (Change --hashlimit-srcmask from 32 to 24 to limit the full Class C network)

-A INPUT-FILTERS -p tcp -m multiport --dports 80,443 -m conntrack --ctstate NEW -m hashlimit --hashlimit-name http1 --hashlimit-above 100/minute --hashlimit-burst 120 --hashlimit-mode srcip --hashlimit-srcmask 32 -j NEWCONN
#-A INPUT-FILTERS -p tcp -m multiport --dports 80,443 -m conntrack --ctstate NEW -m hashlimit --hashlimit-name http2 --hashlimit-above 3000/hour --hashlimit-burst 3000 --hashlimit-mode srcip --hashlimit-srcmask 32 -j NEWCONN
-A NEWCONN -j SET --add-set blacklist src --exist --timeout 3600
-A NEWCONN -m limit --limit 3/minute --limit-burst 5 -j LOG --log-prefix "sptables:NEWCONN:" --log-level 4
-A NEWCONN -j DROP

Port knocking example implemented in pure Iptables:

# Port knocking example implemented in pure Iptables. Open example hidden SSH port 2222 if the sequence 3333,4444,5555 
# is received within a timeout of 5 seconds for each. Keep port 2222 open for 600 seconds of inactivity.

-A INPUT-FILTERS -p tcp --dport 2222 -m conntrack --ctstate ESTABLISHED,RELATED -m recent --name knock-open --set -j ACCEPT
-A INPUT-FILTERS -p tcp --dport 2222 -m conntrack --ctstate NEW -m recent --name knock-open --update --seconds 600 --reap -j ACCEPT
-A INPUT-FILTERS -p tcp -m conntrack --ctstate NEW -j KNOCK
-A KNOCK -p tcp --dport 3333 -m recent --name knock1 ! --rcheck --seconds 5 --reap -m recent --set --name knock1 -j RETURN
-A KNOCK -p tcp --dport 4444 -m recent --name knock1 --rcheck --seconds 5 --reap -m recent --name knock1 --remove -m recent --set --name knock2 -j RETURN
-A KNOCK -p tcp --dport 5555 -m recent --name knock2 --rcheck --seconds 5 --reap -m recent --name knock2 --remove -m recent --set --name knock3 -j RETURN
-A KNOCK -p tcp -m recent --name knock1 --remove
-A KNOCK -p tcp -m recent --name knock2 --remove
-A INPUT-FILTERS -p tcp --dport 5555 -m conntrack --ctstate NEW -m recent --name knock3 --remove -m recent --set --name knock-open -m limit --limit 3/min --limit-burst 5 -j LOG --log-prefix "sptables:KNOCK:" --log-level 4

And, finally the blacklist snippet with Iptables and Ipset:

# If the attacker tries again before the timeout, update blacklist timeout to 3600 seconds and drop the packet 

-A BLACKLIST -j SET --add-set blacklist src --exist --timeout 3600
-A BLACKLIST -m limit --limit 3/minute --limit-burst 5 -j LOG --log-prefix "sptables:BLACKLIST:" --log-level 4
-A BLACKLIST -j DROP

This blacklist is used in conjunction with all the other rules above to block the attacker until the timeout.

Of course we have to create a set named blacklist before starting:

ipset create blacklist hash:net family inet hashsize 1024 maxelem 65536 timeout 3600

The above directives were just some configuration snippets from sptables written for documentary purposes. sptables is licensed under the 2-Clause BSD License, given in the link.

Source: https://volkan.xyz

 

You can share this blog post only by giving appropriate credit as described at Terms & Conditions.

 

Leave a Reply

Your email address will not be published. Required fields are marked *