Skip to content

Commit bf40e00

Browse files
authored
Merge pull request #21 from pieterlange/feature/otp
port google OTP code from kylemanna/openvpn
2 parents 81ec1d5 + 68ca628 commit bf40e00

File tree

4 files changed

+49
-1
lines changed

4 files changed

+49
-1
lines changed

Dockerfile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ MAINTAINER Pieter Lange <pieter@ptlc.nl>
55

66
RUN echo "http://dl-4.alpinelinux.org/alpine/edge/community/" >> /etc/apk/repositories && \
77
echo "http://dl-4.alpinelinux.org/alpine/edge/testing/" >> /etc/apk/repositories && \
8-
apk add --update openvpn iptables bash easy-rsa libintl inotify-tools && \
8+
apk add --update openvpn iptables bash easy-rsa libintl inotify-tools openvpn-auth-pam google-authenticator pamtester && \
99
apk add --virtual build_deps gettext && \
1010
cp /usr/bin/envsubst /usr/local/bin/envsubst && \
1111
ln -s /usr/share/easy-rsa/easyrsa /usr/local/bin && \
@@ -34,4 +34,7 @@ COPY entrypoint.sh /sbin/entrypoint.sh
3434
COPY watch-portmapping.sh /sbin/watch-portmapping.sh
3535
COPY openvpn.tmpl $OVPN_TEMPLATE
3636

37+
# Add support for OTP authentication using a PAM module
38+
ADD ./otp/openvpn /etc/pam.d/
39+
3740
CMD ["/sbin/entrypoint.sh"]

bin/ovpn_otp_user

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#!/bin/bash
2+
3+
#
4+
# Generate OpenVPN users via google authenticator
5+
#
6+
7+
if [ -z $1 ]; then
8+
echo "Usage: ovpn_otp_user USERNAME"
9+
exit 1
10+
fi
11+
12+
# Server name is in the form "udp://vpn.example.com:1194"
13+
if [[ "$OVPN_SERVER_URL" =~ ^((udp|tcp)://)?([0-9a-zA-Z\.\-]+)(:([0-9]+))?$ ]]; then
14+
OVPN_PROTO=${BASH_REMATCH[2]};
15+
OVPN_CN=${BASH_REMATCH[3]};
16+
OVPN_PORT=${BASH_REMATCH[5]};
17+
else
18+
echo "Need to pass in OVPN_SERVER_URL in 'proto://fqdn:port' format"
19+
exit 1
20+
fi
21+
22+
# Ensure the otp folder is present
23+
[ -d /etc/openvpn/otp ] || mkdir -p /etc/openvpn/otp
24+
25+
# Binary is present in image, save an $user.google_authenticator file in /etc/openvpn/otp
26+
if [ "$2" == "interactive" ]; then
27+
# Authenticator will ask for other parameters. User can choose rate limit, token reuse policy and time window policy
28+
# Always use time base OTP otherwise storage for counters must be configured somewhere in volume
29+
google-authenticator --time-based --force -l "${1}@${OVPN_CN}" -s /etc/openvpn/otp/${1}.google_authenticator
30+
else
31+
google-authenticator --time-based --disallow-reuse --force --rate-limit=3 --rate-time=30 --window-size=3 \
32+
-l "${1}@${OVPN_CN}" -s /etc/openvpn/otp/${1}.google_authenticator
33+
fi

entrypoint.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ if [ -r $OVPN_CRL ]; then
7676
addArg "--crl-verify" "$OVPN_CRL"
7777
fi
7878

79+
# Optional OTP authentication support
80+
if [ -d "${OVPN_OTP_AUTH:-}" ]; then
81+
addArg "--plugin" "/usr/lib/openvpn/plugins/openvpn-plugin-auth-pam.so" "openvpn"
82+
fi
83+
7984
if [ $DEBUG ]; then
8085
echo "openvpn.conf:"
8186
cat $OVPN_CONFIG

otp/openvpn

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Uses google authenticator library as PAM module using a single folder for all users tokens
2+
# User root is required to stick with an hardcoded user when trying to determine user id and allow unexisting system users
3+
# See https://github.com/google/google-authenticator/tree/master/libpam#secretpathtosecretfile--usersome-user
4+
auth required pam_google_authenticator.so secret=${OVPN_OTP}/${USER}.google_authenticator user=root
5+
6+
# Accept any user since we're dealing with virtual users there's no need to have a system account (pam_unix.so)
7+
account sufficient pam_permit.so

0 commit comments

Comments
 (0)