I’ve been getting something like a one-person DoS attack overnight, it seems — a single IP address hitting port 80 hundreds of times a minute, generating endless 404s, and chewing up noticeable bandwidth — so I had to add a rule to my iptables to block the IP address at fault. Here’s how to do it:
First, list your current iptable rules, with line numbers, for easy reference:
$ sudo iptables -L -n --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 fail2ban-SSH tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
2 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
3 REJECT all -- 0.0.0.0/0 127.0.0.0/8 reject-with icmp-port-unreachable
4 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
5 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:25
6 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:587
etc...
Add a new rule to block the offending IP address (“xxx.yyy.zzz.www”).
$ sudo iptables -I INPUT 1 -s xxx.yyy.zzz.www -j DROP
This will insert the new rule at position 1, just prior to the rule that accepts TCP incoming traffic on port 22 for SSH and passes it to fail2ban.
Save the updated table and restart the service.
$ sudo service iptables save
$ sudo service iptables restart
$ sudo iptables -L -n --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 DROP all -- 200.85.152.75 0.0.0.0/0
2 fail2ban-SSH tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
3 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
4 REJECT all -- 0.0.0.0/0 127.0.0.0/8 reject-with icmp-port-unreachable
5 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
6 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:25
7 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:587
etc...
Some suggestions for doing this that turn up on Google have used the “-A” (Add) flag rather than the “-I” (Insert) flag. This will not work in most cases, it would add the new rule to the end of the INPUT chain, after the rule that accepts (for instance) HTTP packets. If the banned IP address were attempting to access port 80, if would be ACCEPTed by that rule before it could get DROPped by the new rule.
The position of the rule is important: if it follows a rule which would accept the traffic otherwise, the new rule will have no effect. Placing it before the rules for general public traffic ensures that the annoyance in question can’t consume resources by trying to do things like load non-existent web pages. In fact, by checking first, the IP address is effectively firewalled from the server.