How to Secure SSH with 2FA on Ubuntu
Keep those Russians (and Ukrainians, Chinese, NSA, GCHQ, etc, etc) out of your box!
As you know, I love two factor authentication (2FA). Now the time has come to secure SSH with 2FA on all our Ubuntu servers.
I recently noticed that the bandwidth usage on VBOX4 had increased slightly. Apart from the spikes that come when the server is doing its nightly offsite backup, there was also an average increase in bandwidth usage. In an ideal world, that would be caused by the success of my Facebook antics, but I’ve got Piwik stats that says otherwise.
Now, that there is a slight bandwidth increase that last for a few days isn’t uncommon. Google sometimes finds it necessary to index the entire site. But I’m a curious little nerd, and with the help of netstat I checked incoming connections. It showed a Chinese IP address trying to connect to poor VBOX4 via SSH. That isn’t necessarily a reason to panic either. If you have a computer connected to the internet, there will be bots trying to connect to various services around the clock. For my own convenience, I’ve got SSH running on the standard port, 22, which makes it a prime target for that kind of shenanigans.
Moving it away from the standard port could be an option. But security by obscurity isn’t really security IMHO. Sure, it makes things a little bit harder. But there are only 65,535 ports to choose from, and if a bot wants to find your SSH port, it will find it eventually. Port knocking might be a better scheme if you want to hide your doors.
Or, you can hire a kick-ass doorman! That’s what we’re going to do with 2FA.
Let’s secure SSH with 2FA already!
If you’re using Mosh, configuring 2FA should work out of the box. At least it did on the Android-client I tested, JuiceSSH - SSH Client.
Warning: If you’re doing this while connected to your server via SSH, for the love of all things holy, make sure you don’t lock yourself out of your box in the process! This can be prevented either by A) having physical access to it, B) having more than one account that is allowed to log in via SSH, or C) not fucking up!
Another warning: Just so we’re clear. Once again, you’re following the advice of a random fella you found on the internet. If all goes wrong, you’ve only got yourself to blame, buddy.
First, and foremost, make sure you have the Google Authenticator (or any other app that supports TOTP or HTOP) installed on your phone. Just do a search for “authenticator” in your favorite app store, and you’ll find one.
Then, log on to your Ubuntu box, and install the Google Authenticator PAM module:
sudo apt-get install libpam-google-authenticator
Next, log in with the user you will log in with remotely. Run the following command to generate an authentication token:
Answer “Y” when you’re asked if the authentication token should be time based. You’ll see both an ASCII QR code and a secret key. Use either one to register the authentication token with the authenticator app on your phone. Also make sure you write down the emergency scratch codes, and store them somewhere safe. On a microfilm inside a hollowed out tooth in your dogs mouth sounds like a good spot.
With that out of the way, open the file /etc/pam.d/sshd with your favorite text editor. I prefer VIM:
sudo vim /etc/pam.d/sshd
Add the following line to the file (in VIM, you have to hit “i” before you can edit the file):
auth required pam_google_authenticator.so
And then write the changes to the file, and exit the text editor. In VIM’s case, the commands are:
Next, open the file /etc/ssh/sshd_config:
sudo vim /etc/ssh/sshd_config
Look for a line starting with ChallengeResponseAuthentication. If it’s there, change it so it looks like this (remember to hit that “i” again if you also decided to use VIM):
If a line starting with ChallengeResponseAuthentication doesn’t exist, add the entire line above to the file. Then write the changes to the file, and exit the text editor. Once again, In VIM’s case, the commands are:
Now for the grand finale! It’s time to restart the SSH server. Before we do that, go through this entire guide once more, and make sure you’ve followed it correctly. At least make sure you have ways to log in to the box again in some other way than with this particular user over SSH. Let’s do it:
sudo service ssh restart
If all goes well, you should be asked for a username, password, and a verification code the next time you log in.
So how secure am I really?
I’d say you’re pretty secure. Not only are you using a unique and long password1 for your SSH account, it’s now also secured with the need for a second factor to authenticate.
Keep one thing in mind, though. If someone really, really wants access to your server, they will get in. It doesn’t really matter how good your password is, that you’re using 2FA, or that your server is hidden deep inside an underground vault. The big guys have big guns, and 0-days to spend. They will get access.
It’s also worth mentioning that we haven’t secured local access to your account with 2FA. This means that if someone has physical access to your server, and know your username and password, they can log in without having to provide the 2FA verification code. If that is something that concerns you, I’m sure you can find a guide covering that on the internet, too.
Beautiful work, my security conscious friend. You should be proud of yourself.
Of course you are. ↩︎
This post has no feedback yet.
Do you have any thoughts you want to share? A question, maybe? Or is something in this post just plainly wrong? Then please send an e-mail to
vegard at vegard dot net with your input. You can also use any of the other points of contact listed on the About page.
It looks like you're using Google's Chrome browser, which records everything you do on the internet. Personally identifiable and sensitive information about you is then sold to the highest bidder, making you a part of surveillance capitalism.
The Contra Chrome comic explains why this is bad, and why you should use another browser.