mobile logo

Two Factor SSH with Google Authenticator

posted on February 18, 2011 / IN Security / 36 Comments

Last week, Google enabled two factor authentication for everyone. This article explains how to install and configure Google Authenticator in conjunction with SSH for two factor authentication. Two-factor authentication relies on something you know (a password) and something you have (your phone).

Update: I have posted another article describing this same implementation with a Yubikey.

You can use this existing implementation and Google Authenticator application with SSH via an included PAM in the Google Authenticator open source application.

Download the Google Authenticator application

First, download and install Google Authenticator on your Iphone/Android/Blackberry.

Compile, install, configure Google authenticator PAM

You may need a few dependencies. On RHEL 5 I was missing ‘pam-devel’.

$ hg clone google-authenticator/
$ cd google-authenticator/libpam/
$ make
$ sudo make install
$ sudo vi /etc/pam.d/sshd

Add the following line to the beginning of /etc/pam.d/sshd:
auth required

You also need to update /etc/ssh/sshd_config and add/update:
ChallengeResponseAuthentication yes

Setup your user to require two-factor authentication

As a user, you can now run ‘google-authenticator’. This will generate a secret key, and add a file to your home directory that the newly installed PAM uses.

$ google-authenticator|0&cht=qr&chl=otpauth://totp/
Your new secret key is: AAAAAAAAAAAAAAAA
Your verification code is 123123
Your emergency scratch codes are:

Do you want me to update your "~/.google_authenticator" file (y/n) y

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

Note: The emergency scratch codes are one-time use verification codes in the event your phone is unavailable.

Configure this new secret key in Google Authenticator

In your Google Authenticator application on your phone, add this new secret key that was generated in the previous step. Note, a URL is also displayed, that can be scanned from your Google Authenticator application.

Wrapping up the setup

You will now need to restart SSH for the pam/ssh changes to activate.

At this point, you will want to stay logged into the server while you test in another shell.


Test that two-factor authentication is working.

$ ssh
Verification code:
[user@host ~]$

Enter the verification code as shown on your phone.

Your SSH sessions are now protected with two factor authentication

Running Linux Servers?

We provide 24×7 monitoring and response, proactive updates, and more. Priced per server, per month. Give us a call at 888-877-7118 or click here for further detail.

By admin


Please use the form to leave a comment

    • Chris Swan
      Posted on February 19, 20111:55 pm Reply

      Can this be made to work in combination with public key login? I’ve given it a try following the steps above, but I’m not being prompted for the OTP.

      • nwilkens
        Posted on February 19, 20112:33 pm Reply

        I don’t think this will work in combination with a public key. PubkeyAuthentication overrides the requirement for the auth PAM methods and would likely require a patch for OpenSSH.

        I may be wrong, and would be interested in hearing if anyone knows how to make this work with PubKeyAuthentication.

    • K.C.
      Posted on February 19, 20118:25 pm Reply

      Works great on Ubuntu Server 10.04 LTS. Required packages “mercurial” (for hg) and “libpam0g-dev” to build the PAM modules.

    • Brian
      Posted on February 22, 20111:46 pm Reply

      I’ve set this up on several Linux workstations and servers, some of which I also use ssh keys with. To my knowledge, the keys overwrite the need for the 2FA, which doesn’t bother me, since I’m more worried about intruders from outside versus intruders from what I consider trusted boxes (which they, themselves, are set up with 2FA, so in theory, barring a security hole, they shouldn’t get access to anyway).

      One of the bugs I’ve encountered (and I don’t know if it’s fixed yet) is that if you have a server and you want to make 2FA optional, the original code would not allow people who didn’t have a .google_authenticator file to log in, even if their password was correct. The issue was/is fixed with the patch found

      Also, I had tried this on a server with AFS….after applying the patch, if the user was set up for GA, then they could log in as expected. However, if a user was not set up for GA, they could log in, but wouldn’t receive their AFS token. I don’t know if there’s a workaround for that….

      But, all in all, I love this and have it set up to not only protect ssh, but initial log in and when my screensaver locks on my workstation at work.

    • Philippe
      Posted on March 21, 201110:46 am Reply

      RCDevs OpenOTP also has a nice interface and full blown server platform with RADIUS, SOAP and PAM and Google Authenticator.
      It works with LDAP acounts. It’s very convenient for a PAM-LDAP + Two-factor with GA.
      Found it here :

    • chukaman
      Posted on March 22, 20111:51 am Reply

      Awesome! I had to make two changes to my sshd_config, from what they were to the following:

      PubkeyAuthentication no
      UsePAM yes

      Once changed it worked perfectly.

    • D
      Posted on June 21, 20119:10 am Reply

      I don’t have a smartphone. Can this be made to work via text message?

      • mstanislav
        Posted on June 21, 20119:23 am Reply

        You’re able to select if you want to use: SMS; phone call; or application code generation.

    • Daniel
      Posted on September 23, 20115:03 pm Reply

      I get this after cloning the repository:
      $ hg clone google-authenticator/
      warning: certificate for can’t be verified (Python too old)
      requesting all changes
      adding changesets
      adding manifests
      adding file changes
      added 83 changesets with 437 changes to 315 files
      updating to branch default
      abort: No such file or directory

    • pconwell
      Posted on September 24, 20116:11 pm Reply

      Okay, I’m running into problems installing this on Ubuntu 11.04. The other website I linked to only works for 10.04 and I can’t get your instructions to work. Here is my complete build log:

      ~/google-authenticator/libpam$ make
      gcc --std=gnu99 -Wall -O2 -g -fPIC -c -o google-authenticator.o google-authenticator.c
      gcc --std=gnu99 -Wall -O2 -g -fPIC -c -o base32.o base32.c
      gcc --std=gnu99 -Wall -O2 -g -fPIC -c -o hmac.o hmac.c
      gcc --std=gnu99 -Wall -O2 -g -fPIC -c -o sha1.o sha1.c
      gcc -g -o google-authenticator google-authenticator.o base32.o hmac.o sha1.o
      google-authenticator.o: In function `displayQRCode':
      /home/pconwell/google-authenticator/libpam/google-authenticator.c:154: undefined reference to `dlopen'
      /home/pconwell/google-authenticator/libpam/google-authenticator.c:166: undefined reference to `dlsym'
      /home/pconwell/google-authenticator/libpam/google-authenticator.c:168: undefined reference to `dlsym'
      /home/pconwell/google-authenticator/libpam/google-authenticator.c:253: undefined reference to `dlclose'
      /home/pconwell/google-authenticator/libpam/google-authenticator.c:156: undefined reference to `dlopen'
      collect2: ld returned 1 exit status
      make: *** [google-authenticator] Error 1

    • Evade Flow
      Posted on September 30, 20118:26 pm Reply

      Looks like the Makefile isn’t linking with libdl correctly. You could try changing this line:

      google-authenticator: google-authenticator.o base32.o hmac.o sha1.o
      $(CC) -g $(DEF_LDFLAGS) $(shell [ -f /usr/lib/ ] &&
      echo ” -ldl”) -o $@ $+

      to look like this instead:

      google-authenticator: google-authenticator.o base32.o hmac.o sha1.o
      $(CC) -g $(DEF_LDFLAGS) -ldl -o $@ $+

      That should force it to add ‘-ldl’ to the link.

    • dixdec
      Posted on November 9, 20116:36 am Reply

      sudo apt-get install libpam-google-authenticator

    • John
      Posted on November 9, 20116:25 pm Reply

      Has anyone been able to get this to work with FreeRADIUS for SSL VPN? Is that even possible?

    • doncalamari
      Posted on November 9, 20116:47 pm Reply

      I know pconwell’s problem is over a month old, but in the interest of possibly helping someone else with the same issue, I’ll post what worked for me.

      I got the same error messages in my build and traced it to the fact that I am using a 64-bit version of CentOS. That means the libraries are in a different location. The offending library reference in the Makefile is /usr/lib/ On my system they are located in /usr/lib64 but yours may be different so try to track down where it is first.

      All I needed to be do was to edit the Makefile and replace any occurrence of /usr/lib/ with /usr/lib64/

      I don’t have the link, but someone has submitted this issue to the Authenticator project as a bug, so hopefully it will be fixed someday soon.

    • Troy Rose
      Posted on November 14, 20115:14 pm Reply


      Looks like you’re not linking the binary in with the dynamic linking loader library,*.

      Try modifying the last compile command to include “-ldl”, eg:
      gcc -g -o google-authenticator google-authenticator.o base32.o hmac.o sha1.o -ldl

    • Tran The Luan
      Posted on January 5, 20125:49 am Reply

      Do you think after Google deploy that apps, they will charge money to us?

      Now they can free, but really don’t know in the future.

      And they can access our server, everybody already thinking that!

      Anyway, it ‘s great, like OTP in Ebanking… HEHEHE!

    • phy1729
      Posted on January 12, 20124:03 am Reply

      If you get
      pam_google_authenticator.c:41:34: error: security/pam_modules.h: No such file or directory
      pam_google_authenticator.c:65: error: expected declaration specifiers or ‘…’ before ‘pam_handle_t’

      apt-get install libpam0g-dev

    • Peter
      Posted on January 27, 20129:50 am Reply

      Works great on Debian Lenny 64.

      libpam0g-dev is installed, too

      Thank you

    • Stephen
      Posted on August 7, 20123:36 pm Reply

      It seems it is included in debian testing as I write this.

      apt-get install libpam-google-authenticator

    • Jutt
      Posted on August 9, 201210:24 am Reply

      Just another tip this can be applied on the Mac side as well. You just need to move the pam for Google into the proper spot.

      By default it will place it in /usr/lib/

      Move into /usr/lib/pam/

      Works great and thats for the article.

    • idrositis | jdros
      Posted on August 15, 201210:12 am Reply

      I don’t like this google URL that it is being hit during the process. For my test it was:×200&chld=M|0&cht=qr&chl=otpauth://totp/user2@usrv%3Fsecret%3D7N5PAQNS44UHKRUO

      So google may keep track of my user-name (user2), my server-name (usrv) and my secret (7N5PAQNS44UHKRUO)…

    • Henrik Storner
      Posted on September 20, 20126:32 am Reply

      If you dont fancy Google having your userid and secret, then dont use that URL. Instead, enter the secret directly into the google-authenticator application on your smartphone.

    • Chris
      Posted on January 24, 20136:16 am Reply

      With regards to the SSH Key issue: I think this is by design and not a bug.
      SSH Key Login already *is* two-factor authentication if done according to best practice:
      1. Something you have – your encrypted SSH privkey
      2. Something you know – the passphrase für said privkey

      Thus, using the same factor again (something you have – totp token) does not increase effective security because you still only have two factors.

      In addition to remote logins via SSH, you can also use the PAM module to protect su. Just insert the line
      auth required
      in /etc/pam.d/su
      I don’t think there are repercussions for cron etc., but I might be wrong. It works fine on my test machine, though.
      I didn’t test it, but this should also work for sudo, which is obviously a nice-to-have for Ubuntu users.

    • portblanc
      Posted on February 9, 20137:47 am Reply

      Don’t you think this kind of auth is very weak because of the emergency scratch codes ?
      How can you prevent a brute force attack on this ?

    • Ian Chard
      Posted on February 13, 20134:35 am Reply

      This works with the package ‘libpam-google-authenticator’ in the Debian testing repo. All that’s required are the lines in /etc/ssh/sshd_config and /etc/pam.d/sshd, and it just works. If a public key is available then it will be used in preference to the Google Authenticator code.

    • Matt Rekoske
      Posted on May 24, 20132:11 pm Reply


      There’s an option to enable rate-limiting, which “limits attackers to no more than 3 login attempts every 30s”. That means it would take over 31 years to test all possibilities of the 8 digit backup codes. And you would still have to brute force the SSH password (and the username, since root login should be disabled) as well. You should also have something like fail2ban – – running on your server.

Page 1 of 1

Leave a comment.