In my last article I shared the steps to install ClamAV (antivirus tool for Linux) to protect your node against Trojans, Malware and other types of viruses. In this article I will share the steps to secure SSH and root login with fail2ban. Secure Shell (SSH) in itself is a cryptographic network protocol for operating network services securely over an unsecured network. But some servers are publicly accessible, so they may need an extra reinforcement to their SSH service. For this task, we will be installing a tool called Fail2Ban, which is a very reliable tool that helps protect many services from brute-force attacks. It basically scans the log file for the specific service and looks for failed login attempts in order to block them.

Fail2ban scans log files and bans IPs that show the malicious signs — too many password failures, seeking for exploits, etc. Generally Fail2Ban is then used to update firewall rules to reject the IP addresses for a specified amount of time, although any arbitrary other action (e.g. sending an email) could also be configured. Out of the box Fail2Ban comes with filters for various services (apache, courier, ssh, etc).

How to secure SSH and root login with fail2ban (RHEL / CentOS 7)

 

We need to install the EPEL repository first:

# yum install epel-release

 

Then we need to install it with Rsyslog, since it scans the log output taken from Rsyslog:

# yum install fail2ban rsyslog -y

 

Steps to secure SSH and root login with fail2ban

Then we go ahead to configure it in order to secure SSH. We need to create a file named sshd.local in the jail folder of Fail2Ban and add below content

# cat /etc/fail2ban/jail.d/sshd.local
[DEFAULT]
bantime = 172800
maxretry = 5

[sshd]
enabled = true
filter = sshd
action = iptables[name=SSH, port=ssh, protocol=tcp]
maxretry = 5

 

This will ban attacks for 48 hours. Then we start the service and enable it for system startup services:

# systemctl start fail2ban

# systemctl status fail2ban
● fail2ban.service - Fail2Ban Service
   Loaded: loaded (/usr/lib/systemd/system/fail2ban.service; disabled; vendor preset: disabled)
   Active: active (running) since Fri 2018-11-09 07:58:09 IST; 3s ago
     Docs: man:fail2ban(1)
  Process: 2531 ExecStart=/usr/bin/fail2ban-client -x start (code=exited, status=0/SUCCESS)
 Main PID: 2534 (fail2ban-server)
    Tasks: 3
   CGroup: /system.slice/fail2ban.service
           └─2534 /usr/bin/python2 -s /usr/bin/fail2ban-server -s /var/run/fail2ban/fail2ban.sock -p /var/run/fail2ban/fail2ban.pid -x -b

Nov 09 07:58:08 node1.example.com systemd[1]: Starting Fail2Ban Service...
Nov 09 07:58:08 node1.example.com fail2ban-client[2531]: 2018-11-09 07:58:08,985 fail2ban.server         [2532]: INFO    Starting Fail2ban v0.9.7
Nov 09 07:58:08 node1.example.com fail2ban-client[2531]: 2018-11-09 07:58:08,985 fail2ban.server         [2532]: INFO    Starting in daemon mode
Nov 09 07:58:09 node1.example.com systemd[1]: Started Fail2Ban Service.

 

Now with this configuration, fail2ban will keep monitoring the /var/log/auth or /var/log/secure log file based on your distribution and as soon as it finds multiple failed attempt (based on maxretry value) from the same IP address then it will create a new IPTABLES rule to block ssh from the respective node for the provided bantime period.

 

Sample Demo

My iptables rule before

# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
f2b-SSH    tcp  --  anywhere             anywhere             tcp dpt:ssh
ACCEPT     udp  --  anywhere             anywhere             udp dpt:domain
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:domain
ACCEPT     udp  --  anywhere             anywhere             udp dpt:bootps
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:bootps

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
ACCEPT     all  --  anywhere             192.168.122.0/24     ctstate RELATED,ESTABLISHED
ACCEPT     all  --  192.168.122.0/24     anywhere
ACCEPT     all  --  anywhere             anywhere
REJECT     all  --  anywhere             anywhere             reject-with icmp-port-unreachable
REJECT     all  --  anywhere             anywhere             reject-with icmp-port-unreachable

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     udp  --  anywhere             anywhere             udp dpt:bootpc

Chain f2b-SSH (1 references)
target     prot opt source               destination
RETURN     all  --  anywhere             anywhere

Now I will do some failed login attempts from another node (node2.example.com) to this node (node1.example.com)

[root@node2 ~]# ssh node1
root@10.0.2.20's password:
Permission denied, please try again.
root@10.0.2.20's password:
Permission denied, please try again.
root@10.0.2.20's password:
Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).

After some attempts I see the ssh connection gets refused

[root@node2 ~]# ssh node1
ssh: connect to host 10.0.2.20 port 22: Connection refused

Next I will check the firewall rule list on node1 again for f2b-SSH chain after

# iptables -L f2b-SSH
Chain f2b-SSH (1 references)
target     prot opt source               destination
REJECT     all  --  node2.example.com    anywhere             reject-with icmp-port-unreachable
RETURN     all  --  anywhere             anywhere

 

As you see there is a new rule which blocks ssh port from node2.example.com. So our configuration works as expected.

 

Lastly I hope the steps from the article to secure SSH and root login with fail2ban on Linux was helpful. So, let me know your suggestions and feedback using the comment section.

Leave a Reply

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