Setting Up SSH and 2FA on a Raspberry Pi

Log in from anywhere using SSH and Google Authenticator

Stacy Prowell
The Startup

--

A Raspberry Pi single-board computer
Our quest begins and ends here

I recently used some spare hardware to create a little file server on a Raspberry Pi, and I wanted to be able to log in to the Pi when I am away from home to check on things. This little document describes how I set that up. If you are curious about how I set up the file server, I wrote an article on that, too.

Enable SSH

I started with a Raspberry Pi 3 running Raspbian, and I am going to assume you can get up and running with Raspbian, too. These instructions are going to be Raspbian-specific in some places, but most of this is also applicable to other Linux-based operating systems on the Pi.

You can enable SSH graphically, or from the command prompt.

Enabling SSH Graphically

Click the icon in the top left to open the menu, and then select “Preferences…” and then “Raspberry Pi Configuration.”

The Pi configuration option is selected using the mouse
Open the configuration dialog

In the Raspberry Pi Configuration dialog, switch to the “Interfaces” tab, enable SSH, and click OK. That’s it!

SSH is enabled using the mouse to select a radio button
Enable SSH

Enabling SSH From the Prompt

Enabling SSH from the prompt is also pretty simple. The following two commands will do it.

sudo systemctl enable ssh
sudo systemctl start ssh

An alternate way to enable SSH from the prompt is to use the raspi-config system. Type sudo raspi-config at the prompt and press Enter. You’ll find SSH under “Interfacing Options.” Use the arrow and Tab keys to navigate.

Testing SSH

At this point, you should be able to log in to your Pi from another machine on the same network using your username (likely pi) and password.

Remote login with the command: ssh pi@raspberrypi4
Sweet success!

(You might notice that my Pi is named raspberrypi4. I have a lot of these doing various things. Yours may be named just raspberrypi, or you may have changed the name to something else, like dave. Just substitute the correct name whenever you need to.)

Change the Port

Unfortunately, everyone knows that SSH lives on port 22, and this makes it a target for scanning. We can get a little bit of security by changing the port to something else. In this case, let’s use port 2222.

At the prompt, type the following.

sudo cp /etc/sshd/sshd_config !#$.dist
sudo nano /etc/ssh/sshd_config

The first line makes a backup of the unmodified (“distribution”) SSH daemon configuration file, while the second line will open the SSH daemon configuration file for editing. It is good practice to always make a backup of a critical system configuration file before you edit it!

In the editor, you should see a line that reads something like #Port 22. The first symbol, the hash mark (#), makes this a comment; delete it and change the 22 to 2222.

Editing the SSHD configuration file
Setting the port number

Next find the line that starts ChallengeResponseAuthentication and make sure it is set to yes. (It is no by default on the current release of Raspbian.)

Screenshot of a nano editing session
Enabling challenge-response authentication

Once you have made these changes, type CTRL+x to exit, answer y to save changes, and then press Enter to overwrite the original file.

You should check to make sure the SSH daemon can read the configuration file. Do this with the following command.

sudo sshd -t

If any errors are reported, fix them. If nothing happens, great! You’re ready to restart the SSH daemon with the following command.

sudo systemctl restart ssh

(If you are doing this while logged in remotely via SSH, don’t worry. This won’t affect your current SSH session.)

Test it out by logging in and specifying the new port number. (You can do this with -p 2222 for the usual ssh command.)

Remote login with the command: ssh pi@raspberrypi4 -p 2222
Sweet success! Again!

Enable Two-Factor Authentication

Used properly, two-factor authentication (2FA) can be much more secure. Let’s set up 2FA using Google Authenticator, an open-source token generator. You can find documentation on Google Authenticator on its wiki.

Before I get too far into this, I will note that some object to the way that 2FA is implemented by Google and by similar systems. You can read these objections in the article below. I don’t want to use additional dedicated hardware (I already have a phone) and feel that this approach is sufficient. But it’s your network; you be the judge.

These instructions will set up the Pi to require both a password and a 2FA token. I prefer this approach because it requires (1) something you know and (2) something you have. That is, it really is two-factor authentication.

When you want to log in to your Raspberry Pi using SSH, you will now need to have your phone or tablet running the Google Authenticator app. This app will give you a six-digit “token” to use when logging in. Each token is good for a limited amount of time, and then a new one is generated.

Logging in from the console, or by any other method than SSH, won’t change.

1. Install Google Authenticator on your phone

Grab your phone, head to the app store of your choice, and install Google Authenticator. If you are using an iOS device, you can find it here. If you are using an Android device, you can find it here.

The Authenticator app with some of its friends

2. Install Google Authenticator on the Raspberry Pi

Install Google Authenticator by running the following command at the prompt on the Raspberry Pi.

sudo apt install libpam-google-authenticator

3. Set up Google Authenticator for your account

The next part is going to generate a quick response (QR) code, so make your terminal window as large as you can so the code isn’t mangled by wrapping. (If the code is mangled by wrapping, that’s okay. You can manually enter the information. But using the camera on your phone is much simpler!)

From the prompt on the Pi, as the user you want to log in as (probably pi), run the following command. (NB: If you’ve gotten used to typing sudo in front of commands, be aware that you don’t do that here.)

google-authenticator

This will ask if you want authentication to be time-based. You do, so answer y. At that point, you’ll get a URL, followed by a QR code, followed by your secret key, the first verification code, and your emergency scratch codes.

Screenshot of a terminal showing the output of the google-authenticator command
Congratulations! It’s a QR code

Before you do anything else, copy your scratch codes and save them in a file somewhere safe. These codes will let you log in (via SSH) if you lose your phone. Of course, you can still log in through the console or any other way. If you are already logged in, you can also see your scratch codes in the ~/.google_authenticator file that will be created.

There are more questions to answer, but first, let’s add the code to the Authenticator app before it scrolls off the screen.

4. Add the account to your Google Authenticator app on your phone

Time to find your phone again. Open the Google Authenticator app on your phone and tap the little plus sign (+) at the top right. You should get a little menu popping up at the bottom with two choices.

  • Scan barcode. If the QR code is unmangled, this is what you want. Touch it, and then point the camera at the QR code. If the app recognizes it, great! If not, then try the manual entry method.
  • Manual entry. If your QR code scrolled off the screen or was too wide for your window, you need to select this.

For manual entry, you need to do the following.

  • Enter your account name. For my example this is pi@raspberrypi4. Your computer’s name (the part after the at symbol) may be different; substitute the correct name (possibly just raspberrypi).
  • For key, enter the secret key displayed under the QR code. In this example it is S5NIHPEZN3ACB36OD2ZJSP6D3M.
  • Leave “time-based” enabled, and click the checkmark at the top right.

You should see a new entry in the Authenticator app for your Raspberry Pi. The current six-digit token will be shown and will be blue. After a few seconds, the token will flash red, then change.

5. Finish up with Google Authenticator on the Pi

Back on the Pi, answer y to update the .google_authenticator file. Next you will be asked if you want to disallow multiple uses of the same authentication token. You should, so answer y.

For the “time skew” questions, it is unlikely you will need to increase the window of permitted codes above three, so you should answer n. The next question is about rate limiting. You should enable this, so answer y.

Now you’re done! If you need to change anything or want to see your scratch codes, you can look in your ~/.google_authenticator file.

6. Update PAM

We need to tell the Linux Pluggable Authentication Module (PAM) that we want to use Google Authenticator. Edit the /etc/pam.d/sshd file, making a backup copy of the file first.

sudo cp /etc/pam.d/sshd !#$.dist
sudo nano /etc/pam.d/sshd

Add the following line at the top.

auth required pam_google_authenticator.so
A screenshot of editing the PAM configuration file for SSHD
The updated PAM configuration file for the SSH daemon

Save and exit with CTRL+x, y, and Enter.

I prefer that the auth required pam_google_authenticator.so line comes before the @include common-auth line. This means you must first enter the token and then enter your password. If you ever wish to disable 2FA, just add a hash mark (#) before the auth required pam_google_authenticator line in /etc/pam.d/sshd.

7. Test SSH

Now try to log in from another computer. You still need to specify your username and the port number you chose. When you try to log in now, you should be asked for a verification code. Check the Authenticator app on the phone for the correct code. As I write this, it is 982657, so I enter that. Next I am asked for my password, and then I’m in!

Screenshot of a terminal session loggin in via SSH with 2FA
Sweet success! So much winning!

Allow the SSH Port Through Your Router

The whole reason for doing all this was to allow me to remotely access the Raspberry Pi when I’m not home, so now I need to make sure that connection attempts to my home network are directed to the Pi. Doing this is specific to your router, but the basic steps should be the same.

These steps are going to assume you know your home IP address. Ideally, you have a hostname that is resolved by the internet domain name service (DNS) to your actual IP address. Often your service provider will assign your home a name from their domain, and you can use that (but you will probably have to ask them what it is). It is also possible to register with a dynamic DNS service, such as DYN or No-IP. You can then configure your router to update the service whenever it gets a new IP address.

1. Give the Pi a Reserved IP Address

First I recommend you give your Pi a reserved IP address. On my router, there is a DHCP reservation page where I can check a box to add a reserved IP address. IP addresses are reserved by the network interface’s media access control (MAC) address, which your router knows about. This is a unique 48-bit number assigned to every network interface.

Example DHCP reservation table
Reserving some IP addresses for fictional MAC addresses

If you need to find the MAC address of your particular interface, it’s easy. At the prompt on the Pi, enter the following command to see the MAC address for the wireless interface (wlan0).

cat /sys/class/net/wlan0/address

Likewise, if you have the Pi plugged into a wired connection, do the following to see the MAC address for the wired interface (eth0).

cat /sys/class/net/eth0/address

2. Forward the Pi’s SSH Port Through the Router

This is another router-specific action, but it is often located in a section on “Apps and Gaming.” Look for “single port forwarding,” and forward your SSH port (2222 in this case) to the correct port on your Pi’s reserved IP address.

Example router configuration table with single port forwarding for the Pi
Forward packets on 2222 to the Pi

Now if you know your home IP address, you should be able to SSH into your Pi using your port, the current token, and your password. Congratulations! You can reach your Pi from (almost) anywhere in the world.

--

--

Stacy Prowell
The Startup

Stacy was in the garage, taking something apart. “I can fix it,” he said. Maybe. He is probably be the one who broke it.