Good To Know
Linux Multi-Factor Authentication
Read about how to apply multi-factor authentication on Linux (servers), to sleep better even though you know your server is publicly available
Multi-factor authentication is all around us nowadays. And for a good reason, single layers of authentication are easily compromised by leaked credentials, exposed keys or even third party security leaks.
However, there is no reason to get paranoid. Two or at most three are enough when it comes to layers of authentication. The risk of locking out yourself increases with each layer and restoring gets trickier too.
Also, various layers of authentication do not necessarily mean your server is more secure each layer may be a vulnerability itself if not choosen wisely.
I usually use two layers:
- Time-based one-time Password (TOTP)
In the following three sections we're going through basic security measures and how to configure your server to apply SSH-Key and TOTP (Google Authenticator) based authentication. But first of all we start with some basic security measures.
In this example we're going to assume you use Ubuntu 20.04, but most concepts are easy to adjust to various operating systems and require only slight to none changes using another ubuntu version.
This is a practical how-to, we assume you know about the basics. Be careful when changeing security related settings. You may easily lock yourself out or even create vulnerabilities if you lack proper knowledge of what you're doing. Do not apply anything blindly.
To lessen the chance of a full lock out, you might want to keep a second ssh session connected at all time while applying the steps below.
Your auth layers are basically useless if they're exorbitantly vulnerable. The least you should do, is to make sure everything is up to date, disable the root login and configure a basic firewall.
First thing you should do when configuring a new Linux server, is to update the packages
Update package listssudo apt-get update
Upgrade the packagessudo apt-get upgrade -y
Deactivate Root Login#
One thing you really should do as your second action when configuring a new server, is to disable the root user or atleast prohibit login with it. The root is simply to mighty and a leak of its credentials is your servers armageddon.
Connect via SSHssh firstname.lastname@example.org@126.96.36.199 password:
Create a new usersudo adduser codespecialist
Shell outputAdding user `codespecialist' ...Adding new group `codespecialist' (1000) ...Adding new user `codespecialist' (1000) with group `codespecialist' ...Creating home directory `/home/codespecialist' ...Copying files from `/etc/skel' ...New password:Retype new password:passwd: password updated successfullyChanging the user information for codespecialistEnter the new value, or press ENTER for the defaultFull Name :Room Number :Work Phone :Home Phone :Other :Is the information correct? [Y/n]
Add the user to sudoersusermod -aG sudo codespecialist
Switch and check permissionssu codespecialistsudo ls
Shell outputcodespecialist@ubuntu:~$ sudo ls[sudo] password for codespecialist:codespecialist@ubuntu:~$
If the sudo command succeeds, then you have been successfully aded to the sudoers.
Test logging inssh email@example.com
You should be able to login with the credentials you just created.
Disable the root login
sshd_configsudo nano /etc/ssh/sshd_config
PermitRootLoginentry and change it to
no# Authentication:...PermitRootLogin no...
Restart the SSHD servicesudo systemctl restart sshd
Open a second terminal and try to connect as rootssh firstname.lastname@example.org
Shell email@example.com's password:Permission denied, please try again
Set up a Firewall#
To restrict access from and to ports, you might want to add a basic firewall. One firewall widely used is the Uncomplicated Firewall (UFW)
Install UFWsudo apt-get install ufw
Add SSH firewall rule
Allow ssh connections, either by applying
sudo ufw allow sshor
sudo ufw allow 22.sudo ufw allow ssh
Shell output[sudo] password for codespecialist:Rules updatedRules updated (v6)
Make sure this step proceeds by checking the output. Else, you might lock out yourself and exstinguish any chance to restore the server as well.
Enable the firewallsudo ufw enable
When you use the
ufw enablecommand, UFW will be started, and also registered as a service started on system startup.
Authenticate using a SSH-Key#
Using a SSH-Key is an easy way to improve security without increasing the number of manually provided credentials. All you have to do is configure your local ssh-agent and provide your public key to the machine your want to secure. You need to apply the following steps on your local machine.
This section requires you to have installed openshh-client. This should be preinstalled on most operating systems. But you might have to find a work-arround when using Windows.
[Optional] Create a SSH-Key
If you do not have a ssh key yet, you can create a new one. It's possibly a good choice to add a comment with
-Cto allocate it correctly later on. Follow the instructions given by the CLI. Also, make sure not to loose the private key created in this step. Its also recommended you use a passphrase in order for the key to be encrypted with AES-CBC instead of lying arround as plain text filesssh-keygen -t ed25519 -C "firstname.lastname@example.org"
Shell outputssh-keygen -t ed25519 -C "email@example.com"Generating public/private ed25519 key pair.Enter file in which to save the key (/Users/codespecialist/.ssh/id_ed25519): /Users/codespecialist/.ssh/codespecialistEnter passphrase (empty for no passphrase):Enter same passphrase again:Your identification has been saved in /Users/codespecialist/.ssh/codespecialistYour public key has been saved in /Users/codespecialist/.ssh/codespecialist.pubThe key fingerprint is:SHA256:ggejZWoZgOYJL4epj/IkvL34z0T3Var+GBS6K93kiTo firstname.lastname@example.orgThe key's randomart image is:+--[ED25519 256]--+|o ||oo ||+=. = . . ||=.oB + . . + ||.o= ..ooS. o ||o. ....+.o ||.+. ...=+. ||oo= oE oo+o ||.+o+o++. o.. |+----[SHA256]-----+
Add the key to the serverssh-copy-id -i ~/.ssh/codespecialist email@example.com
Shell outputssh-copy-id -i /Users/codespecialist/.ssh/codespecialist firstname.lastname@example.org/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/Users/codespecialist/.ssh/codespecialist.pub"/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new email@example.com's password:Number of key(s) added: 1Now try logging into the machine, with: "ssh 'firstname.lastname@example.org'"and check to make sure that only the key(s) you wanted were added.
Check if the key was added correctly on the remote hostcat ~/.ssh/authorized_keys
Shell outputssh-ed25519 AAAAC3NzaC2lZDI1NTE5AAAAIMdM36AX6tY/+vnPSQ4JLB20SP2ANU7js8uBnIzlQHFf email@example.com
Disable password authentication
sshd_configand change the
nosudo nano /etc/ssh/sshd_config...PasswordAuthentication no...
Restart the SSHD servicesudo systemctl restart sshd
Login using the SSH-Key
Logging in without password should now be possible, but at the same time, only your SSH-Key will be accepted from now on.ssh -i ~/.ssh/codespecialist firstname.lastname@example.org
Authenticate using the Google-Authenticator#
Now that we have a decent authentication mechanism and some basic security features, lets add a second layer to the authentication.
Make sure you are logged in to the remote host with the user you want to use in future, as the google authenticator is only configured for this specific user.
Also, please open a second SSH connection to the server and keep it open until you're sure, the google autenticator is working properly. Otherwise you might lock out yourself with a single misconfiguration.
Install the google authenticatorsudo apt-get install libpam-google-authenticator
Run the google authenticator script
Once you followed the steps of the google authenticator, a QR-code will be generated in the shell, that you can scan with an authenticator app on your smartphone, tablet or whatever. Just make sure, its not your local machine, as the authentication layer is horribly ineffective against attackers compormising your local machine.google-authenticator
Shell outputDo you want authentication tokens to be time-based (y/n) yWarning: pasting the following URL into your browser exposes the OTP secret to Google:Your new secret key is: G2URAC442DYGBIJDCDHY2HTFNMYour verification code is 221804Your emergency scratch codes are:2569088790233439528519547105120530624510Do you want me to update your "/home/codespecialist/.google_authenticator" file? (y/n) yDo you want to disallow multiple uses of the same authenticationtoken? This restricts you to one login about every 30s, but it increasesyour chances to notice or even prevent man-in-the-middle attacks (y/n) yBy default, a new token is generated every 30 seconds by the mobile app.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. This allows for atime skew of up to 30 seconds between authentication server and client. If youexperience problems with poor time synchronization, you can increase the windowfrom its default size of 3 permitted codes (one previous code, the currentcode, the next code) to 17 permitted codes (the 8 previous codes, the currentcode, and the 8 next codes). This will permit for a time skew of up to 4 minutesbetween client and server.Do you want to do so? (y/n) yIf the computer that you are logging into isn't hardened against brute-forcelogin 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
Make sure to write down these scratch codes, as they are the only thing that may help you, if you loose or damage your device with the TOTP-App.
Add the google authenticator as a auth factorsudo nano /etc/pam.d/sshd
Search for the
@include common-authline which should be at the very beginning and comment it out.#@include common-auth
Add the authenticator module at the bottom of the fileauth required pam_google_authenticator.so
Adjust the SSHD config
There are several things in the config you have to change or assure this time:
...ChallengeResponseAuthentication yes...UsePAM yes...AuthenticationMethods publickey,keyboard-interactive
ChallengeResponseAuthenticationis set to
UsePAMis set to
AuthenticationMethodsis set to
Restart the SSHD servicesudo systemctl restart sshd
When try you open a new ssh session with the server, it is going to ask for a verification code, which should accept the one your TOTP app displays.ssh -i .ssh/codespecialist email@example.com
Shell output(firstname.lastname@example.org) Verification code:
Your remote host is now a bit more secure, and the likelyhood of you being a victim of bruteforce attacks significantly lower. If you are interested in further ways to improve security, system hardening is the topic to look into next.
If you encounter any issues please comment below, so we can provide a solution and improve this article.