There's quite a few dedicates bits of software like SSHGuard, blockhosts, denyhosts and fail2ban that will monitor your server logs looking for suspicious activity and then block the source IP - usually though a host-based firewall.

They're all fine bits of software, but basic throttling of connections is usually enough to stop a brute-force attack and it can be acheived with five commands and the firewall that is built into the kernel.

This is particularly useful if you are running the latest RHEL7/CentOS7 release, which replaces syslog with journald - meaning there's no log files for these programs to read!

The below will limit SSH to a maximum of 5 new connections per hour, per unique source IP. If this is a server you log into frequently, you might want to increase that number.

$ sudo iptables -N SSHSCAN
$ sudo iptables -A INPUT -i !lo -m tcp -p tcp --dport 22 -m state --state NEW -j SSHSCAN
$ sudo iptables -A SSHSCAN -m recent --set --name SSH --rsource
$ sudo iptables -A SSHSCAN -m recent --update --seconds 3600 --hitcount 5 --name SSH --rsource -j LOG --log-prefix "Anti SSH-Bruteforce: " --log-level 6
$ sudo iptables -A SSHSCAN -m recent --update --seconds 3600 --hitcount 5 --name SSH --rsource -j DROP
$ sudo iptables-save

The above might look complicated if you haven't used IPTables before, so lets go through it line by line:

Line 1: Create a new table called SSHSCAN, where we will store our new firewall rules and direct all SSH traffic to.

Line 2: Direct all new incoming SSH traffic (tcp port 22) on all network interfaces except localhost to our new SSHSCAN table.

Line 3: Keep a counter called SSH that will track how many new connections we receive per unique source IP.

Line 4: If we have already received 5 or more connections from this source IP within the last 3600 seconds (1 hour), then add an entry to our log.

Line 5: If we have already received 5 or more connections from this source IP within the last 3600 seconds (1 hour), then block the connection.

Default Policy

The above assumes that your firewall has a default policy of allow. If you deny incoming requests by default, you will also need:

$ sudo iptables -I SSHSCAN 1 -m tcp -p tcp --dport 22 -m state --state ESTABLISHED -j ACCEPT
$ sudo iptables -A SSHSCAN -j ACCEPT

Line 1: Insert a rule at the top of the SSHSCAN table that will allow any established SSH traffic.

Line 2: Add a rule at the bottom of the SSHSCAN table that will explicitly allow any SSH traffic that we've not blocked.

Protecting Other Protocols

This example is explicitly for SSH, but the same principle could be applied to almost any other protocol by simply changing the port number.