Simply, there are three factors of authentication, “something the user knows”, “something the user is”, and “something the user has”. Two factor authentication means that we are going to check at least two of the three authentication factors before letting you in. Specifically, I will be discussing the “knows” and “has” factors. The “is” factors are things like finger prints and iris scans. Cool stuff for the movies but not really practical yet and still easily spoof-able.
Why do we need Multi-Factor Authentication?
Basically because we are all lazy. We get mad at our IT people for requesting an 8 character or greater password with capitals and numbers so we make our password start with a capital and end with a number, like “Password1”. So, we have greatly diminished the entropy of our 8 character password by sticking it to the man and then we decide to give free cake to the hackers by reusing the password multiple times. Awesome. And since it is hard to change human behavior and the adoption of strong passphrases is not jumping out of the IT crowd, it is time to push for something that will harden our log ins with very little work. Two factor passwords give us a new one time password that we don’t have to remember every 30 seconds for free! All we have to do is “have it” – which in our case is a cell phone.
I am really excited about the free product from Google called Google Authenticator. They have a client for almost every phone / device type (even Blackberries and Windows phones) and they implement open standards. I am hoping to see wide spread adoption by many site in the future. If you don’t have your Google account and Dropbox account setup with this already, you should stop reading and go test it out. It is cool how easy it is. Facebook, AWS Amazon and Paypal also have a two factor product, but not as cool.
How to Add Two Factor Authentication to Your Server
I am doing it on a Raspberry Pi but the concepts should be the same for most Linux distros. We are going to install Google’s PAM, that will ask for a verification token before letting us in to the Raspberry Pi.
To start – Let’s make sure we have everything:
sudo apt-get update sudo apt-get libpam0g-dev ntp make build-essential
Once this is done, check that your time is right and that you are using NTP to stay in sync. You do this by typing ‘date’ into the command line and then ‘ntpq -p’. If you don’t see any servers listed when you run ‘ntpq -p’ you have to reconfigure. The time is extremely important in generating accurate tokens.
Next let’s download and make the PAM library file.
wget http://google-authenticator.googlecode.com/files/libpam-google-authenticator-1.0-source.tar.bz2 tar xvjf libpam-google-authenticator-1.0-source.tar.bz2
cd libpam* sudo make install //for good measure sudo cp pam_google_authenticator.so /lib/security google-authenticator // will ask you if you want it to be time based (Y is the anwser)
You should get a URL to copy into your browser that will display a QR code. You should scan it immediately and make sure everything is looking correct. Also print out your emergency codes. These codes will let you in the box if you lose you phone.
Now we are ready to update our PAM configuration and our SSHd configuration – This step is where the scary can happen. If you have physical access to the box or Pi in case anything goes wrong you can access the disk from another machine and set everything back. If not, now is a good time to make a quick back up.
I would keep multiple ssh sessions open now. Then, make the following changes:
sudo nano /etc/ssh/sshd_config
ChallengeResponseAuthentication no becomes ChallengeResponseAuthentication yes
sudo nano /etc/pam.d/common-auth
I added ‘auth required pam_google_authenticator.so’ to the very bottom.
Now while you are still logged in, restart ssh
sudo /etc/init.d/ssh restart
and try opening a new ssh session. You should see:
Using username "pi". Using keyboard-interactive authentication. Password: Using keyboard-interactive authentication. Verification code: Linux rasproot 3.2.27+ #250 PREEMPT Thu Oct 18 19:03:02 BST 2012 armv6l
If you get stuck in a loop, you might have a time problem. Give it a few minutes and try again. Then it is troubleshooting time.