Advanced OpenSSH Security Hardening Guide. – Debyum

share on:
SSH Hardening Guide

OpenSSH is also known as OpenBSD Secure Shell, released under simplified BSD License, is used to provide secure network communications via encrypting network traffic.

Encrypting all traffic provides extra security from network sniffing and other attacks and it is available for multiple platforms.

We can also implement SSH port forwarding to provide protection to data which would otherwise be transferred insecurely.

For more details, please read  More About OpenSSH.

Here are some other similar posts on security harden your Server and Applications which you should check.

 

The OpenSSH suite consists of many tools:

  • ssh, scp and sftp for authentication and transferring data securely.
  • ssh-add, ssh-keyscan and ssh-keygen for creating and managing keys.
  • sshd, ssh-agent and sftp-server for managing services.

 

We use OpenSSH tools almost daily for various tasks, from logging in to the remote server to transferring data between servers.

SSH server is widely used for server authentication. It’s very secure but we can still do some tweaks to make it more secure.

Here are a few things we can tweak in order to make OpenSSH server more secure.

 

Installation of OpenSSH in Linux.

To install OpenSSH, run these commands with superuser permissions in the terminal.

For Ubuntu/Debian, use:

shell> apt-get install openssh-server openssh-client -y

 

For RHEL/Centos/Fedora, use:

Type the following yum command to install OpenSSH client and server.

shell> yum install openssh-server openssh-clients -y

 

 

Configuration File of SSH.

The SSH server configuration files are located in /etc/ssh/ directory. we can edit /etc/ssh/sshd_config file to make it more secure.

Before making any changes to the sshd_config file we will take a backup of this file.

shell> cp /etc/ssh/sshd_config  /etc/ssh/sshd_config.$(date +%Y-%m-%d)

 

now we can start editing SSH configuration file.

 

Use only SSH protocol 2.

One of the most important things to do is use the secure version of SSH protocol > SSHv2.
SSHv2 is an improved version of SSHv1. SSHv2 has a number of new features like Encryption ciphers and support for public key certificates to provide more security.

To use SSHv2 we can edit /etc/ssh/sshd_config and change

# The default requires explicit activation of protocol 1
Protocol 2,1

 

to

# The default requires explicit activation of protocol 1
Protocol 2

 

 

Change SSH Port.

By default, SSH listens for connections on Port 22 which is the first port Attackers use to attack. We will change it to some random Private Port number from 49152 through 65535.

Edit the /etc/ssh/sshd_config file and change this line:

Port 22

to

Port 50150

Now we will configure Firewall to allow this port.

for Iptables:

shell> iptables -A INPUT -p tcp -m tcp --dport 50150 -j ACCEPT
shell> /sbin/service iptables save

 

for Firewalld.

shell> firewall-cmd --zone=public --add-port=50150 --permanent
shell> firewall-cmd --reload

 

If you’re using CentOS or Red hat and you have SELinux in enforcing mode then you also need to configure SELinux to allow new SSH Port.

shell> semanage port -a -t ssh_port_t -p tcp 50150

 

(If your server has only 512MB RAM then you need to Create at least 1GB swap space to finish this operation.)

Now restart the SSH service:

shell> /etc/init.d/ssh restart

 

or

shell> systemctl restart sshd.service

 

Try to do ssh access using new port 50150:

shell> ssh -p 50150 root@198.123.231.111

 

 

Create a custom SSH banner.

You can create a banner to convey a specific message to your users. To do this create a text file and put your message into it.

This is my favorite one which I found on the Internet. Simple and effective.

shell> vi /etc/ssh/banner.text

 *************************************************************************************
 *The use of this SSH service is restricted to authorized user's only.*
 *All the acitvities on this SSH server will be logged.*
 *************************************************************************************

 

Save this file and then edit sshd_config.

shell> vi /etc/ssh/sshd_config
# no default banner path
#Banner none
Banner /etc/ssh/banner.txt

 

 

Restrict the root account to console access only.

There’s a big debate on whether you should allow root logins via SSH or not. If you don’t want root logins via SSH then you need to change this:

shell> vi /etc/ssh/sshd_config
PermitRootLogin no

 

Make sure you have another user that can switch to superuser. ( make sure user is a part of wheel group )

 

Allow only specific users via SSH.

By default, all users can log in using SSH. But if you want to allow the only specific user’s to login via SSH then you can use AllowUsers and DenyUsers to configure that.

If you want only “mohan” and “john” to log in to the system via SSH then use:

AllowUsers root mohan john

 

Similarly, if you don’t want a user, say “Jingping” to access system through SSH then use:

DenyUsers jingping

 

 

Prevent Unattended SSH Sessions.

set up an idle timeout interval in seconds to avoid unattended SSH sessions.

shell> vi /etc/ssh/sshd_config
ClientAliveInterval 600     # 10 minutes
ClientAliveCountMax 0

 

After 10 mins of inactivity, the user will be logged out automatically.

 

Disable user’s .rhosts files.

Since we are using SSH we will disable .rhosts authentication which will prevent users from using the obsolete rsh commands such as rcp and rsh on the local system without a password.

shell> vi /etc/ssh/sshd_config
IgnoreRhosts yes

 

 

Disable Host-Based Authentication.

Host-Based authentication is a security risk and is disabled by default. If it’s not disabled by default then you can disable it by:

shell> vi /etc/ssh/sshd_config
HostbasedAuthentication no

 

 

Set a login grace timeout

We will set “LoginGraceTime” to specify how long after a connection request the SSH server will wait before disconnecting. By default, it is set to 2 minutes in SSH config file but we will change it to 60 seconds.

we can change this value by editing following line:

LoginGraceTime 60

 

 

Configure SSH logging level.

By default, SSH logs everything. Depending upon the amount of information you want, you can change the value from INFO to VERBOSE.

we can change this value by editing following line:

shell> vi /etc/ssh/sshd_config
LogLevel VERBOSE

 

Disable Empty Passwords.

For security reasons, we will deny login from accounts with empty (blank) passwordsBy default this option is disabled, if not then we can change this value by editing following line:

PermitEmptyPasswords no

 

 

Secure SSH using TCP wrappers.

TCP wrappers are useful in providing host-based access control system which can be used to limit network access to the internet.
we can use /etc/hosts.allow or /etc/hosts.deny to allow or deny SSH from specific IP address(s).

To allow SSH only from specific IP address for e.g 192.168.231.1, 172.16.30.13 we can edit /etc/hosts.allow file as following.

shell> vi /etc/hosts.allow
sshd : 192.168.231.1 172.16.30.13

 

To deny access to the bad guy we can use.

shell> vi /etc/hosts.deny
ALL: 192.168.231.2

 

 

Restrict SSH logins to specific IP address(s).

If you have more than one interface on your machine and you want SSH server to listen only on a specific Interface or IP Address then you can easily do this by editing the sshd_config file.

You can also configure SSH server to listen on multiple IP addresses of the machine. We can force SSH server to listen only on a specific Ip Address of our machine, we can do this by editing the following line.

To make SSH server listen only on Ip address 192.168.111.22,

ListenAddress 192.168.111.22

 

To verify this use,

[root@debyum ~]# ss -plant | grep ssh
LISTEN     0      128    192.168.111.22:50150                     *:*                   users:(("sshd",pid=28189,fd=3))
ESTAB      0      36     192.168.111.22:50150            112.211.73.45:62857               users:(("sshd",pid=28062,fd=3))

 

If you want to add another Ip address 192.168.111.33 in this list then just add another line like.

ListenAddress 192.168.111.22
ListenAddress 192.168.111.33

 

 

Secure SSH with the help of Firewall.

Before we make any changes in rules of firewall, You may like to save your rules;

shell> sudo iptables-save > firewall-old-rules.txt.

 

Now we can configure Firewall to secure SSH server by allowing only Allowed Ip address and Limit the number of attempts that can be made in a given time frame for SSH connection on a port.

If you want to allow connection only from a specific IP ADDRESS like e.g 192.168.231.21, then we can use;

shell> iptables -A INPUT -p tcp -m state --state NEW --source 192.168.231.21 --dport 50150 -j ACCEPT

 

If you want to allow connection only from a specific subnet like e.g 192.168.231.0/25 which allows about 62 IP addresses then we can use ;

shell> iptables -A INPUT -s 192.168.231.0/25 -m state --state NEW -p tcp --dport 50150 -j ACCEPT

 

where SSH Port no is 50150 and subnet we allow is 192.168.231.0/25

we can also configure Firewall to limit the number of incoming connections for SSH port within a time frame.

Here we will configure the firewall to allow only 3 connection attempts on SSH port 50150 within 30 seconds. This will drop all the incoming connections which will try to make more than 3 connection attempts on SSH port 50150 within 30 seconds.

 

Rate-limit the incoming SSH port connections.

We can configure firewall’s rate-limit option to control the incoming connections on SSH port.

shell> iptables -A INPUT  -i eth0 -p tcp --dport 50150 -m state --state NEW -m limit --limit 3/min --limit-burst 3 -j ACCEPT
shell> iptables -A INPUT  -i eth0 -p tcp --dport 50150 -m state --state ESTABLISHED -j ACCEPT
shell> iptables -A OUTPUT -o eth0 -p tcp --sport 50150 -m state --state ESTABLISHED -j ACCEPT

 

we can also configure iptables to allow only three connection attempts on port 50150 within 30 seconds:

shell> iptables -I INPUT -p tcp --dport 50150 -i eth0 -m state --state NEW -m recent --set
shell> iptables -I INPUT -p tcp --dport 50150 -i eth0 -m state --state NEW -m recent --update --seconds 30 --hitcount 3 -j DR

 

To implement the same with Firewalld you need to follow these steps.

Setup a xt_recent configuration file.

we will create a file /etc/modprobe.d/xt_recent.conf.

shell> vi /etc/modprobe.d/xt_recent.conf
options xt_recent ip_pkt_list_tot=30

 

Now we will reinstall the xt_recent module.

sehll> sudo modprobe -r xt_recent
shell> sudo modprobe xt_recent

( you need to repeat these steps everytime you want to change the xt_recent config.)

Now we can add these rules to rate-limit the incoming connection in firewall-cmd.

shell> firewall-cmd --permanent --direct --add-rule ipv4 filter Rate_limit  0 -p tcp --dport 50150 -m state --state NEW -m recent --set
success
shell> firewall-cmd --permanent --direct --add-rule ipv4 filter Rate_limit   1 -p tcp --dport 50150 -m state --state NEW -m recent --update  --seconds 30 --hitcount 3 -j REJECT --reject-with tcp-reset
success
shell> firewall-cmd --reload

 

 

Hide the last login.

You can also hide last login user by editing the following line.

shell> vi /etc/ssh/sshd_config
PrintLastLog no

 

 

Configure Port forwarding.

If you don’t need Port Forwarding then it’s better to disable it.

we can disable this by setting these values:

AllowTcpForwarding no
X11Forwarding no

 

Setting up maximum startup connections.

we can configure sshd_config file to setup a limit on concurrent connections to the SSH Daemon.

This is very useful to protect SSH server from Brute-Force Attack.

We will allow here, for this example, only 2 concurrent connections.

MaxStartups 2

 

 

Log in with SSH keys instead of a password.

Using Password for SSH authentication is not recommended and is insecure. A weak password can compromise the security of your server. Alternative is to use SSH keys for authentication.

Here’s how we can create and use SSH keys for authentication. ( we will use the simplest and fastest way)

Generate SSH keys

we will generate SSH keys on your client machine by running the following command:

[root@engy ~]$ ssh-keygen -b 2048 -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
f0:12:1f:0b:17:28:1c:e4:bc:f2:c5:54:a7:36:b9:53 root@engy
The key's randomart image is:
+--[ RSA 2048]----+
|                 |
|                 |
|      .          |
|     . +         |
|    . . S        |
|   + o + .* . +. |
|  . * . + .*.*   |
|   . ..+ +E+.o   |
|      ooo   ..   |
+-----------------+

 

Copy the public key file to your remote server.

Before copying the Public key file we will first create the SSH folder on our remote server.

[debyum@server-ip-address ~]$ mkdir -p ~/.ssh/

 

Now we will copy the public key from host to the authorized_keys file on the destination Server e.g debyum@server-ip-address

shell> scp -p /root/.ssh/id_rsa.pub debyum@server-ip-address:/home/debyum/.ssh/authorized_keys

 

On server:

Now we will secure these keys by using these steps.

[debyum@server-ip-address ~]$ chmod 700 .ssh
[debyum@server-ip-address ~]$ chmod 600 .ssh/authorized_keys

 

Now you can log into your SSH server without a password.

shell> ssh -p 50150 debyum@serverip-address

 

 

Keep OpenSSH server up-to-date.

For security purposes, it’s very important to keep your server up-to-date with latest security patches.

 

Conclusion

There is other software which you can use to help secure your OpenSSH server like  fail2ban  which once configured, automatically scans log files and bans IPs that show the malicious signs.

I have tried to cover all the basic to advance concepts with their examples. Still, if I have missed anything please update us through comment box to help your fellow readers. I will keep updating the same based on feedback’s received. Thanks.

Thanks for visiting this Page and have a Great day. 🙂

 

share on:
engy

engy

Hello there, My name is Rishi Guleria and I work as a Linux system administrator. I have created this blog to share what I have learned so far and to learn new things. Don't forget to leave the feedback. Have a great day. :)

Leave a Response

share on: