pam_tally2 module is available in RHEL and CentOS and it can be used to protect your system against bruteforce attacks.
Enabling pam_tally2
Edit /etc/pam.d/password-auth and add this line on top of the auth lines:
auth required pam_tally2.so onerr=fail deny=3 unlock_time=900
Then add following line on top of the account lines:
account required pam_tally2.so
Parameters to this module are simple:
onerr=fail
If something weird happens (like unable to open the file), return with PAM_SUCCESS if onerr=succeed is given, else with the corresponding PAM error code.
deny=3
Deny access if tally for this user exceeds 3 times.
unlock_time=900
Allow access after 900 seconds (15 minutes) after failed attempt. If this option is used the user will be locked out for the specified amount of time after he exceeded his maximum allowed attempts. If this option is not set administrator will need to unlock user's account manually.
Check if you have following options set in /etc/ssh/sshd_config:
UsePAM yes
ChallengeResponseAuthentication yes
Testing pam_tally2
login as: pajarito
Using keyboard-interactive authentication.
Password:
Access denied
Using keyboard-interactive authentication.
Password:
Access denied
Using keyboard-interactive authentication.
Password:
Access denied
Using keyboard-interactive authentication.
Account locked due to 3 failed logins
Password:
As you can see after third attempt user's account was locked.
Verifying and unlocking users
To check current pam_tally2 statistics run pam_tally2 command:
# pam_tally2
Login Failures Latest failure From
jsmith 3 09/09/15 15:17:21 evil.attacker.com
To unlock a user use the "-r" flag:
# pam_tally2 -u pajarito -r
Login Failures Latest failure From
jsmith 3 09/09/15 15:20:49 evil.attacker.com
Finally if the output of pam_tally2 is empty it means that no account has been locked.
SSH server running on some quite popular hosting is exposed to many automated attacks these days.
There are more and more bots scanning the whole Internet and especially targeting popular hosting/VPS providers.
1. Changing the default sshd port number
In contrast to other well known services (ftp/mail/www) ssh server does not need to listen on the default port. It's being used by a fewer people, sometimes only you and changing the default port is yet another step in increasing your server security.
I have been using fail2ban software for some time. It scans the logs for failed login attempts and bans the attacker's IP if he fails to login too many times.
However, after a few days my firewall was full of banned IPs (good day - 5/10 IPs, bad day - more than 20).
From now on my ssh server is always running on a non-standard IP.
The number of failed login attempts has greatly decreased and the automated attacks are no longer spamming my logs.
Some useful settings from /etc/ssh/sshd_config file:
[root@server ~]# egrep "^Port|^PermitRootLogin|^MaxAuth" /etc/ssh/sshd_config
Port 4321
PermitRootLogin no
MaxAuthTries 3
2. Logging incoming connections
Even with ssh daemon running on a different port you may find it useful to log all the connection attempts to it. You can catch it via following iptables rule:
iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 4321 -j LOG --log-prefix "iptables: "
Which should be inserted before accepting the connection on ssh port.
Next if you're using rsyslogd you can filter all the messages starting with "iptables :" and put them into a separate file:
[root@server ~]# cat /etc/rsyslog.d/iptables.conf
:msg, startswith, "iptables: " -/var/log/iptables.log
& ~
[root@server ~]# service rsyslog restart
[root@server ~]# cat /var/log/iptables.log
Dec 16 18:39:41 server kernel: iptables: IN=eth0 OUT= MAC=00:1c:14:01:30:de:00:16:83:76:07:29:08:00 SRC=10.23.189.14 DST=20.40.50.101 LEN=60 TOS=0x00 PREC=0x00 TTL=54 ID=31528 DF PROTO=TCP SPT=44074 DPT=4321 WINDOW=29200 RES=0x00 SYN URGP=0
Setting up SSH public/private keys
This will be a short introduction "for dummies" describing how to generate and setup ssh keys between two computers.
I will be using OpenSSH version but process is similar for commercial distributions like SSH Tectia or VShell.
However you must be aware that connectivity between two different vendors my require some additional work (like converting OpenSSH public key to Tectia format before using it).
Generating SSH Keys
Linux/Unix:
On the source machine (host from which you will be initiating the connection) run:
[mike@client ~]$ ssh-keygen -t dsa
Generating public/private dsa key pair.
Enter file in which to save the key (/home/mike/.ssh/id_dsa):
Created directory '/home/mike/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/mike/.ssh/id_dsa.
Your public key has been saved in /home/mike/.ssh/id_dsa.pub.
The key fingerprint is:
df:95:5e:3a:1b:fc:30:81:2a:15:54:72:7e:1a:9d:2c mike@client.example.com
The key's randomart image is:
+--[ DSA 1024]----+
| o.o |
| . + o . |
| . E = |
| . * . |
| S . o + .|
| o o + + |
| . o . O |
| . B |
| . .|
+-----------------+
[mike@client ~]$
You may accept default path and filenames (~/.ssh/id_dsa - private key, ~/.ssh/id_dsa.pub - public key) or provide your own.
When prompted for secret passphrase you may choose to provide such one (but then you will be asked for this passphrase every time when using this key pair) or leave this field empty to allow passwordless connectivity.
Remember to keep correct permissions to .ssh folder and its contents - some SSH versions may not work if those rights are not setup properly:
[mike@client ~]$ chmod 700 .ssh
Private key should always be readable by its owner only - this file stays on the source server and should never be shared with anyone:
[mike@client ~]$ chmod 400 .ssh/id_dsa
Public key should be writable by its owner only but it can be read by others - this file may be shared to other servers to allow passwordless connectivity:
[mike@client ~]$ chmod 644 .ssh/id_dsa.pub
Now you need to transfer public key (id_dsa.pub) to the destination machine:
[mike@client ~]$ scp ~/.ssh/id_dsa.pub mike@server.example.com:/home/mike/mike@client.example.com.pub
On the destination machine add recently copied public key to authorized_keys2 file:
[mike@server ~]$ mkdir .ssh
[mike@server ~]$ cat mike@client.example.com.pub >> .ssh/authorized_keys2
[mike@server ~]$ chmod 700 .ssh
[mike@server ~]$ chmod 644 .ssh/authorized_keys2
Finally you may test passwordless connectivity between two hosts:
[mike@client ~]$ ssh server
Last login: Sat May 11 18:23:34 2013 from client.example.com
[mike@server ~]$
Tricks:
Limit public key to selected hosts only
This may be an additional layer of security - you may allow only selected machines to be able to logon using selected public key.
If you know that mike will be always connecting from one host you may specify its ip address or dns name. You may also provide subnet, domain or combine both options.
Edit ~/.ssh/authorized_keys2 and add from= directive.
Examples:
from="*.example.com" ssh-dss AAAAB3NzaC1kc3MAA...yfinIwP9ZSoi0LMUM6g== mike@client.example.com
This setup will allow hosts from example.com domain to logon using mike's public key.
from="*.example.com,192.168.0.100" ssh-dss AAAAB3NzaC1kc3MAA...yfinIwP9ZSoi0LMUM6g== mike@client.example.com
This will allow hosts from example.com domain and from 192.168.0.100 host.
Debugging:
Check /var/log/secure or /var/log/authlog for entries related to sshd daemon.
Positive logon looks like:
May 11 18:42:46 server sshd[3064]: Accepted publickey for mike from 192.168.0.190 port 46816 ssh2
May 11 18:42:46 server sshd[3064]: pam_unix(sshd:session): session opened for user mike by (uid=0)
Negative logon:
May 11 18:42:06 server sshd[3005]: Authentication tried for mike with correct key but not from a permitted host (host=192.168.0.100, ip=192.168.0.100).
Limit public key to allow execution of one command only:
If you don't want to give somebody full shell access you may limit his access to one command only.
Using command= directive only chosen command will be executed when somebody will connect using particular key.
If he specify any other command during logon it will be ignored.
Example:
command="echo Bye Bye" ssh-dss AAAAB3NzaC1kc3MAA...yfinIwP9ZSoi0LMUM6g== mike@client.example.com
This setup will execute "echo Bye Bye" command after user will pass authentication process.
You may put here something more useful like svnserve or backup command.
Windows:
I prefer to use PuTTY and PuTTYgen utility.
To generate ssh key pair start PuTTYgen select key type (rsa/dsa), its strength (number of bits, 1024 or more) and click on "Generate" option.
Then save public and private key in some safe location (lets call them id_dsa.ppk and id_dsa.pub).
Copy public key to the destination's server using pscp command or copy&paste contents of that file while using PuTTY to some local file on destination server.
Once the public key is on the destination server you need to convert it first from PuTTY format to OpenSSH:
[mike@server ~]$ ssh-keygen -if id_dsa.pub > id_dsa_converted.pub
Then add id_dsa_converted.pub contents to ~/.ssh/authorized_keys2 file:
[mike@server ~]$ cat id_dsa_converted.pub >> .ssh/authorized_keys2
Now start PuTTY, go to the Connection->Data settings and fill in "Auto-login username" field (specify username that will be used on the destination server).
Then go to Connection->SSH->Auth and select "Private key for authentication" file (id_dsa.ppk).
Go back to the Session list, provide destination server name or ip address and save this connection under specified name.
Connection from Windows-based client should work fine now.