In previous Home server related post I described how to connect to the server remotely and I have discussed some security issues about remote connection. In this post I can offer to you some hints how to improve your SSH remote access security.
Use Non-Standard port for SSH connections
When you exposed your SSH server to the Internet on default SSH port 22 you will see some connection attempts from completely unknown computers in short time. In SSH logs, you will see that somebody will try to connect with credentials root/root, admin/admin, root/123456 etc.
Almost 99% of those records are caused by automated bots which spider the Internet and searching for unsecured SSH servers to hack them and use them for malicious activities.
These bots operates in fully automatic mode and provide these operations:
- Find available SSH server on the Internet
- Try to log in by some “well known” credentials or by dictionary attack.
- Try to run some known SSH exploits against the SSH server
If you created strong password (as I recommend you before) like “Fz3Q%hV@” you are relatively safe against attacks from point 2. This kind of password can be only brute forced, is not possible to guess it by a dictionary attack in reasonable time.
If you are patching your SSH server immediately when new exploit is discovered and patch available, you are relatively safe against attacks from point 3 too. You can be harmed here only by 0 day exploits what means that the exploit is available for hackers, but patch for SSH server is not ready yet. When this situation occurs, is good idea to block access on your server from the internet by Firewall, because a hacker can provide successful attack in this time. Of course, some exploits are not known to good guys, so a vulnerability can be available for bad guys long time, without your knowledge…
So the best way how to make this attack more difficult is to eliminate step 1 from attack scenario. When hacker doesn’t detect your SSH server, he doesn’t start any attack against it.
The easiest way how to do this is to change default SSH server TCP port 22 to an unpredictable value known only to you and persons who are granted to access your server. Mentioned bots in major cases only traversed the internet (means trying IP address by IP address from a list or incrementally) and try if the SSH server is listening on port 22. They do not provide full port scan against the computer, because it is time consuming. So, when you move your server on port 54321, here is high probability that your server will be not detected and then no attack will be tried against it. I can recommend a port with high value and unassigned to any known service if possible, because standard port scan (provided by most random attackers) is trying all ports or lot of ports in range 1 – 1024 plus several well known ports with higher value than 1024. So if you select something as I mentioned before, you decrease probability of detection your ssh server to minimum.
To change the SSH server port, you have to modify /etc/ssh/sshdconfig_ file:
sudo vim /etc/ssh/sshd_config
Then locate line
and change value 22 to new ssh port selected by you.
Note: You can use Port direction in the sshd_config file more than once. For example if you put here those lines
Port 22 Port 2222 Port 22222
Then server will be listening for incoming connections on ports 22,2222 and 22222.
Save changes and restart ssh daemon:
sudo /etc/init.d/ssh restart
Now, you can connect to your server on new port which you defined. To do this from command-line ssh client, use this command:
ssh mailto:firstname.lastname@example.org –p <your_new_ssh_port>
If you are using PuTTy, modify value in Port field on default putty config page.
Allow Only Specific User to Log In by SSH
If you have more users on your Linux box (for example due Samba sharing, Mail boxes, etc), you can restrict who is able to login by SSH to the server only on specified subgroup of the users. For example, if you can allow only users john and paul to log in by SSH server, you can do this by adding this line to the /etc/ssh/sshdconfig_ file:
AllowUsers john paul
You can use opposite logic, so if you can disable login possibility only for several users, you can use reverse directive:
DenyUsers john paul
By this directive all defined linux users except john and paul can log in here by SSH.
On this place I can mentioned that permit direct login for root user is not good idea. Ubuntu disable root account by default so you cannot login as root from direct console or remotely. Anyway, I can recommend disabling this possibility directly in SSH config file by adding or modifying the line PermitRootLogin to this form:
Disable Empty Passwords
To be sure that is not possible to log in by an user account with empty password (you can forgot to set password for an user or you can create an user with empty password for some special reasons) modify or add PermitEmptyPasswords line to this form:
Disable Password Login Globally
By default, SSH allows authenticating users by user login name and password prompt. This is well known way and strong as user specified password.
SSH offers others authentication methods and well known and commonly used is authenticate user by private/public RSA or DSA keys. Instead of specifying a password, you can generate cryptographic key pair and authorize yourself by these keys. This improves security a lot because without private key file is not possible to login to the server, and additionally the key is not transferred by wire, then is not possible to “sniff” credentials on the way.
To enable this authentication, you need Private/Public key pair. Public key is stored on your server. Private key have to be presented on client side during login process and is used to cryptographically sign your login. This signature can be verified by public key stored on server and if signature is verified correctly, your access is granted.
If you can know more things about Private/Public keys cryptography, use Google to find additional pieces of information. This is out of the scope of this article.
SSH offers possibility to coexist password and key authentication processes side by side, or you can suppress password logins globally, then only key authentication will be possible and all users have to have own key pairs to login. This behavior is controlled by PasswordAuthentication line in the the /etc/ssh/sshdconfig file_. If you add or modify this line to this form:
then password authentications will be disabled.
From my point of view, disabling password logins is good idea. It improves your server security with very small amount of disadvantages. If you do not plan connect to your server from unpredictable places where you do not have your private key, then disable password logins!
In those days it is not problem to have your private key on small USB stick which you have always in your pocket. Additionally you can have placed Portable SSH or PuTTY Portable on your stick, so you can easily login from computers where is no Linux ssh or windows PuTTY installed.
I can only noticed here, that if you try to login from some public places, as Internet café etc. your private key and it’s password can be silently copied and sniffed by some spying software, then be careful where you try use your credentials.
But this is common notice -> when you are using any of your credentials on some non trusted computer as in Internet café or similar place, these credentials can be sniffed and your account can be compromised.
Remember that when you are trying to log-in anywhere on similar place. The best idea is to use your own laptop for those purposes and use only café connectivity or use one time passwords for this kind of login.
Seems to be paranoid? Maybe, but cyber crime is growing… Take this as my recommendation. How you use my advice is up to you.
To enable keys authentication, we have to generate own key pair and configure key logins. On Linux OS you can do that by command:
then you will find generated keys in ~/.ssh directory. You will find here two files:
- Id_rsa – your private key
- Id_rsa.pub - your public key
To generate key pair on Windows platform I recommend to use PuTTYgen application.
During the generation process, you are asked for a passphrase for your key. Select here very strong passphrase and type different passphrase from your password assigned to the account for classical login. Do not use private key without passphrase!
Generate private key without passphrase is the same way, as you write your classical password and login name in plaintext file and leaves this on your USB stick unencrypted. Keys without passphrase are secure as place where you store those keys!!!
Maybe now you have a question. Why I need a passphrase for a key? We generate keys to eliminate passphrase logins!
The answer is: Key passphrase is used to unlock your private key for signing. This passphrase is used only locally by SSH client and is not necessary to present this password to your server to grants access.
Additionally, without private key file, sniffed key passphrase is completely unusable for attacker. Do you remember what I wrote about Internet café? Attacker has to copy your key and sniff passphrase! If he sniffed your password only and doesn’t copy your key, he cannot login to server, because he needs the key file too. On this example you can see that attacker have to do more things to steal your login against simple password authentication method. And because no password is presented to your server during login, remote attacker cannot provide brute force password cracking or login guess technique because no password is used.
Now we have private/public key pair. To set up the key login process, we have to inform SSH server where is possible to find your public key.
SSH server expects those keys in ~/.ssh/authorizedkeys _file.
So, if you are generated the key directly on your server, type this command:
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
and change permission to this file by this command:
chmod 600 ~/.ssh/authorized_keys chmod 700 ~/.ssh/
Change permissions are important, because if the authorized_keys file has improper access rights, SSH server will refuse to use keys stored here.
If you generated key on different computer you have to copy this key to your server or write public key to authorized_keys file by hand. It is preferred way if you are used PuTTYgen tool. You can find special field with necessary value here :
So provide this:
cd ~/.ssh/ vim authorized_keys
and paste whole copied value from this filed to this file. Be sure that you add only one line and all informations from the field are copied to the line!
Write changes and modify rights:
chmod 600 ~/.ssh/authorized_keys
Now we have to check if key authentication is allowed by configuration of your SSH daemon:
sudo vim /etc/ssh/sshd_config
add or modify this line to this form:
Write changes and restart sshd daemon:
sudo /etc/init.d/ssh restart
Your server is now ready for key authenticated login.
Now you have to copy your private key on computer where you will provide remote login or on USB stick. You can do this by SCP transfer, by mail, or by direct USB stick connection to your server.
If you have private key on your client, then you can test if everything works:
From linux use this command:
ssh email@example.com –p <your_new_ssh_port> -i <path_to_your_private_file>
If you are using PuTTY, then you have to inform PuTTY that you can use key login. Fill in specified field full path to your key:
To automated login as possible, set your user name to this field:
If you are generated private key on linux, and you want to use PuTTY, you have to convert Linux key to special PuTTY key file format. You can do this through PuTTYgen. Simply import the Linux private key file to PuTTYgen (Menu item Conversions->Import Key) and save private key to ppk file format by pressing “Save private key” button.
During login process, you are asked to provide password for your key. When you typed it correctly and do not provide a mistake in described process, you can be successfully logged in.
When you verified that is possible to log in by key authentication, you can now disable classical password login globally:
sudo vim /etc/ssh/sshd_config
add or modify this line to this form:
Save changes and restart SSH daemon:
sudo /etc/init.d/ssh restart
Now, when you will try to connect without your key (remove key path parameter from ssh command or clear key field in PuTTY, you will get info:
Disconnected: No supported authentication methods available
Multiple Login Automation
If you are selected really strong passphrase, then you can find that typing this passphrase every time when you are need log in is annoying.
When you are using classical password authentication, you have no option. With Key authentication, you can reduce password typing only to one time. The way for this is to use ssh-agent on Linux, or Pageant on Windows with PuTTY.
Pageant use is self explaining. Only just fire the process and press “Add Key” button.
When you select your key file, Pageant asks you for key password and then the key is stored inside this process safely.
Every time when you will connect to your server with PuTTY and your key will be added in the Pageant, unlocked key from Pageant will be used for login automatically and you do not need to type password again.
Additionally, you can automate key loading process to the Pageant by command-line interface.
I recommend creating Pageant shortcut on your desktop, then modified Target line in the shortcut by adding full path to your key:
Now, when you clicked on this shortcut, the Pageant will be fired and try to load your key. You will get key password prompt and when you typed password correctly, Pageant will be running in your session with loaded key.
You can create as many shortcuts as you need, if the Pageant is already running, then new key is added to running instance. So you can add by this way so many keys as you need.
Linux ssh-agent works on same principle in Linux console.
In console start agent by typing
then add your key to the agent by typping
now you can log in to your server by ssh-agent cached key without needs to set password:
ssh firstname.lastname@example.org –p <your_new_ssh_port>
Second option to cache your SSH keys under Linux is keychain software. I do not try it, but maybe in the future I’ll provide here some additional info about that.
Allow Only Specific Hosts To Connect
If you know that you will provide logins to your server only from specific hosts or networks, you can limit the access only for those hosts and reject connections from others.
It is possible by TCP Wrappers. They use two files to handle service access:
To check if you have TCP Wrappers available on your system, type
sudo ldd `which sshd` | grep -i libwrap
If you get output like this:
libwrap.so.0 => /lib/libwrap.so.0
Then you have wrappers support compiled into the kernel
I’m do not using this wrappers on my server, so I do not provide detailed information about this approach here. If you will find this useful, you can find lot of documents about wrappers on the Internet.
Ban Brute Force Sites Temporarily
If you do not want to restrict some hosts statically, you can use dynamic method. When you detect lot of tries on your server from one IP address, you will move this IP to Ban list temporarily or forever. This refuse connection to your SSH daemon directly on packet level then attacker cannot provide any malicious actions against your daemon.
If you find this idea useful, you can use several ways to get this protection:
One of them mentioned on internet is to use IP Tables commands. I’m not going to use this approach. If you are interested in, you can find info about that on the Internet.
Second one is to use more specialized tool as fail2ban.
I’m going to use fail2ban for various purposes on my server, then when I will have fully functional configuration, I’ll add appropriate part of this document. If you are impatient, then start exploration yourself.