25

I'm using Ubuntu 14.04.1 (with OpenSSH 6.6 and libpam-google-authenticator 20130529-2).

I'm trying to set up SSH logins where the public key authenticates (without a password) and a user is prompted for a code from Google's Authenticator.

Following/adapting these instructions has gotten me a password prompt as well as a Google Auth prompt:

I've installed the package, edited my /etc/ssh/sshd_config and /etc/pam.d/ssh files

In /etc/ssh/sshd_config:

ChallengeResponseAuthentication yes
AuthenticationMethods  publickey,keyboard-interactive
UsePAM yes

and at the bottom of /etc/pam.d/ssh:

auth required pam_google_authenticator.so nullok # (I want to give everyone a chance to set up their 2FA before removing "nullok")

I know PAM is order dependent, but is sshd_config also?

What am I doing wrong? Any help would be appreciated.

7ochem
  • 280
  • 1
  • 3
  • 12
JT.
  • 353
  • 1
  • 3
  • 6

3 Answers3

33

Have got it working well, first did:

apt-get install libpam-google-authenticator

In /etc/pam.d/sshd I have changed/added the following lines (at the top):

# @include common-auth
auth required pam_google_authenticator.so

And in /etc/ssh/sshd_config:

ChallengeResponseAuthentication yes
UsePAM yes
AuthenticationMethods publickey,keyboard-interactive
PasswordAuthentication no

Works well and I now receive a "Verification code" prompt after authentication with public key. I am not sure how I would allow authentication with password+token OR key+token, as I have now effectively removed the password authentication method from PAM.

Using Ubuntu 14.04.1 LTS (GNU/Linux 3.8.0-19-generic x86_64) with ssh -v : OpenSSH_6.6.1p1 Ubuntu-2ubuntu2, OpenSSL 1.0.1f 6 Jan 2014

Linus Kendall
  • 346
  • 3
  • 2
  • So, for posterity's sake, I realized my problem. I also had tried `PasswordAuthentication no`, but that wasn't it. The problem is/was that I had/have `ControlMaster auto` and `ControlPath` directives in my ~/.ssh/config file. I wanted to make sure I didn't lock myself out, so I would always leave an SSH session open. Since my computer would just reuse them, I always got in without the system asking for a token. I marked your answer as correct, since someone following it would indeed get a working setup. Thanks! – JT. Dec 02 '14 at 06:02
  • I am also interested in learning how to setup password+token OR key+token authentication. – dma_k Jan 04 '15 at 21:11
  • 3
    I'm using CentOS 7. I have `PasswordAuthentication no`, `ChallengeResponseAuthentication yes`, `AuthenticationMethods publickey,keyboard-interactive`, and `UsePAM yes` in `sshd_config`. It validates my key _and then_ asks me for my Google Authenticator token _**and then also**_ asks me for my password. Makes me do all three—can't skip any of them. I've also tried `AuthenticationMethods publickey,keyboard-interactive:pam` as suggested by the man page, but that didn't change anything. Any ideas? – Nick Williams Feb 11 '15 at 02:52
  • 10
    @NickWilliams I was having the same issue. What fixed it for me was that I needed to commend out the `@include common-auth` line that the answers shows. I just thought it was a comment for the `pam_google_authenticator` line in /etc/pam.d/sshd at first. – freb Feb 27 '15 at 20:14
  • 5
    Thank you! My solution wasn't exactly the same (I needed to comment out `auth substack password-auth`), but your comment solved my problem! – Nick Williams Feb 27 '15 at 22:04
  • @NickWilliams Nick, thanks so much. Your solution about `auth substack password-auth` helped save me from more searching. CentOS 7 – CJ Travis Oct 23 '15 at 16:06
  • 1
    https://sysconfig.org.uk/two-factor-authentication-with-ssh.html – Christian Oct 26 '15 at 16:38
9

Linus Kendall's answer should work on older systems, but on newer Linux machines it is problematic; on my arch linux based webserver that configuration results in pam asking for my authenticator code and my password after receiving my ssh key (i.e. I need all 3).

A simpler solution that prevents this problem and that should work on every system is to change the entry in /etc/pam.d/sshd to:

auth sufficient pam_google_authenticator.so

And then to make the same edits to ``/etc/ssh/sshd` that Linus mentioned:

ChallengeResponseAuthentication yes
UsePAM yes
AuthenticationMethods publickey,keyboard-interactive
PasswordAuthentication no

That should ask you for your authenticator token after the server accepts your public key. It should not ask for your password.

As a side note, if you wish to have an sftp user account, you will probably need to bypass google authenticator in order to get it to work. Here is a suggestion of how to do that securely using an sftp jail. In etc/ssh/sshd_config:

Subsystem sftp internal-sftp
Match User ftp-user
  PasswordAuthentication yes
  AuthenticationMethods password
  ChrootDirectory /path/to/ftp/dir
  ForceCommand internal-sftp

You will need to make the permissions on /path/to/ftp/dir root write only (e.g. chown root:root /path/to/ftp/dir, chmod 755 /path/to/ftp/dir. All of the parents above that directory also need secure permissions. The way I usually do this is by making the chroot directory /home/shared/user, creating a directory in there (e.g. 'data') and then mounting whatever directory I want to share like this: sudo mount -o bind /path/to/ftp/dir /home/shared/user/data

If you follow all of those steps, you will have public key + google authenticator login for your ssh users, and a functional password protected sftp account for data transfer.

Mike Dacre
  • 288
  • 3
  • 6
  • This works great. And since for some reason I just don't feel comfortable commenting out common-auth, this was more ideal than Linus's solution. – Luke Sapan Jan 11 '16 at 06:32
  • Thanks a lot! wasted a night debugging ssh, wondering why I still have to type password after pubkey+authcode…… – felix021 Apr 22 '17 at 16:14
8

I was finally able to get this working by placing auth [success=done new_authtok_reqd=done default=die] pam_google_authenticator.so nullok at the top of /etc/pam.d/sshd.

According to the pam.d man page:

  • success=done means that if Google Authenticator signs off, no more authentication will be performed, meaning no additional password prompt.
  • default=die means that if Google Authenticator rejects the login attempt, authentication will immediately fail, skipping the password prompt.

So [success=done new_authtok_reqd=done default=die] is sort of a mix between the sufficient and requisite control values, since we want behavior from both: if success, terminate immediately (sufficient), and if failure, also terminate immediately (requisite).

Note that the nullok argument to pam_google_authenticator.so means that if a ~/.google_authenticator file is not found for a user, public-key authentication proceeds as normal. This is useful if I want to lock down only a subset of my accounts with 2FA.

bluegate010
  • 99
  • 1
  • 4
  • I've tried this, however if I don't have a .google_authenticator file then the keyboard-interactive authentication fails, I think because no other PAM module approves the login. – Hamish Moffatt Aug 05 '21 at 05:15