adds 2fa ssh post

This commit is contained in:
Wxcafé (Clément Hertling) 2017-11-24 16:30:10 +01:00
parent bfea28c2a7
commit cdb0e0c10e
2 changed files with 133 additions and 1 deletions

View File

@ -4,7 +4,7 @@ if [[ -z "$@" ]]; then
exit 1 exit 1
fi fi
title="$@" title="$@"
filename="$(echo $@ | tr ' ' '_' | tr '[:upper:]' '[:lower:]')" filename="content/$(echo $@ | tr ' ' '_' | tr '[:upper:]' '[:lower:]')"
if [[ -e $filename.md ]]; then if [[ -e $filename.md ]]; then
echo "$filename.md already exists" echo "$filename.md already exists"
exit 1 exit 1

View File

@ -0,0 +1,132 @@
Title: 2fa SSH on Linux, and deploying it via Puppet
Date: 2017-11-24T13:11+01:00
Author: Wxcafé
Category:
Slug: 2fa_ssh_on_linux,and_deploying_it_via_puppet
So, I recently (on Monday, 11/20/17) started at a new job! Aside from all the new
stuff that implies, and that is much more important overall, I received
a Yubikey Neo key to be used for two-factor authentication on various internal
services. I found this pretty cool, started using it, and thought no more of it.
Then the next day, I tried to SSH to my server for some reason and found out
that I could obviously not log in since I didn't have my key. So I thought for
a minute, didn't find any way to enter my infrastructure when I don't have my
key, and took note to do whatever I was planning that evening.
After a bit of time I put two and two together and thought I could probably try
to add 2fa (TOTP, Time-based One Time Password + username) as an alternative
authentication method to RSA public key. So I looked a bit and ended up setting
that up. Here's how it works.
So as you might know, authentication on Linux is handled by PAM (Pluggable
Authentication Modules). As the name implies, it's made of modules that you can
simply plug onto the existing authentication mechanism. And thankfully, someone
developped a TOTP module for PAM, which is named `libpam_google_authenticator`
(which is not a very good name, but I'm not gonna complain if I can get it
working). So the plan is to install that module (pretty easy, since it's
packaged by most linux distros), then configure ssh to use it to auth users.
*That's* done by editing the `/etc/pam.d/sshd` file, and setting it up like so:
```ini
# PAM configuration for the Secure Shell service
### This is the important part. It adds the module and marks it as a required
### authentication method.
##
auth required pam_google_authenticator.so
##
@include common-auth
# Disallow non-root logins when /etc/nologin exists.
account required pam_nologin.so
# Uncomment and edit /etc/security/access.conf if you need to set complex
# access limits that are hard to express in sshd_config.
# account required pam_access.so
# Standard Un*x authorization.
@include common-account
# SELinux needs to be the first session rule. This ensures that any
# lingering context has been cleared. Without this it is possible that a
# module could execute code in the wrong domain.
session [success=ok ignore=ignore module_unknown=ignore default=bad]
pam_selinux.so close
# ... nothing else interesting until end of file
```
Now that this is done, we need to change sshd's config, to allow it to present
the prompt for the TOTP code and tell it to fallback to keyboard-interactive if
publickey auth doesn't work. To do that, we add these lines to
`/etc/ssh/sshd_config`:
```sshd
UsePam yes
ChallengeResponseAuthentication yes
AuthenticationMethods publickey keyboard-interactive:pam
```
**Be careful, this will allow users to login with TOTP+pass even if **
`PasswordAuthentication` **is set to** `no`
Once this is done, we need to generate a secret for the TOTP generator.
`libpam_google_authenticator` has a tool for this named ...
`google-authenticator`. Once you run it, it'll ask a few questions, display
a QR-code on the screen, give you a private key and a few recovery codes, and
write all this into a file named `~/.google_authenticator`. Scan the QR code or
add the private key into your TOTP client (an app on your phone, a linux CLI
client, whatever. I use OTP Auth on iOS.)
Once that's done, you can try to use that authentication by running `ssh -o
PubkeyAuthentication=no whatever.space`. It should ask you for your
"Verification Code", which is the TOTP, and then your password, and then let you
log in. Done, you have 2fa on SSH now 😄
Now for the puppet setup:
```ruby
package {'libpam-google-authenticator':
ensure => present,
}
file {'/etc/pam.d/sshd':
ensure => present,
content => file('base/pam/sshd'),
owner => 'root',
group => 'root',
}
file {'/home/wxcafe/.google_authenticator':
ensure => present,
content => file(modules/base/google_authenticator,
owner => 'wxcafe',
group => 'wxcafe',
mode => '0600',
}
file {'/etc/ssh/sshd_config':
ensure => present,
content => file('base/ssh/sshd_config'),
}
```
Yeah, I know, this is pretty generic. It was a bit harder for me because I use
a git repo for my dotfiles, and as such I have a `git` block and an `exec` block
to chmod 600 the .google_authenticator file, and I had a bit of trouble trying
to use a `file` block inside another `file` block (setting the mode of the file
inside dotfiles git repo) (if you're wondering, puppet simply ignores the
least-specific block here... I spent a while wondering why my files wouldn't
copy...)
Either way it should work alright. You might also notice that I just deploy the
.google_authenticator file on every machine, and think that's not a very good
security practice. I think it's alright, a TOTP is basically identical
security-wise to 10 TOTPs, as long as the key doesn't leak, and the increased
usability of not having to keep tens of TOTP codes on my phone is clearly worth
it.