We are going to use a combination of lists created by the recent module and a new chain to track attackers. The two problems we are trying to minimise are:
- centralised port scans.
- ssh attacks: somebody tries to log in through ssh from a unique ip address using different user IDs and passwords.
A port scan will try to talk to our machine on different ports. The idea here is to ban the offending ip address as soon as it touches a non-authorised port.
We accomplish this by creating two rules. The first one has to be the last rule in the INPUT chain, it replaces your rule that says that if a packet has not matched any rule it should be DROPped. Additionally to DROPping the packet, we add the source ip address to the « badguys » list:
iptables ... . . . iptables -A INPUT -t filter -i $OUTS -j DROP -m recent --set --name badguys
The next rule will be the first rule of the INPUT chain and will block any packet from ip addresses that are present in the badguys list and for which we have received packet within the last hour. Note that we use the « –update » option rather than « –rcheck », so that any new packet resets the clock ; offenders have to be completely silent for one hour in order to be able to communicate with us again:
iptables -A INPUT -i $OUTS -m recent --name badguys --update --seconds 3600 -j DROP iptables ... . . . iptables -A INPUT -t filter -i $OUTS -j DROP -m recent --set --name badguys
iptables does not distinguish between a successful and an unsuccessful ssh connection. Therefore we limit the rate at which one ip address can establish new ssh connections. If the attack carries on, we add the attacker’s ip address to the « badguys » list, DROPping any connection until no connection has been made for an hour.
First, we need to add to the « ssh » list all new (–syn) ssh connection. Then, we DROP new connections that happen within 30 seconds using the ‘--seconds 30‘ and ‘--hitcount 2‘ options:
iptables -A INPUT -i $OUTS -p tcp --syn --dport ssh -m recent --name ssh --set iptables -A INPUT -i $OUTS -p tcp --syn --dport ssh -m recent --name ssh --rcheck --seconds 30 --hitcount 2 -j DROP
To add a repeat offender to the « badguys » list, we create a new chain, the BADGUY chain which contains only one rule, which adds the source address to the « badguys » list.
Then we use a trick, we add a rule in the INPUT chain using the recent module that says that if the same ip address attempts to establish a new ssh connection 6 times within 5 minutes, it executes the BADGUY chain, which in turn, will add this address to the « badguys » list. This rule has to be placed ahead of the previous « ssh » list rule ; Both rules match packets for addresses already present in the « ssh » list, one will match addresses that have been seen within 30 seconds while the other, 5 minutes. If the 30 second rule is ahead of the 5 minute rule, it will match all the packets and drop them before they have a chance to reach the 5 minute rule.
iptables -N BADGUY iptables -t filter -I BADGUY -m recent --set --name badguys iptables -A INPUT -i $OUTS -p tcp --syn --dport ssh -m recent --name ssh --set iptables -A INPUT -i $OUTS -p tcp --syn --dport ssh -m recent --name ssh --rcheck --seconds 300 --hitcount 6 -j BADGUY iptables -A INPUT -i $OUTS -p tcp --syn --dport ssh -m recent --name ssh --rcheck --seconds 30 --hitcount 2 -j DROP
You can verify the content of the lists created by the recent module in /proc/net/ipt_recent. If you used the rules above, you should see two files, badguys and ssh.