This tutorial is about integrating the Google authentication mechanism in our servers to harden security. It guides readers on how to integrate Google authentication with more traditional user names/passwords and with SSH keys for better security.
Google Authenticator is a tool that generates TOTP codes, which can be used with various services. Generally, this generated code is a six-character long integer number, which is updated after every 30 seconds when installed on a smartphone (there are apps which can be used on a computer as well, but I will use the one that I have installed on my Android phone from Google Play). ‘OTP’ stands for the ‘one time password’ that is generally used with net banking, two-way authentication for Gmail and other email services, etc. ‘TOTP’ stands for ‘time-based one time password’, which means that a generated password is valid only for a specific period (30 seconds, in this case). This can also be looked upon as a two factor authentication, which can be integrated with SSH (more on this later) in order to harden the access to your server.
SSH
SSH stands for Secure Shell and, as the name suggests, it is a protocol that is used to make terminal connections with UNIX shell accounts. Although shell accounts are the least used these days, the protocol remains a standard for connections made to servers or remote machines when a user does not have physical access to a UNIX or Linux machine. When connected, SSH provides encrypted sessions over insecure networks in a client-server architecture. SSH was introduced as a replacement for telnet and rsh, which created insecure connections. These connections are insecure because any packet capturing tool such as ‘Wireshark’ and ‘tcpdump’ can reveal the passwords, thus posing a security threat.
Various ways to secure SSH
There are basically two methods that are widely used to gain access to a server or remote machine using SSH.
user name/password: This is a very basic mechanism by which a user connects to the server with a user name and the server asks for a password. If the password is correct, access is granted; otherwise it is denied. Although SSH itself encrypts the sessions, a weak password can be cracked by brute force.
SSH public/private keys: This mechanism is more secure, as it does not need a password for a user, but a private key is needed to access the server. When a user connects to the server with the correct private key, the server performs a check. If the provided key is correct, access is granted to the user; otherwise it is denied.
We can use Google Authenticator with either of the above mechanisms in order to add another layer of security, which can also be called two-way authentication for SSH access. An important point that must be borne in mind when implementing two-way authentication with SSH keys is that the minimum ‘openssh’ version installed on your server needs to be 6.2. If the ‘openssh’ version is earlier than 6.2, then it must be upgraded. This is the case with Centos 6, for which the version of ‘openssh’ is 5.x, which needs to be upgraded.
Integrating Google Authenticator with SSH (TOTP and user name/password)
Let’s get to the fun part now, which is implementation! In this section, I will walk you through the setup, in the course of which we will implement TOTP (Google Authentication) along with the user name/password to gain access to the server. All the steps need to be performed on the server itself and nothing is to be done at the client end.
There are certain prerequisites for installing ‘Google-authenticator’, which I’ve listed below:
- autoconf
- automake
- libtool
- pam-devel
Use your system’s package manager to install these packages. For example, if you are using CentOS 6, then all the above mentioned packages can be installed using yum, as follows:
yum install autoconf automake libtool pam-devel -y
Once done, your server is ready for the installation of Google Authenticator. Follow the steps shown below in order to install it.
To download the package, give the following command:
# cd /tmp # wget -c “https://github.com/google/google-authenticator/archive/master.zip”
To extract the files, use the command given below:
# unzip master.zip
Note: If you do not have the unzip binary installed on your server, you can easily install it using your Linux distribution package manager.
Change the directory to the extracted one, and run the following command:
# cd google-authenticator-master/libpam/ # ./bootstrap.sh
Once the above bootstrap script is completed successfully, run the configure script, followed by make and make install:
# ./configure # make && make install
If the architecture of your server is 64-bit, you will need to copy the PAM module into the library path manually. This can be done with the following code:
# cp -var /usr/local/lib/security/pam_google_authenticator.so /usr/local/lib64/security/
Note: If you are not able to find the pam_google_authenticator.so file in the /usr/local/lib/security/ directory, simply search for it by using the code given below:
# find / -iname “pam_google_authenticator.so”
The above code will reveal the location of this file, which you can then copy to the above location (/lib64/security/).
The next step is to simply run the google-authenticator binary and you should see the output given below:
# google-authenticator Do you want authentication tokens to be time-based (y/n) y https://www.google.com/chart?chs=200x200&chld=M|0&cht=qr&chl=otpauth://totp/root@localhost.localdomain%3Fsecret%3D4OGXT3WS4WBDBPUG%26issuer%3Dlocalhost.localdomain Your new secret key is: 4OGXT3WS4WBDBPUG Your verification code is 299377 Your emergency scratch codes are: 80424629 71128987 80705796 32121438 48161927 Do you want me to update your “/root/.google_authenticator” file (y/n) y Do you want to disallow multiple uses of the same authentication token? This restricts you to one login about every 30s, but it increases your chances to notice or even prevent man-in-the-middle attacks (y/n) Do you want to disallow multiple uses of the same authentication token? This restricts you to one login about every 30s, but it increases your chances to notice or even prevent man-in-the-middle attacks (y/n) y By default, tokens are good for 30 seconds and in order to compensate for possible time-skew between the client and the server, we allow an extra token before and after the current time. If you experience problems with poor time synchronization, you can increase the window from its default size of 1:30min to about 4min. Do you want to do so (y/n) n If the computer that you are logging into isn’t hardened against brute-force login attempts, you can enable rate-limiting for the authentication module. By default, this limits attackers to no more than 3 login attempts every 30s. Do you want to enable rate-limiting (y/n) y
Note: You should never allow direct access to your server using ‘root’ user for security purposes. I ran it just for demonstration purposes. You should run ‘google-authenticator’ binary only from a user who is allowed to access the server using SSH.
You will notice that there is a URL in the second line of the output, which is the link to the QR code that you will need to scan in your phone’s version of the Google Authenticator app, which you can easily install from Play Store (for Android) or from the Apple Store (for iPhones/iTabs, etc). Open this link in a Web browser, and you will have the QR code. After scanning this on your phone, you will have a TOTP setup on your phone. Now it’s time to set it up on the server such that it asks for this TOTP along with the user name and password.
Edit the PAM configuration file for SSH which is located at /etc/pam.d/sshd:
# vim /etc/pam.d/sshd #%PAM-1.0 auth required pam_google_authenticator.so auth required pam_sepermit.so auth include password-auth account required pam_nologin.so account include password-auth password include password-auth ... ... ... session include password-auth
Notice that the first line that includes pam_google_authenticator.so as the first authentication method is set to ‘required’. This means that when you try to log into your server using SSH, PAM (pluggable authentication modules) will look for a TOTP authentication token first instead of the password (Google Authenticator’s TOTP that you’ve configured on your phone in the previous step). One more step to this is that we need to instruct SSH to ask for keyboard interactive input (in this case, it would be the verification code or the token from the Google Authenticator app). This is followed by the more generic password authentication mechanism. The access will be granted to the user only if both the verification token and the password are correct!
Edit the SSH configuration file (/etc/ssh/sshd_config) to add/edit the following:
PasswordAuthentication yes ChallengeResponseAuthentication yes UsePAM yes
The following output from the server shows that the setup is successful and working perfectly, as expected:
debug1: Next authentication method: keyboard-interactive debug2: userauth_kbdint debug2: we sent a keyboard-interactive packet, wait for reply debug2: input_userauth_info_req debug2: input_userauth_info_req: num_prompts 1 <b>Verification code:</b> debug2: input_userauth_info_req debug2: input_userauth_info_req: num_prompts 1 <b>Password:</b> debug2: input_userauth_info_req debug2: input_userauth_info_req: num_prompts 0 debug1: Authentication succeeded
Integrating Google Authenticator with SSH (TOTP and SSH keys)
Instead of using Google-authentication verification code with the old password mechanism, we can also opt for SSH keys which are considered more secure. Combining Google authentication with SSH keys, we can have a pretty strong verification mechanism on the server which will be very hard to break.
In order to make use of SSH keys with Google Authenticator, the openSSH package version should be 6.2 or later. The reason is that older versions do not support the use of SSH keys with Google Authenticator. For example, at the time of writing this article, CentOS 6 is shipping with openSSH 5.3 (after a system upgrade), which is not sufficient for the setup we are after.
Upgrading openSSH to 6.2 or later
The best way to do this is to use third party repositories for your distribution instead of compiling the package manually. You can use any repository of your choice to upgrade the openSSH package. I used the CentALT repo (on a CentOS 6 box) for the same purpose, followed by a service restart:
# rpm --import http://mirror.sysadminguide.net/centalt/repository/centos/RPM-GPG-KEY-CentALT # rpm -Uvh http://mirror.sysadminguide.net/centalt/repository/centos/6/x86_64/centalt-release-6-2.noarch.rpm # /etc/init.d/sshd restart
You might get errors like the ones shown below during the service restart:
# service sshd restart Stopping sshd: [ OK ] Starting sshd: Could not load host key: /etc/ssh/ssh_host_ecdsa_key Could not load host key: /etc/ssh/ssh_host_ed25519_key [ OK ]
The most probable reason for this is that while installing, the installer renamed some file along with which some keys also got renamed. Re-generating these keys (using the ssh-keygen -A command) fixes this error:
# ssh-keygen -A ssh-keygen: generating new host keys: ECDSA ED25519 # service sshd restart Stopping sshd: [ OK ] Starting sshd: [ OK ]
The next step in this setup is to generate the SSH keys which we will use with Google Authenticator:
# mkdir .ssh (In the home directory of the user) # cd .ssh # ssh-keygen -t rsa -b 2048 # chmod 700 ~/.ssh # chmod 600 ~/.ssh/keyuser # cat keyuser.pub >> ~/.ssh/authorized_keys # chmod 600 ~/.ssh/authorized_keys
Note: As mentioned before, make sure to generate the keys with the user with which you want to log onto the server. Also, accessing your server using the ‘root’ user is not recommended at all. I am using ‘root’ here just for illustration purposes.
Edit the openSSH configuration file again and set the following:
PermitRootLogin no PasswordAuthentication no UsePAM yes AuthenticationMethods publickey,keyboard-interactive
Note: As per the AuthenticationMethods directive, public/private key pairs will be checked first. Once successful, the Google authentication verification code will be asked by the server.
Copy the private keys (key user) to the machine. This will be used to gain access to your server along with Google authentication.
Edit the /etc/pam.d/sshd file once again and make the following changes:
#%PAM-1.0 auth required pam_sepermit.so #auth include password-auth auth required pam_google_authenticator.so account required pam_nologin.so account include password-auth password include password-auth ... ... session include password-auth
Note: Password-auth is now commented out, which means it will not be used in the authentication mechanism.
Restart the openSSH service once again and, hopefully, everything will be in place. The next time you try to log into your server, your keys will be used along with TOTP from the Google Authenticator installed on your phone, in order to provide access to your server.
Using all the above authentication methods (for those who’re paranoid)
For the people who are extra careful when it comes to the security of their servers, let’s use three-way authentication: publickey, google-authentication and user password.
Uncomment the following line from /etc/pam.d/sshd in order to achieve this:
#auth include password-auth
Restart the openSSH service and you will have three-way authentication on your server.
In my opinion, this is not necessary because SSH keys with Google authentication provide a pretty tight and secured login mechanism by themselves. However, if a systems administrator is concerned about such a configuration on multiple servers – for instance, 1000+ machines in a network – then using a third party application such as jumpcloud would be much easier to configure and maintain for implementing two-factor authentication across the network.
Today, it is very important to secure your network/infrastructure and, luckily, we have open source tools available to us which we can make use of to achieve that perfect, secured network.