This is kind of a brain dump of the work I did to get OpenVPN working, where MFA is provided by Google Authenticator and PAM working together.
In my case, I wanted something with low-code that can be easily replicated without debugging a python script in ten years
Prerequisites (these are beyond the scope of this howto):
- Get Debian working. In my case, that's Debian 10 on AWS EC2 (arm), but should work on all Debian 10, or 11 platforms.
- Get PAM working. In my case, I have PAM authenticating against WINBIND and ultimately an ADC for first factor (username + password).
- Get your Certificate Authority set up. In my case, I used the easy-rsa suite on a separate EC2 instance.
- Get google authenticator working. See https://github.com/google/google-authen ... /README.md
- Get OpenVPN >= 2.4.10. There's a "feature" that's included here that allows the MFA token to be passed to PAM. In my case, that meant adding the buster-backports repository and installing the openvpn/buster-backports package
Code: Select all
cat >> /etc/pam.d/openvpn << EOM
auth optional pam_faildelay.so delay=3000000
auth [success=1 default=ignore] pam_unix.so nullok_secure
auth requisite pam_deny.so
auth required pam_permit.so
auth required pam_google_authenticator.so nullok
EOM
Code: Select all
# basic tunnel configuration
port 1194
proto udp
dev tun
sndbuf 0
rcvbuf 0
keepalive 10 120
cipher AES-256-CBC
auth SHA256
link-mtu 1500
comp-lzo
# enable multi-factor authentication with google authenticator
reneg-sec 0
plugin openvpn-plugin-auth-pam.so "openvpn login USERNAME password PASSWORD 'verification code' OTP"
verify-client-cert none
username-as-common-name
# lose permissions, but read the keys before dropping permissions (persist-key)
user nobody
group nogroup
persist-key
persist-tun
# certificates and persistent ip store
ca /etc/openvpn/ca.crt
key /etc/openvpn/server/private.key
cert /etc/openvpn/server/server.crt
dh /etc/openvpn/server/dh.pem
status /etc/openvpn/status.txt
ifconfig-pool-persist /etc/openvpn/server/ipp.txt
crl-verify /etc/openvpn/server/crl.pem
# push down dns, domain and routes
topology subnet
server a.b.c.d 255.255.255.0
push "dhcp-option DNS a.b.c.e"
push "dhcp-option DNS a.b.c.f"
push "dhcp-option DOMAIN mydomain.local"
push "route 10.0.0.0 255.0.0.0"
push "block-outside-dns"
Code: Select all
client
dev tun
proto udp
sndbuf 0
rcvbuf 0
remote remote.mydomain.com 1194
link-mtu 1500
resolv-retry infinite
remote-cert-tls server
cipher AES-256-CBC
auth SHA256
comp-lzo
key-direction 1
verb 3
reneg-sec 0
auth-user-pass
static-challenge "MFA OTP" 1
<ca>
-----BEGIN CERTIFICATE-----
YOUR CA CERTIFICATE HERE
-----END CERTIFICATE-----
</ca>
- To enable IPV4 forwarding
- To adjust the FORWARD chain to ALLOW
- To remove the source/destination check in EC2 (if applicable)