Every day there seems to be a security breach reported in the news where our data is at risk. Despite the fact that SSH is a secure way to connect remotely to a system, you can still make it even more secure. This article will show you how.
That’s where two-factor authentication (2FA) comes in. Even if you disable passwords and only allow SSH connections using public and private keys, an unauthorized user could still gain access to your system if they steal your keys.
With two-factor authentication, you can’t connect to a server with just your SSH keys. You also need to provide the randomly generated number displayed by an authenticator application on a mobile phone.
The Time-based One-time Password algorithm (TOTP) is the method shown in this article. Google Authenticator is used as the server application. Google Authenticator is available by default in Fedora.
For your mobile phone, you can use any two-way authentication application that is compatible with TOTP. There are numerous free applications for Android or IOS that work with TOTP and Google Authenticator. This article uses FreeOTP as an example.
Install and set up Google Authenticator
First, install the Google Authenticator package on your server.
$ sudo dnf install -y google-authenticator
Run the application.
$ google-authenticator
The application presents you with a series of questions. The snippets below show you how to answer for a reasonably secure setup.
Do you want authentication tokens to be time-based (y/n) y
Do you want me to update your "/home/user/.google_authenticator" file (y/n)? y
The app provides you with a secret key, verification code, and recovery codes. Keep these in a secure, safe location. The recovery codes are the only way to access your server if you lose your mobile phone.
Set up mobile phone authentication
Install the authenticator application (FreeOTP) on your mobile phone. You can find it in Google Play if you have an Android phone, or in the iTunes store for an Apple iPhone.
A QR code is displayed on the screen. Open up the FreeOTP app on your mobile phone. To add a new account, select the QR code shaped tool at the top on the app, and then scan the QR code. After the setup is complete, you’ll have to provide the random number generated by the authenticator application every time you connect to your server remotely.
Finish configuration
The application asks further questions. The example below shows you how to answer to set up a reasonably secure configuration.
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. 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 +-1min (window size of 3) to about +-4min (window size of 17 acceptable tokens).
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
Now you have to set up SSH to take advantage of the new two-way authentication.
Configure SSH
Before completing this step, make sure you’ve already established a working SSH connection using public SSH keys, since we’ll be disabling password connections. If there is a problem or mistake, having a connection will allow you to fix the problem.
On your server, use sudo to edit the /etc/pam.d/sshd file.
$ sudo vi /etc/pam.d/sshd
Comment out the auth substack password-auth line:
#auth substack password-auth
Add the following line to the bottom of the file.
auth sufficient pam_google_authenticator.so
Save and close the file. Next, edit the /etc/ssh/sshd_config file.
$ sudo vi /etc/ssh/sshd_config
Look for the ChallengeResponseAuthentication line and change it to yes.
ChallengeResponseAuthentication yes
Look for the PasswordAuthentication line and change it to no.
PasswordAuthentication no
Add the following line to the bottom of the file.
AuthenticationMethods publickey,password publickey,keyboard-interactive
Save and close the file, and then restart SSH.
$ sudo systemctl restart sshd
Testing your two-factor authentication
When you attempt to connect to your server you’re now prompted for a verification code.
[user@client ~]$ ssh user@example.com
Verification code:
The verification code is randomly generated by your authenticator application on your mobile phone. Since this number changes every few seconds, you need to enter it before it changes.
If you do not enter the verification code, you won’t be able to access the system, and you’ll get a permission denied error:
[user@client ~]$ ssh user@example.com
Verification code:
Verification code:
Verification code:
Permission denied (keyboard-interactive).
[user@client ~]$
Conclusion
By adding this simple two-way authentication, you’ve now made it much more difficult for an unauthorized user to gain access to your server.
zlopez
Isn’t there a non Google alternative for server?
I’m trying to get my life Google free.
mike
duo
Jake
A good alternative as long as you have less than ten users, yes! This Duo method Works excellent on my end. Past ten users would require a subscription with Duo.
https://duo.com/docs/duounix?utm_medium=paid_search&utm_source=google&utm_campaign=Brand
czocher
It’s just called google-authenticator but in reality it’s completely free and open-source, not really requiring any google-related service to operate. The name is a bit unfortunate though.
Turbovix
Congratulations, I really liked this solution!
João Rodrigues
You’ve also made it much more difficult for you to access your own server.
Forgot your phone? Lost it? It was stolen? Well, you’re SOL.
Paul W. Frields
@João: No, that’s not correct. Reread the article — even assuming you have no physical access to the server, the recovery codes provided give you several “get out of jail free” cards in case you lose or forget your phone.
Curt Warfield
Hi João,
During the initial setup as noted in the article, recovery codes will be generated. If you lost access to your phone, you can use one of the recovery codes to regain access.
Chris Hiner
When you initially set it up, after scanning the QR code with your phone, print the QR code and stick it in the safe.
You can then use that to set up a new device if you lose your phone.
Or there are some TOTP apps that let you back up the secret values.
ricardotiellet
Hello everyone. I liked the article and I would like to make use of it if the sending of the password occurs through the Short Message Service (SMS).
Saeed
I don’t think you should ever send password in clear text, in SMS!
ricardotiellet
Hello @Saeed, I expressed myself incorrectly. Where I wrote “password”, I should have typed “random number verification”. SMS is a consolidated and compatible service for ANY mobile device by your long existence, different and restrictive to receive through mobile device that are currently using Android or IOS systems. In other words, or you acquire, purchase a modern mobile device (companies providing information and communication technology infrastructure (ICT) and smart devices will continue to thank consumers for preference and who doesn’t buy a current mobile device continues in the same, without security.
D.a
Men if you and guy who wrote this topic doesn’t know: Google Authenticator uses TOTP protocol. Look at Wikipedia. One time passwords not random, like all in PC actually )). Them based on text from QR code what you scanned + hashed with time range of 30 sec. So that 6/8 digits ARE NOT A PASSWORD and because of that you see every 30 sec new code.
Basri Azemi
Thank you very much for posting this article which is so useful in the wake of the bulnerabilities found even with the TLSv1.3.
I am going to implement these changes on my system ASAP
Brett Stauner
This looks really interesting, and I’m looking forward to giving this a try, but I’m curious… Is there a way to make this work for automated processes as well? I could easily see putting this in place for human logins, but when you’ve got automated systems accessing your server to update code, config, etc. Can that account also use this method somehow?
Kurt B
It would seem to me that having password in the AuthenticationMethods option would be useless since you have PasswordAuthentication set to no. Why not just set AuthenticationMethods to publickey,keyboard-interactive?
Ondrej Kolin
By the way for the desktop is in Flatpak the Gnome Authenticator: https://flathub.org/apps/details/com.github.bilelmoussaoui.Authenticator
Dmitriy Alekseev
What a point? Better use Authy app it crossplatform and ☁️ based
svsv sarma
Beware that even phones are not secure! You get an interrupting call from an unknown number just at the time of the OTP and you will be in a dilemma.
You are secure as long as you are lucky or you are not that important.
I feel that there is some flaw in the keyboard itself.
May the 2FA help us all.
James Susanka
Will one time password otop work on fedora? It works on Ubuntu and no google involvement and you keep track of everything.
Jake
Make sure the time is set and synchronised properly to a time source (ntp or whatever) on both sides!
Einer Petersen
Hey Folks,
SSH already has a 2FA setup that needs no 3rd party authenticator and it is easy to setup and use.
1) When you generate your ssh key-pair, passphrase protect the private key
2) copy the private key to a USB stick
3) copy your public key to the ~.ssh/authorized_keys of the accounts you want to log into via ssh (can use ssh-copy-id {user}@{host} to do this)
4) in /etc/ssh/sshd_config, set PermitRootLogin without-password
5) in /etc/ssh/sshd_config, set PasswordAuthentication no
6) restart sshd
when you want to ssh to that machine:
ssh -i {path_to_ssh-Private key} {user}@{host}
You will be prompted for your passphrase of your private key
2 Factor Authentication == something you have {your private key} + something you know {your private key passphrase}
As long as you keep your ssh private key on that usb stick with you, you are pretty much set 🙂
Einer
Jakub Jelen
Do not use USB sticks for private keys, but try smart cards or yubikey, giving you much better assurance with a simple PIN. I wrote about that here last year:
https://fedoramag.wpengine.com/fedora-28-better-smart-card-support-openssh/
Einer
Hi Jakub,
I would agree with you, don’t use USB keys for private keys, except … 🙂
1) IF the private key is passphrase protected (which also means it is encrypted AES 256) — then even if you loose the USB stick, the private key is useless to an unauthorized user
2) Not everyone has a SmartCard reader on their machine
3) SmartCards are not as readily available as USB sticks 🙂
4) a 20+ character passphrase used to encrypt an SSH private key is a whole lot stronger than a 4 digit PIN simply due to the fact that a 4 digit PIN only has a maximum of 9,999 possible combinations vs a 20 character passphrase which is approximately 10^74 combinations …. with an encryption algorithm (AES 256) which has not been broken to date 🙂
Einer
Yaroslav Fedevych
You do realize that they restrict your PIN entry attempts to three for a reason, don’t you? Three incorrect attempts and your card is toast.
Kurt Bechstein
It seems like that since you are disabling password authentication that you would only need AuthenticationMethods publickey,keyboard-interactive.
Hoja
FreeOTP is also available on F-Droid
Earl Ramirez
FreeOTP stopped working after F27 and was accepting any random code
0xSheepdog
In your Configure SSH section, you explain that we should edit /etc/pam.d/sshd but then your code example is editing /etc/pam.d/ssh
This will cause problems for copy-pasta people.
Curt Warfield
Thanks so much for spotting that typo. It’s been fixed !
Curt Warfield
Thanks so much for spotting that typo! It’s been fixed.
UrsaTech
Thanks for posting this, very easy to follow. One comment I found while following the steps:
The first line of code under Configuring SSH is missing the final character ‘d’.
$ sudo vi /etc/pam.d/ssh
should be
$ sudo vi /etc/pam.d/sshd
Curt Warfield
Thanks so much for spotting that typo! It’s been fixed.
Rudra Banerjee
Can I do the sshd thing in my userspace, eg at ~/. ssh?
This article is good, but for me, I don’t want to repeat each step with each new install.
Maikel Grep
Good to read about this, have this setup myself since 2014 on OpenSuse and Debian.
During that time I lost my phone a couple of times and needed the emergency codes.
After that it’s easy to restore the situation with a new phone.
Earl
I have also enabled 2FA on the GDM in /etc/pam.d/gdm-password, for SSH you don’t need to disable password auth
Einer
If you don’t disable password auth in SSHD, you are basically defeating the purpose of 2FA. The object in 2FA is to eliminate the use of typical password authentication in an effort to reduce password brute force attacks or the use of a valid password by an unauthorized person (someone stole your password and is now using it and your system privileges to compromise the system).
Einer
Robert
Would love to the same for HTOP, like a Yubikey. I used to use TOTP a lot, but since I tried a Yubikey, I find it much more pleasant. You enter it into your laptop as long as you use it and experience basically no slowdown in your workflow. But you can worry less about your system getting compromised.
Mark Tinberg
A place I like storing the TOTP tokens instead of the Authenticator app (Google, Microsoft, FreeOTP, Duo, whatever..) on a phone is to store them on a Yubikey that has NFC, then the tokens can’t be easily lost or stolen even if some app roots your phone, or your phone dies, additionally you can read the tokens using any NFC or USB device, so they are still copy/pastable on a phone but also on a computer. The Yubikey lasts for years attached to a regular keychain with your housekeys in my experience, and if it does start to wear out, it’s not too much trouble to load a new Yubikey with tokens.
Dirk
Nice Article.
I personally prefer using my openPGP-Card for SSH authentication because I don’t want to rely on any third party service.
But, this article is very useful for people which are not able to use a smartcard or a Yubikey, anyway.
rder
How do it without google? I need normal paper.
nothing more, only otp paper
Johan Heikkila
From the comments we see that more education is needed for 2FA and especially TOTP/HOTP.
One funny thing. The Raspberry Pi doesn’t have an internal clock. For some reason the ntp on it had died, and being an internet connected device, I had enabled TOTP on ssh. When the clock now was drifting, it didn’t accept the TOTP code. I had to wait longer than 30s to enter the code. I guess rescue codes would have worked.
Jeff
You say “scan the QR code” but how does the QR code appear? I would like to get this working on headless servers (no graphical display, only text.)
Aarem
Would this break ssh-keygen passwordless entry?
Btw, I wonder if it is possible to aiutomate the code retrieval process fo the Google Authenticator and submit it. Is this possible?