This is a guide on how to setup the use of Google Authenticator along with public-key authentication.
First, we clone the Google Authenticator PAM module from Github:
$ git clone https://github.com/google/google-authenticator-libpam.git
To build it, we need a few packages which are not included by default in macOS.
$ brew install autoconf automake libtool
To be able to get QR codes without revealing secrets to Google, you can install
libqrencode
:
$ brew install libqrencode
Now we are ready to build Google Authenticator.
$ ./bootstrap $ ./configure $ make $ sudo make install
To install the PAM module, invoke
$ sudo cp /usr/local/lib/security/pam_google_authenticator.so /usr/lib/pam/
Then, we add the line
auth required pam_google_authenticator.so
to the configuration file /etc/pam.d/sshd
. It will look something like this:
# sshd: auth account password session # Not used by me! # auth optional pam_krb5.so use_kcminit # auth optional pam_ntlm.so try_first_pass # auth optional pam_mount.so try_first_pass # auth required pam_opendirectory.so try_first_pass # Relevant methods of authentication: auth required pam_google_authenticator.so account required pam_nologin.so account required pam_sacl.so sacl_service=ssh account required pam_opendirectory.so password required pam_opendirectory.so session required pam_launchd.so session optional pam_mount.so
I have removed the alternative methods of authentication. In /etc/ssh/sshd_config
, we set
PubkeyAuthentication yes ChallengeResponseAuthentication yes UsePAM yes AuthenticationMethods publickey,keyboard-interactive:pam
This will force the user to prove ownership of a valid SSH-key and along with a verification code from Google Authenticator.
Now we are ready to setup the two-factor authentication. Running
$ /usr/local/bin/google-authenticator
generate a shared secret and provide you with a QR code to be used with your phone. You can use TOTP or OTP verification codes. I suggest going with TOTP and small time windows.
Adding some notifications
Another good thing is to add some notifications to your ~/.ssh/rc
file (also — if you are in the US, there are a lot of services available for sending SMS, which can be handy, but remember not to send any sensitive data through third parties). For instance:
# Get and sanitize sender address, probably not needed... ip=`echo $SSH_CONNECTION | cut -d " " -f 1` ip=${ip//[^a-zA-Z0-9:.]/} # Sanitize user, probably not needed... user=`whoami` user=${user//[^a-zA-Z0-9_]/} # Show notification osascript -e 'display notification "SSH connection as '$user' from '$ip'" with title "SSH"' # Send email echo "SSH connection as '$user' from '$ip'" | sendmail me@mydomain.com
This will give a notification to you directly if you are at the computer being connected to. Additionally, it will send an email to you just in case you are AFK. The regexp are there to mitigate possible command injection, though I doubt it is possible unless there is severe bug in SSHD and the script above is running as a user with higher privileges. On the other hand, santitation is never bad if it negligible in terms of computations and you are doing it right 🙂
Another way of sending notifications is to use a Telegram bot. See below for an example output.
For this purpose, one might use e.g. telegram-send.