Setting up two-factor authentication on your Raspberry Pi

Enabling two-factor authentication (2FA) to boost security for your important accounts is becoming a lot more common these days. However you might be surprised to learn that you can do the same with your Raspberry Pi. You can enable 2FA on Raspberry Pi, and afterwards you’ll be challenged for a verification code when you access it remotely via Secure Shell (SSH).

Accessing your Raspberry Pi via SSH

A lot of people use a Raspberry Pi at home as a file, or media, server. This is has become rather common with the launch of Raspberry Pi 4, which has both USB 3 and Gigabit Ethernet. However, when you’re setting up this sort of server you often want to run it “headless”; without a monitor, keyboard, or mouse. This is especially true if you intend tuck your Raspberry Pi away behind your television, or somewhere else out of the way. In any case, it means that you are going to need to enable Secure Shell (SSH) for remote access.

However, it’s also pretty common to set up your server so that you can access your files when you’re away from home, making your Raspberry Pi accessible from the Internet.

Most of us aren’t going to be out of the house much for a while yet, but if you’re taking the time right now to build a file server, you might want to think about adding some extra security. Especially if you intend to make the server accessible from the Internet, you probably want to enable two-factor authentication (2FA) using Time-based One-Time Password (TOTP).

What is two-factor authentication?

Two-factor authentication is an extra layer of protection. As well as a password, “something you know,” you’ll need another piece of information to log in. This second factor will be based either on “something you have,” like a smart phone, or on “something you are,” like biometric information.

We’re going to go ahead and set up “something you have,” and use your smart phone as the second factor to protect your Raspberry Pi.

Updating the operating system

The first thing you should do is make sure your Raspberry Pi is up to date with the latest version of Raspbian. If you’re running a relatively recent version of the operating system you can do that from the command line:

$ sudo apt-get update
$ sudo apt-get full-upgrade

If you’re pulling your Raspberry Pi out of a drawer for the first time in a while, though, you might want to go as far as to install a new copy of Raspbian using the new Raspberry Pi Imager, so you know you’re working from a good image.

Enabling Secure Shell

The Raspbian operating system has the SSH server disabled on boot. However, since we’re intending to run the board without a monitor or keyboard, we need to enable it if we want to be able to SSH into our Raspberry Pi.

The easiest way to enable SSH is from the desktop. Go to the Raspbian menu and select “Preferences > Raspberry Pi Configuration”. Next, select the “Interfaces” tab and click on the radio button to enable SSH, then hit “OK.”

You can also enable it from the command line using systemctl:

$ sudo systemctl enable ssh
$ sudo systemctl start ssh

Alternatively, you can enable SSH using raspi-config, or, if you’re installing the operating system for the first time, you can enable SSH as you burn your SD Card.

Enabling challenge-response

Next, we need to tell the SSH daemon to enable “challenge-response” passwords. Go ahead and open the SSH config file:

$ sudo nano /etc/ssh/sshd_config

Enable challenge response by changing ChallengeResponseAuthentication from the default no to yes.

Editing /etc/ssh/ssd_config.

Then restart the SSH daemon:

$ sudo systemctl restart ssh

It’s good idea to open up a terminal on your laptop and make sure you can still SSH into your Raspberry Pi at this point — although you won’t be prompted for a 2FA code quite yet. It’s sensible to check that everything still works at this stage.

Installing two-factor authentication

The first thing you need to do is download an app to your phone that will generate the TOTP. One of the most commonly used is Google Authenticator. It’s available for Android, iOS, and Blackberry, and there is even an open source version of the app available on GitHub.

Google Authenticator in the App Store.

So go ahead and install Google Authenticator, or another 2FA app like Authy, on your phone. Afterwards, install the Google Authenticator PAM module on your Raspberry Pi:

$ sudo apt install libpam-google-authenticator

Now we have 2FA installed on both our phone, and our Raspberry Pi, we’re ready to get things configured.

Configuring two-factor authentication

You should now run Google Authenticator from the command line — without using sudo — on your Raspberry Pi in order to generate a QR code:

$ google-authenticator

Afterwards you’re probably going to have to resize the Terminal window so that the QR code is rendered correctly. Unfortunately, it’s just slightly wider than the standard 80 characters across.

The QR code generated by google-authenticator. Don’t worry, this isn’t the QR code for my key; I generated one just for this post that I didn’t use.

Don’t move forward quite yet! Before you do anything else you should copy the emergency codes and put them somewhere safe.

These codes will let you access your Raspberry Pi — and turn off 2FA — if you lose your phone. Without them, you won’t be able to SSH into your Raspberry Pi if you lose or break the device you’re using to authenticate.

Next, before we continue with Google Authenticator on the Raspberry Pi, open the Google Authenticator app on your phone and tap the plus sign (+) at the top right, then tap on “Scan barcode.”

Your phone will ask you whether you want to allow the app access to your camera; you should say “Yes.” The camera view will open. Position the barcode squarely in the green box on the screen.

Scanning the QR code with the Google Authenticator app.

As soon as your phone app recognises the QR code it will add your new account, and it will start generating TOTP codes automatically.

The TOTP in Google Authenticator app.

Your phone will generate a new one-time password every thirty seconds. However, this code isn’t going to be all that useful until we finish what we were doing on your Raspberry Pi. Switch back to your terminal window and answer “Y” when asked whether Google Authenticator should update your .google_authenticator file.

Then answer “Y” to disallow multiple uses of the same authentication token, “N” to increasing the time skew window, and “Y” to rate limiting in order to protect against brute-force attacks.

You’re done here. Now all we have to do is enable 2FA.

Enabling two-factor authentication

We’re going to use Linux Pluggable Authentication Modules (PAM), which provides dynamic authentication support for applications and services, to add 2FA to SSH on Raspberry Pi.

Now we need to configure PAM to add 2FA:

$ sudo nano /etc/pam.d/sshd

Add auth required pam_google_authenticator.so to the top of the file. You can do this either above or below the line that says @include common-auth.

Editing /etc/pam.d/sshd.

As I prefer to be prompted for my verification code after entering my password, I’ve added this line after the @include line. If you want to be prompted for the code before entering your password you should add it before the @include line.

Now restart the SSH daemon:

$ sudo systemctl restart ssh

Next, open up a terminal window on your laptop and try and SSH into your Raspberry Pi.

Wrapping things up

If everything has gone to plan, when you SSH into the Raspberry Pi, you should be prompted for a TOTP after being prompted for your password.

SSH’ing into my Raspberry Pi.

You should go ahead and open Google Authenticator on your phone, and enter the six-digit code when prompted. Then you should be logged into your Raspberry Pi as normal.

You’ll now need your phone, and a TOTP, every time you ssh into, or scp to and from, your Raspberry Pi. But because of that, you’ve just given a huge boost to the security of your device.

Now you have the Google Authenticator app on your phone, you should probably start enabling 2FA for your important services and sites — like Google, Twitter, Amazon, and others — since most bigger sites, and many smaller ones, now support two-factor authentication.

24 comments

Slinxy avatar

Does anyone know if this works with the Microsoft 2FA app? I’m a bit louth to have more than one 2FA app installed…

Ashley Whittaker avatar

Alasdair says: “Yes, it’ll work with the MS authenticator app.” And proffers this link saying TOTP is a standard: https://tools.ietf.org/html/rfc6238

xXAzazelXx avatar

Great Article!

Can you have this setup and use keyless private key logon?

Luis avatar

Thanks for posting this! :) I tried this late last year and it seems a great idea until you realise that there is no token issued once you logged in via 2FA/MFA and so you have to grab the randomly generated token from your app for every single connection. So if you connect and disconnect a lot you have to do the MFA dance each time ; likewise, if you like to have multiple terminal sessions to a host then you have the same problem. If there were some way the host could issue the connecting client with a token with a user-configurable lifetime, but I’ve not found a way to do that yet. In the mean time, properly secured ssh keys etc are more convenient and have decent security.

Luke avatar

didn’t tried this with 2FA, but wouldn’t ssh multiplexing spare the hassle?
https://en.wikibooks.org/wiki/OpenSSH/Cookbook/Multiplexing

Ashley Whittaker avatar

Alasdair has spoken. He says: “Yes. In theory, although I haven’t tried it recently, if you use a public/private key pair it’ll authenticate using that first, and then drop to password+2FA if there isn’t a key”

Slinxy avatar

Hi Again, Thanks it works with the MS Auth App, I’m having issues as I can’t seem to create/mod the .google_authenticator file in the users home directory as a standard admin user; permission denided, even if a touch the file as root first then chown it to the standard user with the correct permissions or 777.

It’s fine as root, but I’m not going to be ssh loging in as root.

Alasdair Allan avatar

You shouldn’t be using sudo to run the Google Authenticator, it should be run as pi.

Andy avatar

Great article, have been using 2FA to lock down everything recently including a large project with RPi’s. One word of warning, time is critical, if your pi looses time sync you will not be able to authenticate. The OTP is time based and as a RPi has no native onboard clock if the time drifts then your RPi is expecting one code whilst your app generates a different one. I appreciate only a limited number of usecases will not be syncd to NTP but if you have heavily tied down iptables rules be sure they can reach an NTP source. We were actually hooking up through a VPN so added some fun complications!

slinbody avatar

Is it available for different accounts??

Alasdair Allan avatar

The functionality is available to all accounts on the Raspberry Pi, but you have to run the google_authenticator command for each account and you have a separate TOTP for each (and entry into your Authenticator app on your phone).

ludwhe avatar

@Slinxy, it might be that the file has the immutable attribute set (it is recommended in the Arch Wiki’s article on setting up Google Authenticator). You may have to run “sudo chattr -i .google_authenticator” to edit it. I’d advise re-setting the attribute afterwards to avoid security problems, and that can be done with “sudo chattr +i .google_authenticator”.
While I’m at it, I’d also like to add a shameless plug for Red Hat’s wonderful 2FA app, FreeOTP. It’s open source, made by Red Hat which is a great contributor to Linux and other software used by the Raspberry Pi, and it’s more secure than Google Authenticator in the sense that it prevents potential malware for snooping on your 2FA codes through screenshots, using Android’s built in security features.

Simon avatar

That sounds great. We use something similar at work, where I have two devices with a TOTP generator which are both associated with the same account.
1) Is it possible to associate two installations of the TOTP generator with the same account on the Pi?
2) If you do lose your phone, how do you remove it’s association from the Pi?
Thanks

Alasdair Allan avatar

Yes, you can associate two TOTP generators with the same account. Just use the QR code with both generators, or copy down the key and enter it manually in the second if needed. If you loose your phone, so long as you can login on console — with a monitor, keyboard, and mouse — you could just login there (the 2FA only happens for remote access via SSH) and disable it by (more or less) reversing the instructions and removing the auth required pam_google_authenticator.so from the /etc/pam.d/sshd file.

Tim avatar

This is awesome. Does this work with VNC or SFTP connections?

Alisa Miss avatar

On Armbian, enabling 2FA is by far more user friendly https://www.cnx-software.com/2019/05/03/two-factor-authentication-ssh-armbian/

Salvador avatar

…and how do you log into it when your internet decides to fail?

Andrew avatar

It’s great that such a capable platform as Raspberry Pi offers the ability to secure connections with TOTP 2FA. Is there a way to use it with a Yubikey for 2FA, other than by simply using their YubiAuth TOTP app?

Burf avatar

You should still be able to hook it up to a KB, and monitor and login that way? this would only affect logins via SSH

Pcave avatar

You can use the key exchange feature in yubikeys with SSH already. This isn’t ToTP, but it is 2FA.

StevenP avatar

Great article, very well written.
But is it only me, or does TOTP just mean ‘Top of the Pops’ to anyone else too? I guess you have to be of a certain age to have that excitement for 7pm Thursdays, BBC1…

Jason avatar

Hahaha! I do think of that NOW – thanks!

Sugandhan avatar

@Alasdair Alan This is sugandhan from India this is helpful information for me I have one problem how to contact you

Linda Yue avatar

This is definitely a great thing for us users. I have been using two factor authentication for long. There are many software which need it. Download the Google Authenticator is OK. But if you restore factory settings, it will be a little complex… I’ve tried that before.

Comments are closed