SSH Multi Factor Authentication with Google Authenticator from external networks

Tags: #<Tag:0x00007f0cabcff148> #<Tag:0x00007f0cabcfefe0> #<Tag:0x00007f0cabcfee28> #<Tag:0x00007f0cabcfec98> #<Tag:0x00007f0cabcfeae0>


Because authentication is too easy...

Authentication is so easy, 1000s of people try it every hour at my servers, which are reachable from the internet.
Let’s make use of Multi Factor Authentication with Google Authenticator, using OpenSSH.

What is PAM and what does it have to do with MFA?

Linux-PAM is a system of libraries that handle the authentication tasks of applications (services) on the system. The library provides a stable general interface (Application Programming Interface - API) that privilege granting programs (such as login(1) and su(1)) defer to to perform standard authentication tasks.

For example OpenSSH can make use of PAM. PAM can get support for Google Authenticator. And this way OpenSSH gets Multi Factor Authentication.

➜  ~ dpkg -l | grep google
ii  libpam-google-authenticator        20130529-2                                 amd64        Two-step verification

Okay, so this Debian / Ubuntu package got installed.

At the end of of my /etc/pam.d/sshd:

# Standard Un*x password updating.
@include common-password
auth [success=1 default=ignore] accessfile=/etc/security/access-local.conf
auth required nullok

The file /etc/security/access-local.conf looks like this:

➜  ~ more /etc/security/access-local.conf
# only allow from local IP range
+ : ALL :
+ : ALL :
- : ALL : ALL

This means IPs outside or need to authenticate with the pam_google_authenticator.

The next thing you need to do is to rate-limit the logins. Too many people probe for logins against SSH on TCP port 22. This generates too much login noise, and the issue is, that it may overload the Multi Factor system due to API ratio limits.

A solution for that is Fail2Ban.

Fail2Ban - because it's a free API

I use Fail2Ban on my servers. The relevant config for /etc/fail2ban/jail.conf can resemble this:

enabled = true
port    = ssh
logpath = %(sshd_log)s

This means that Fail2Ban will follow the /var/log/auth.log for login fails, and take action. Which actions?

# "bantime" is the number of seconds that a host is banned.
bantime  = 600

# A host is banned if it has generated "maxretry" during the last "findtime"
# seconds.
findtime  = 600

# "maxretry" is the number of failures before a host get banned.
maxretry = 25

In this case a host (IP) get banned via iptables for 600 seconds if it tried to authenticate 25 times without success within 600 seconds. My goal is not to support insecure passwords.

My goal is to use this to stay within the Google Authenticator ratio limit. I haven’t found this to be documented anywhere, but the point is that this is a free API. Overloading it with brute-force login noise is bad style.

~ » ssh [email protected]                                            
Verification code: 

MFA SSH logins with Bitvise SSH

On SSH clients, such as Bitvise SSH client alias Tunnelier, you have to select the login method:

That isn’t too intuitive.

Why not just key based authentication?

If you provide an RSA key, you do not need to insert multiple factors. You could disable password based authentication in general. I don’t want to do this.

Why not to use the Goog Authenticator app?

If you switch your mobile phone, you will not be able to transfer the configuration out of the Goog Authenticator app. That mans you manually need to reconfigure all your the Google Authenticator enabled services. As of now there is no export function in the Goog Auth app.

Personally I use the 1Password mobile app for this, because it has got support for Goog Authenticator One Time Tokens. And Keychain export.

Some services offer an SMS fallback option, which is very useful in case you either lose or switch your mobile. But most services don’t.
And this kind of setup has no SMS fallback. Yet :wink:


  • This is a quick and easy way to support MFA with OpenSSH, using Goog One Time Tokens.
  • Make sure that you plan ahead, when you chose the mobile app for the OTP tokens
  • If in doubt, check for the Anti-BruteForce measures to limit the login noise
    • check for issues with ratio limits, if these exist at Goog’s end. Within the PAM module this appears to be optional though.