This tutorial describes how to set up multi-factor authentication with Google Authenticator on your Ubuntu server when using SSH keys.
I like using SSH keys instead of passwords but wanted an extra level of security. So implementing a second factor to confirm the user's identity was the logical choice. We will be using Google Authenticator in this tutorial to generate one-time passwords that need to be provided during the login process.
The following equipment is needed:
There are no other requirements. Basically any server or VPS from netcup can be used. I have successfully implemented this and am currently using it on a VPS 1000 G9 and an older VPS 1000 G8. The G9 is running Ubuntu 20.04 LTS.
I am assuming that you already have a working SSH server setup and are just looking to add an extra level of security. Take a look at the other tutorials as well, using SSH keys instead of passwords is also recommended.
Please also take a snapshot before attempting this tutorial in order to be able to rollback any changes made! If something goes wrong, you could loose access to your server.
Log in and install the required packages. We will be using the Google Authenticator PAM module. (More info can be found on the project's github: https://github.com/google/google-authenticator-libpam)
Install it via the following command:
sudo apt install libpam-google-authenticator
In order to use the newly installed module we will have to edit our sshd file. I use nano as my editor.
sudo nano /etc/pam.d/sshd
Add one of the following lines to the file:
auth required pam_google_authenticator.so
To allow login for users who have not yet created a secret key, use
auth required pam_google_authenticator.so nullok
instead of the line above. I always configure secrets for my users right away, so I prefer option 1.
Close and save.
In order to apply the changes, restart the sshd daemon by running:
sudo systemctl restart sshd.service
We need to make some changes to /etc/ssh/sshd_config
by running:
sudo nano /etc/ssh/sshd_config
Look for the line "ChallengeResponseAuthentication". You want to change it from "no" to "yes".
In the end it should look like this:
## Change to yes to enable challenge-response passwords (beware issues with
## some PAM modules and threads)
ChallengeResponseAuthentication yes
Close and save.
Run the following command with each user you want to use mfa with.
google-authenticator
You will be asked several questions. I choose to answer them like this, but feel free to make changes depending on your needs:
You should now see a QR code, a secret key, a verification key, and several emergency codes. Write the emergency scratch codes down and store them in a safe place. You will need them if you loose access to your device or the app.
Install the Google Authenticator app from your App Store of choice. In order to generate tokens for your server, you can either scan the QR code or enter the secret key. On most of my machines the QR code tends to get distorted due to the size of my shell, so I usually go with the manual entry method. If you choose manual mode, you will be asked for a name. Choose something that you easily recognize. If you have several servers, as I do, you want to have names that easily correlate to the servers, otherwise you might end up entering the wrong tokens. Then enter the secret key generated in Step 2.3. Now you should see the generated code being displayed in the Authenticator app. The little circle on the right indicates the time remaining before a new token is generated.
We are all done. Reboot your server and try to log in. After entering your password, you should now be asked for a token.
Every time you try to log in you will now be asked for a second factor. Keep your phone / tablet with you, otherwise you won't be able to log in.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicence, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
By making a contribution to this project, I certify that:
The contribution was created in whole or in part by me and I have the right to submit it under the license indicated in the file; or
The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same license (unless I am permitted to submit under a different license), as indicated in the file; or
The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it.
I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the license(s) involved.