One effective method to mitigate brute-force attacks and attempts to break into your public server via the SSH daemon is to use the appropriate iptables rule that will handle such abuse. There are a couple that do the job really well but the one I personally use is one that works on both, dedicated and virtual, servers.
Firstly, we’ll look at the iptables rules already in place in our public server. To list our iptables rules, we’ll be using the following iptables options:
-L, --list [chain] List all rules in the selected chain. If no chain is selected, all chains are listed.
--line-numbers When listing rules, add line numbers to the beginning of each rule, corresponding to that rule's position in the chain.
You can get the full list of valid iptables option commands, parameters and other options from this document online.
We are obviously concerned with the
INPUT chain here, so the iptables command we are going to use to list all the
INPUT rules will look like this:
iptables --list INPUT --line-numbers
The actual command line and results from one of my other servers is shown here:
[me@jenia ~]$ sudo iptables --list INPUT --line-numbers Chain INPUT (policy DROP) num target prot opt source destination 1 ACCEPT all -- anywhere anywhere 2 ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED 3 ACCEPT tcp -- anywhere anywhere tcp dpt:ssh 4 ACCEPT tcp -- anywhere anywhere tcp dpt:smtp ...
If you look closely, you’ll see that the rule at line no. 3 (highlighted) is the rule that grants access to all SSH traffic into my server. The current rule at line no. 3 (above) simply opens port 22 of my public server to anyone with the proper credentials to connect from the outside.
To prevent bad people from abusing this port with brute-force attacks, we will now limit the number of times a person may attempt to login unsuccessfully. If a person from a particular IP address attempts to login to the SSH daemon and supplies the wrong login information 3 times, and all 3 attempts occur within a span of 1 minute, the firewall (iptables) must kick-in and block all further access to port 22 from this IP address.
To accomplish this, we are going to replace (amend) the iptables rule on line no. 3 that simply opens port 22, with this new one which will also limit unsuccessful login attempts to 3 a minute:
[me@jenia ~]$ sudo iptables --replace INPUT 3 -p tcp --dport ssh --syn -m limit --limit 1/m --limit-burst 3 -j ACCEPT
-R, --replace chain rulenum rule-specification Replace a rule in the selected chain. If the source and/or destination names resolve to multiple addresses, the command will fail. Rules are numbered starting at 1.
Now when we list our INPUT chain iptables rules again, we’ll see that the rule at line no. 3 has been successfully modified.
[me@jenia ~]$ sudo iptables --list INPUT --line-numbers Chain INPUT (policy DROP) num target prot opt source destination 1 ACCEPT all -- anywhere anywhere 2 ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED 3 ACCEPT tcp -- anywhere anywhere tcp dpt:ssh flags:FIN,SYN,RST,ACK/SYN limit: avg 1/min burst 3 4 ACCEPT tcp -- anywhere anywhere tcp dpt:smtp 5 ACCEPT tcp -- anywhere anywhere tcp dpt:domain 6 ACCEPT udp -- anywhere anywhere udp dpt:domain 7 ACCEPT tcp -- anywhere anywhere tcp dpt:http ...
The last thing you want to do, after you are certain all your changes have been successfully implemented, is to save your changes. With CentOS, this is quite painless:
[me@jenia ~]$ sudo service iptables save iptables: Saving firewall rules to /etc/sysconfig/iptables:[ OK ]
A few hours later, if you go through your
/var/log/secure log file, you’ll see that the usual torrent of sshd-related reports have been reduced down to a trickle!