52 Commits

Author SHA1 Message Date
98f9681d3e Merge pull request #122 from TheNotary/readme-debug-section
Debugging tips added to readme
2016-04-23 16:21:48 -07:00
74ba753f70 Created a debug section in readme 2016-04-23 10:52:39 -07:00
cd8fd6afaa Merge pull request #119 from rudijs/fragment-option
Add openvpn.conf gerneration -f fragment directive option
2016-04-11 18:54:59 -07:00
9ea4815a74 Fix incorrect local image being used 2016-04-06 15:21:13 +08:00
74bfad0aac Add openvpn.conf gerneration -f fragment directive option 2016-04-06 15:06:02 +08:00
ed51116fb6 docs: Add contribution guidelines
* High level overview of contribution guidelines.
2016-04-04 23:49:14 -07:00
eb22992a2f Merge pull request #102 from fabn/otp
Two factor authentication using a token application
2016-03-14 07:42:30 -07:00
286676879d Merge pull request #107 from croepha/selinux
Updated SELinux docs
2016-02-23 21:56:59 -08:00
42bf842202 Updated SELinux docs
for hosts not allowing module loading
2016-02-23 12:05:13 -06:00
bd51bb273e Merge pull request #104 from croepha/selinux
Selinux policy and docs
2016-02-17 15:07:15 -08:00
70b70e298d Merge pull request #105 from mypetyak/master
Added documentation details on using TCP protocol.
2016-02-17 15:06:43 -08:00
95c260a97a Added documentation details on using TCP protocol. 2016-02-16 22:44:10 -08:00
35c9103454 Updated Alpine Linux packages, including pamtester 2016-02-15 21:01:52 +01:00
d481313311 Back to Alpine Linux using packaged version of google-authenticator 2016-02-11 18:10:51 +01:00
9b824fb35a Fix typo 2016-02-10 13:01:54 -06:00
7a9abf4c14 Update README.md 2016-02-10 12:37:56 -06:00
44055aa687 added docs for SELinux policy file 2016-02-10 12:34:35 -06:00
8356a664d8 Added linux policy file 2016-02-10 12:25:45 -06:00
ba7b925a9f Using a different volume name for otp test, should allow tests to run 2016-02-10 17:12:49 +01:00
517ad6aeb2 Implemented tests for 2 factor authentication 2016-02-10 16:59:15 +01:00
9c6f3311a1 Fix for Dockerfile, trailing slash is needed. 2016-02-07 14:45:28 +01:00
dc4656ef48 OTP documentation 2016-02-07 14:30:56 +01:00
e8d93ea4fa Use $USER@$OVPN_CN for OTP label. 2016-02-07 13:22:20 +01:00
10dd404159 Fixes pam authentication when dealing with virtual users 2016-02-07 03:48:44 +01:00
607063b358 Do not cache user credentials 2016-02-07 02:53:43 +01:00
bb3d1add3c Export user pass option in client when OTP is enabled 2016-02-06 21:40:11 +01:00
c24a22deea Allow interactive usage 2016-02-06 21:38:26 +01:00
6084261943 Improved script for user OTP generation, tested with pamtester 2016-02-06 21:31:08 +01:00
5ca92a2c5e Fixed configuration for pam module to allow login of non existing user accounts, i.e. VPN only users. 2016-02-06 21:20:34 +01:00
dd719c1f11 Save OTP variable in server env 2016-02-06 20:25:03 +01:00
6fcebf9adb Server side configuration for OTP 2016-02-06 20:23:59 +01:00
86d2a52f85 Install google authenticator in jessie 2016-02-06 19:45:42 +01:00
1623afe651 Reverted to debian jessie 2016-02-06 19:40:54 +01:00
e7d0d4ea0e ovpn_run: Fix sysctl IPv6 forwarding write
* I'm not sure if this ever worked without the `-w` flag.  Perhaps in an
  old version of sysctl?
2015-12-29 13:33:55 -08:00
e50f4dcc23 Merge pull request #90 from ypid/added-badges
Added badges showing a few key facts next to the CI status.
2015-12-21 16:05:35 -08:00
96d17bb5a7 Added badges showing a few key facts next to the CI status.
* Updated Docker Hub URL to new schema.
2015-12-21 22:19:22 +01:00
f2111006ad Merge pull request #82 from vielmetti/patch-1
Split tunnels, as documented in #51
2015-11-30 13:43:22 -08:00
d520a58ec4 Split tunnels, as documented in #51
Taking text from #51 and putting in into the FAQ to make it that much easier to find.
2015-11-30 16:27:46 -05:00
1c290e60db Merge branch 'compression'
Closes #81
2015-11-29 10:16:13 -08:00
2fa3abe064 fixed getopts argument typo. removed ":" before "z" 2015-11-29 10:15:15 -08:00
2650d4a286 COMP-lzo param is set in client config, if defined in server. 2015-11-29 10:15:15 -08:00
2abbcf1999 added config param to enable COMP-LZO compression 2015-11-29 10:14:07 -08:00
818e8682d1 Dockerfile: EasyRSA is in community now
* No longer in testing.
2015-11-28 09:10:55 -08:00
3edc12a6b7 Merge pull request #78 from gdb/gdb/master
Respect the -D flag
2015-11-01 10:38:26 -08:00
ded4414ef4 Respect the -D flag
It looks like edfbffb85f caused the
OVPN_DNS variable to start being ignored, meaning the -D flag was a
no-op.
2015-10-31 19:39:32 -07:00
f277449569 Merge pull request #76 from discordianfish/push-custom-dns-servers
Support pushing custom DNS servers
2015-10-16 07:44:53 -07:00
edfbffb85f Support pushing custom DNS servers 2015-10-16 15:41:22 +02:00
98cf2128c7 Merge pull request #70 from kylemanna/alpine
Switch to Alpine for Base
2015-10-04 08:24:18 -07:00
c3d526fd67 Merge branch 'master' into alpine 2015-09-29 11:43:08 -07:00
ba7860cced Merge branch 'travis-ci' into alpine 2015-09-22 15:03:20 -07:00
23f66094ff alpine: Use easy-rsa in testing branch of alpine
* Simplifes the Dockerfile significantly.
* No need for curl.
2015-09-10 10:33:05 -07:00
3da0efa5bc alpine: Use alpine as base image instead of Debian
* Debian Jessie -> Alpine 3.2: 150MB -> 15MB
2015-09-08 10:07:16 -07:00
15 changed files with 427 additions and 18 deletions

35
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,35 @@
# Contributing to docker-openvpn
Community contributions are welcome and help move the project along. Please review this document before sending any pull requests.
Thanks!
## Bug Fixes
All bug fixes are welcome. Please try to add a test if the bug is something that should have been fixed already. Oops.
## Feature Additions
New features are welcome provided that the feature has a general audience and is reasonably simple. The goal of the repository is to support a wide audience and be simple enough.
Please add new documentation in the `docs` folder for any new features. Pull requests for missing documentation is welcome as well. Keep the `README.md` focused on the most popular use case, details belong in the docs directory.
If you have a special feature, you're likely to try but it will likely be rejected if not too many people seem interested.
## Tests
In an effort to not repeat bugs (and break less popular features), unit tests are run on [Travis CI](https://travis-ci.org/kylemanna/docker-openvpn). The goal of the tests are to be simple and to be placed in the `tests` directory where it will be automatically run. Review existing tests for an example.
## Style
The style of the repo follows that of the Linux kernel, in particular:
* Pull requests should be rebased to small atomic commits so that the merged history is more coherent
* The subject of the commit should be in the form "<subsystem>: <subject>"
* More details in the body
* Match surrounding coding style (line wrapping, spaces, etc)
More details in the [SubmittingPatches](https://www.kernel.org/doc/Documentation/SubmittingPatches) document included with the Linux kernel. In particular the following sections:
* `2) Describe your changes`
* `3) Separate your changes`

View File

@ -1,21 +1,19 @@
# Original credit: https://github.com/jpetazzo/dockvpn
# Leaner build then Ubunutu
FROM debian:jessie
# Smallest base image
FROM alpine:3.2
MAINTAINER Kyle Manna <kyle@kylemanna.com>
RUN apt-get update && \
apt-get install -y openvpn iptables curl && \
apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
RUN mkdir -p /usr/local/share/easy-rsa && \
curl -L https://github.com/OpenVPN/easy-rsa/archive/v3.0.0.tar.gz | tar xzf - --strip=1 -C /usr/local/share/easy-rsa easy-rsa-3.0.0/easyrsa3 && \
ln -s /usr/local/share/easy-rsa/easyrsa3/easyrsa /usr/local/bin
RUN echo "http://dl-4.alpinelinux.org/alpine/edge/community/" >> /etc/apk/repositories && \
echo "http://dl-4.alpinelinux.org/alpine/edge/testing/" >> /etc/apk/repositories && \
apk add --update openvpn iptables bash easy-rsa openvpn-auth-pam google-authenticator pamtester && \
ln -s /usr/share/easy-rsa/easyrsa /usr/local/bin && \
rm -rf /tmp/* /var/tmp/* /var/cache/apk/*
# Needed by scripts
ENV OPENVPN /etc/openvpn
ENV EASYRSA /usr/local/share/easy-rsa/easyrsa3
ENV EASYRSA /usr/share/easy-rsa
ENV EASYRSA_PKI $OPENVPN/pki
ENV EASYRSA_VARS_FILE $OPENVPN/vars
@ -29,3 +27,6 @@ CMD ["ovpn_run"]
ADD ./bin /usr/local/bin
RUN chmod a+x /usr/local/bin/*
# Add support for OTP authentication using a PAM module
ADD ./otp/openvpn /etc/pam.d/

View File

@ -1,6 +1,10 @@
# OpenVPN for Docker
[![Build Status](https://travis-ci.org/kylemanna/docker-openvpn.svg)](https://travis-ci.org/kylemanna/docker-openvpn)
[![Docker Stars](https://img.shields.io/docker/stars/kylemanna/openvpn.svg)](https://hub.docker.com/r/kylemanna/openvpn/)
[![Docker Pulls](https://img.shields.io/docker/pulls/kylemanna/openvpn.svg)](https://hub.docker.com/r/kylemanna/openvpn/)
[![ImageLayers Size](https://img.shields.io/imagelayers/image-size/kylemanna/openvpn/latest.svg)](https://hub.docker.com/r/kylemanna/openvpn/)
[![ImageLayers Layers](https://img.shields.io/imagelayers/layers/kylemanna/openvpn/latest.svg)](https://hub.docker.com/r/kylemanna/openvpn/)
OpenVPN server in a Docker container complete with an EasyRSA PKI CA.
@ -9,7 +13,7 @@ a corresponding [Digital Ocean Community Tutorial](http://bit.ly/1AGUZkq).
#### Upstream Links
* Docker Registry @ [kylemanna/openvpn](https://registry.hub.docker.com/u/kylemanna/openvpn)
* Docker Registry @ [kylemanna/openvpn](https://hub.docker.com/r/kylemanna/openvpn/)
* GitHub @ [kylemanna/docker-openvpn](https://github.com/kylemanna/docker-openvpn)
#### Example Service
@ -45,9 +49,21 @@ a corresponding [Digital Ocean Community Tutorial](http://bit.ly/1AGUZkq).
docker run --volumes-from $OVPN_DATA --rm kylemanna/openvpn ovpn_getclient CLIENTNAME > CLIENTNAME.ovpn
## Debugging Tips
* Create an environment variable with the name DEBUG and value of 1 to enable debug output (using "docker -e").
docker run --volumes-from $OVPN_DATA -d -p 1194:1194/udp --privileged -e DEBUG=1 kylemanna/openvpn
docker run --volumes-from $OVPN_DATA -p 1194:1194/udp --privileged -e DEBUG=1 kylemanna/openvpn
* Test using a client that has openvpn installed correctly
$ openvpn --config CLIENTNAME.ovpn
* Run through a barrage of debugging checks on the client if things don't just work
$ ping 8.8.8.8 # checks connectivity without touching name resolution
$ dig google.com # won't use the search directives in resolv.conf
$ nslookup google.com # will use search
## How Does It Work?
@ -75,6 +91,7 @@ Conveniently, `kylemanna/openvpn` comes with a script called `ovpn_getclient`,
which dumps an inline OpenVPN client configuration file. This single file can
then be given to a client for access to the VPN.
To enable Two Factor Authentication for clients (a.k.a. OTP) see [this document](/docs/otp.md).
## OpenVPN Details
@ -167,3 +184,8 @@ of a guarantee in the future.
* OpenVPN core 3.0 android armv7a thumb2 32-bit
* OS X Mavericks with Tunnelblick 3.4beta26 (build 3828) using openvpn-2.3.4
* ArchLinux OpenVPN pkg 2.3.4-1
*
## Having permissions issues with Selinux enabled?
See [this](docs/selinux.md)

View File

@ -37,17 +37,21 @@ usage() {
echo " [-s SERVER_SUBNET]"
echo " [-r ROUTE ...]"
echo " [-p PUSH ...]"
echo " [-n DNS_SERVER ...]"
echo
echo "optional arguments:"
echo " -d Disable NAT routing and default route"
echo " -c Enable client-to-client option"
echo " -D Disable built in external dns (google dns)"
echo " -D Do not push dns servers"
echo " -N Configure NAT to access external server network"
echo " -m Set client MTU"
echo " -t Use TAP device (instead of TUN device)"
echo " -T Encrypt packets with the given cipher algorithm instead of the default one (tls-cipher)."
echo " -C A list of allowable TLS ciphers delimited by a colon (cipher)."
echo " -a Authenticate packets with HMAC using the given message digest algorithm (auth)."
echo " -z Enable comp-lzo compression."
echo " -2 Enable two factor authentication using Google Authenticator."
echo " -f Set the fragment directive."
}
if [ "$DEBUG" == "1" ]; then
@ -67,6 +71,8 @@ OVPN_ROUTES=()
TMP_ROUTES=()
OVPN_PUSH=()
TMP_PUSH=()
OVPN_DNS_SERVERS=("8.8.8.8" "8.8.4.4")
TMP_DNS_SERVERS=()
OVPN_TLS_CIPHER=''
OVPN_CIPHER=''
OVPN_AUTH=''
@ -75,7 +81,7 @@ OVPN_AUTH=''
[ -r "$OVPN_ENV" ] && source "$OVPN_ENV"
# Parse arguments
while getopts ":a:C:T:r:s:du:cp:DNm:t" opt; do
while getopts ":a:C:T:r:s:du:cp:n:DNmf:tz2" opt; do
case $opt in
a)
OVPN_AUTH="$OPTARG"
@ -104,6 +110,9 @@ while getopts ":a:C:T:r:s:du:cp:DNm:t" opt; do
p)
TMP_PUSH+=("$OPTARG")
;;
n)
TMP_DNS_SERVERS+=("$OPTARG")
;;
D)
OVPN_DNS=0
;;
@ -116,6 +125,15 @@ while getopts ":a:C:T:r:s:du:cp:DNm:t" opt; do
t)
OVPN_DEVICE="tap"
;;
z)
OVPN_COMP_LZO=1
;;
2)
OVPN_OTP_AUTH=1
;;
f)
OVPN_FRAGMENT=$OPTARG
;;
\?)
set +x
echo "Invalid option: -$OPTARG" >&2
@ -137,6 +155,9 @@ done
# if new push directives were not defined with -p, use default
[ ${#TMP_PUSH[@]} -gt 0 ] && OVPN_PUSH=("${TMP_PUSH[@]}")
# if dns servers were not defined with -n, use google nameservers
[ ${#TMP_DNS_SERVERS[@]} -gt 0 ] && OVPN_DNS_SERVERS=("${TMP_DNS_SERVERS[@]}")
# Server name is in the form "udp://vpn.example.com:1194"
if [[ "$OVPN_SERVER_URL" =~ ^((udp|tcp)://)?([0-9a-zA-Z\.\-]+)(:([0-9]+))?$ ]]; then
OVPN_PROTO=${BASH_REMATCH[2]};
@ -158,6 +179,9 @@ export OVPN_SERVER OVPN_ROUTES OVPN_DEFROUTE
export OVPN_SERVER_URL OVPN_ENV OVPN_PROTO OVPN_CN OVPN_PORT
export OVPN_CLIENT_TO_CLIENT OVPN_PUSH OVPN_NAT OVPN_DNS OVPN_MTU OVPN_DEVICE
export OVPN_TLS_CIPHER OVPN_CIPHER OVPN_AUTH
export OVPN_COMP_LZO
export OVPN_OTP_AUTH
export OVPN_FRAGMENT
# Preserve config
if [ -f "$OVPN_ENV" ]; then
@ -202,8 +226,13 @@ EOF
[ -n "$OVPN_AUTH" ] && echo "auth $OVPN_AUTH" >> "$conf"
[ -n "$OVPN_CLIENT_TO_CLIENT" ] && echo "client-to-client" >> "$conf"
[ "$OVPN_DNS" == "1" ] && echo push "dhcp-option DNS 8.8.4.4" >> "$conf"
[ "$OVPN_DNS" == "1" ] && echo push "dhcp-option DNS 8.8.8.8" >> "$conf"
[ -n "$OVPN_COMP_LZO" ] && echo "comp-lzo" >> "$conf"
[ -n "$OVPN_FRAGMENT" ] && echo "fragment $OVPN_FRAGMENT" >> "$conf"
[ "$OVPN_DNS" == "1" ] && for i in "${OVPN_DNS_SERVERS[@]}"; do
echo "push dhcp-option DNS $i" >> "$conf"
done
# Append Routes
for i in "${OVPN_ROUTES[@]}"; do
# If user passed "0" skip this, assume no extra routes
@ -216,6 +245,12 @@ for i in "${OVPN_PUSH[@]}"; do
echo push \"$i\" >> "$conf"
done
# Optional OTP authentication support
if [ -n "$OVPN_OTP_AUTH" ]; then
echo -e "\n\n# Enable OTP+PAM for user authentication" >> "$conf"
echo "plugin /usr/lib/openvpn/plugins/openvpn-plugin-auth-pam.so openvpn" >> "$conf"
fi
set +e
# Clean-up duplicate configs

View File

@ -84,6 +84,15 @@ $OVPN_ADDITIONAL_CLIENT_CONFIG
if [ -n "$OVPN_AUTH" ]; then
echo "auth $OVPN_AUTH"
fi
if [ -n "$OVPN_OTP_AUTH" ]; then
echo "auth-user-pass"
echo "auth-nocache"
fi
if [ -n "$OVPN_COMP_LZO" ]; then
echo "comp-lzo"
fi
}
dir="$OPENVPN/clients/$cn"

33
bin/ovpn_otp_user Executable file
View File

@ -0,0 +1,33 @@
#!/bin/bash
#
# Generate OpenVPN users via google authenticator
#
if ! source "$OPENVPN/ovpn_env.sh"; then
echo "Could not source $OPENVPN/ovpn_env.sh."
exit 1
fi
if [ "x$OVPN_OTP_AUTH" != "x1" ]; then
echo "OTP authentication not enabled, please regenerate configuration using -2 flag"
exit 1
fi
if [ -z $1 ]; then
echo "Usage: ovpn_otp_user USERNAME"
exit 1
fi
# Ensure the otp folder is present
[ -d /etc/openvpn/otp ] || mkdir -p /etc/openvpn/otp
# Binary is present in image, save an $user.google_authenticator file in /etc/openvpn/otp
if [ "$2" == "interactive" ]; then
# Authenticator will ask for other parameters. User can choose rate limit, token reuse policy and time window policy
# Always use time base OTP otherwise storage for counters must be configured somewhere in volume
google-authenticator --time-based --force -l "${1}@${OVPN_CN}" -s /etc/openvpn/otp/${1}.google_authenticator
else
google-authenticator --time-based --disallow-reuse --force --rate-limit=3 --rate-time=30 --window-size=3 \
-l "${1}@${OVPN_CN}" -s /etc/openvpn/otp/${1}.google_authenticator
fi

View File

@ -55,8 +55,8 @@ if [ $? = 0 ]; then
# If this fails, ensure the docker container is run with --privileged
# Could be side stepped with `ip netns` madness to drop privileged flag
sysctl net.ipv6.conf.default.forwarding=1 || echo "Failed to enable IPv6 Forwarding default"
sysctl net.ipv6.conf.all.forwarding=1 || echo "Failed to enable IPv6 Forwarding"
sysctl -w net.ipv6.conf.default.forwarding=1 || echo "Failed to enable IPv6 Forwarding default"
sysctl -w net.ipv6.conf.all.forwarding=1 || echo "Failed to enable IPv6 Forwarding"
fi
if [ "$#" -gt 0 ]; then

10
docs/docker-openvpn.te Normal file
View File

@ -0,0 +1,10 @@
module docker-openvpn 1.0;
require {
type svirt_lxc_net_t;
class tun_socket create;
}
#============= svirt_lxc_net_t ==============
allow svirt_lxc_net_t self:tun_socket create;

View File

@ -12,3 +12,9 @@ Use a Docker image with a text editor pre-installed (i.e. Ubuntu) and connect th
The run-time image (`kylemanna/openvpn`) is intended to be an ephemeral image. Nothing should be saved in it so that it can be re-downloaded and re-run when updates are pushed (i.e. newer version of OpenVPN or even Debian). The data container contains all this data and is attached at run time providing a safe home.
If it was all in one container, an upgrade would require a few steps to extract all the data, perform some upgrade import, and re-run. This technique is also prone to people losing their EasyRSA PKI when they forget where it was. With everything in the data container upgrading is as simple as re-running `docker pull kylemanna/openvpn` and then `docker run ... kylemanna/openvpn`.
## How do I set up a split tunnel?
Split tunnels are configurations where only some of the traffic from a client goes to the VPN, with the remainder routed through the normal non-VPN interfaces. You'll want to disable a default route (-d) when you generate the configuration, but still use NAT (-N) to keep network address translation enabled.
ovpn_genconfig -N -d ...

72
docs/otp.md Normal file
View File

@ -0,0 +1,72 @@
# Using two factor authentication for users
Instead of relying on complex passwords for client certificates (that usually get written somewhere) this image
provides support for two factor authentication with OTP devices.
The most common app that provides OTP generation is Google Authenticator ([iOS](https://itunes.apple.com/it/app/google-authenticator/id388497605?mt=8) and
[Android](https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2&hl=it)) you can download it
and use this image to generate user configuration.
## Usage
In order to enable two factor authentication the following steps are required.
* Generate server configuration with `-2` option
docker run --volumes-from $OVPN_DATA --rm fabn/openvpn ovpn_genconfig -u udp://vpn.example.com -2
* Generate your client certificate (possibly without a password since you're using OTP)
docker run --volumes-from $OVPN_DATA --rm -it fabn/openvpn easyrsa build-client-full <user> nopass
* Generate authentication configuration for your client. -t is needed to show QR code, -i is optional for interactive usage
docker run --volumes-from $OVPN_DATA --rm -t fabn/openvpn ovpn_otp_user <user>
The last step will generate OTP configuration for the provided user with the following options
```
google-authenticator --time-based --disallow-reuse --force --rate-limit=3 --rate-time=30 --window-size=3 \
-l "${1}@${OVPN_CN}" -s /etc/openvpn/otp/${1}.google_authenticator
```
It will also show a shell QR code in terminal you can scan with the Google Authenticator application. It also provides
a link to a google chart url that will display a QR code for the authentication.
**Do not share QR code (or generated url) with anyone but final user, that is your second factor for authentication
that is used to generate OTP codes**
Here's an example QR code generated for an hypotetical user@example.com user.
![Example QR Code](https://www.google.com/chart?chs=200x200&chld=M|0&cht=qr&chl=otpauth://totp/user@example.com%3Fsecret%3DKEYZ66YEXMXDHPH5)
Generate client configuration for `<user>` and import it in OpenVPN client. On connection it will prompt for user and password.
Enter your username and a 6 digit code generated by Authenticator app and you're logged in.
## TL;DR
Under the hood this configuration will setup an `openvpn` PAM service configuration (`/etc/pam.d/openvpn`)
that relies on the awesome [Google Authenticator PAM module](https://github.com/google/google-authenticator).
In this configuration the `auth` part of PAM flow is managed by OTP codes and the `account` part is not enforced
because you're likely dealing with virtual users and you do not want to create a system account for every VPN user.
`ovpn_otp_user` script will store OTP credentials under `/etc/openvpn/otp/<user>.google_authentication`. In this
way when you take a backup OTP users are included as well.
Finally it will enable the openvpn plugin `openvpn-plugin-auth-pam.so` in server configuration and append the
`auth-user-pass` directive in client configuration.
## Debug
If something is not working you can verify your PAM setup with these commands
```
# Start a shell in container
docker run --volumes-from $OVPN_DATA --rm -it fabn/openvpn bash
# Then in container install pamtester utility
apt-get update && apt-get install -y pamtester
# To check authentication use this command that will prompt for a valid code from Authenticator APP
pamtester -v openvpn <user> authenticate
```
If you configured everything correctly you should get authenticated by entering a OTP code from the app.

25
docs/selinux.md Normal file
View File

@ -0,0 +1,25 @@
# For hosts that use SELinux
Try this [policy file](docker-openvpn.te)
Run these commands to compile and load it:
```
checkmodule -M -m -o docker-openvpn.mod docker-openvpn.te
semodule_package -o docker-openvpn.pp -m docker-openvpn.mod
sudo semodule -i docker-openvpn.pp
```
Also, some configurations don't allow containers to load kernel modules, so on the host run this:
```
sudo modprobe tun
```
So the container doesn't have to load the `tun` module.
# Still having issues?
In January 2016, Fedora based systems got an update that fixed an issue for labeling namespaced net objects under /proc
to fix, make sure that you have run `sudo dnf update` and you need to reboot to load the new policies

18
docs/tcp.md Normal file
View File

@ -0,0 +1,18 @@
# TCP Protocol
## TCP vs. UDP - Pros & Cons
By default, OpenVPN is configured to use the UDP protocol. Because UDP incurs minimal protocol overhead (for example, no acknowledgment is required upon successful packet receipt), it can sometimes result in slightly faster throughput. However, in situations where VPN service is needed over an unreliable connection, the user experience can benefit from the extra diagnostic features of the TCP protocol.
As an example, users connecting from an airplane wifi network may experience high packet drop rates, where the error detection and sliding window control of TCP can more readily adjust to the inconsistent connection.
## Using TCP
Those requiring TCP connections should initialize the data container by specifying the TCP protocol and port number:
docker run --volumes-from $OVPN_DATA --rm kylemanna/openvpn ovpn_genconfig -u tcp://VPN.SERVERNAME.COM:443
docker run --volumes-from $OVPN_DATA --rm -it kylemanna/openvpn ovpn_initpki
Because the server container always exposes port 1194, regardless of the
specified protocol, adjust the mapping appropriately:
docker run --volumes-from $OVPN_DATA -d -p 443:1194/tcp --cap-add=NET_ADMIN kylemanna/openvpn

7
otp/openvpn Normal file
View File

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

View File

@ -0,0 +1,55 @@
#!/bin/bash
OVPN_DATA=opvn-data
IMG=kylemanna/openvpn
# Function to fail
abort() { cat <<< "$@" 1>&2; exit 1; }
#
# Create a docker container with the config data
#
sudo docker run --name $OVPN_DATA -v /etc/openvpn busybox
#
# Generate openvpn.config file
#
SERV_IP=$(ip -4 -o addr show scope global | awk '{print $4}' | sed -e 's:/.*::' | head -n1)
sudo docker run --volumes-from $OVPN_DATA --rm $IMG ovpn_genconfig -u udp://$SERV_IP -f 1400
#
# grep for config lines from openvpn.conf
# add more tests for more configs as required
#
# 1. verb config
CONFIG_REQUIRED_VERB="verb 3"
CONFIG_MATCH_VERB=$(sudo docker run --rm -it --volumes-from $OVPN_DATA busybox grep verb /etc/openvpn/openvpn.conf)
# 2. fragment config
CONFIG_REQUIRED_FRAGMENT="fragment 1400"
CONFIG_MATCH_FRAGMENT=$(sudo docker run --rm -it --volumes-from $OVPN_DATA busybox grep fragment /etc/openvpn/openvpn.conf)
#
# Clean up
#
# sudo docker rm -f $OVPN_DATA
#
# Tests
#
if [[ $CONFIG_MATCH_VERB =~ $CONFIG_REQUIRED_VERB ]]
then
echo "==> Config match found: $CONFIG_REQUIRED_VERB == $CONFIG_MATCH_VERB"
else
abort "==> Config match not found: $CONFIG_REQUIRED_VERB != $CONFIG_MATCH_VERB"
fi
if [[ $CONFIG_MATCH_FRAGMENT =~ $CONFIG_REQUIRED_FRAGMENT ]]
then
echo "==> Config match found: $CONFIG_REQUIRED_FRAGMENT == $CONFIG_MATCH_FRAGMENT"
else
abort "==> Config match not found: $CONFIG_REQUIRED_FRAGMENT != $CONFIG_MATCH_FRAGMENT"
fi

81
tests/otp.sh Executable file
View File

@ -0,0 +1,81 @@
#!/bin/bash
set -ex
OVPN_DATA=basic-data-otp
CLIENT=travis-client
IMG=kylemanna/openvpn
OTP_USER=otp
# Function to fail
abort() { cat <<< "$@" 1>&2; exit 1; }
#
# Create a docker container with the config data
#
docker run --name $OVPN_DATA -v /etc/openvpn busybox
ip addr ls
SERV_IP=$(ip -4 -o addr show scope global | awk '{print $4}' | sed -e 's:/.*::' | head -n1)
# Configure server with two factor authentication
docker run --volumes-from $OVPN_DATA --rm $IMG ovpn_genconfig -u udp://$SERV_IP -2
# nopass is insecure
docker run --volumes-from $OVPN_DATA --rm -it -e "EASYRSA_BATCH=1" -e "EASYRSA_REQ_CN=Travis-CI Test CA" $IMG ovpn_initpki nopass
docker run --volumes-from $OVPN_DATA --rm -it $IMG easyrsa build-client-full $CLIENT nopass
# Generate OTP credentials for user named test, should return QR code for test user
docker run --volumes-from $OVPN_DATA --rm -it $IMG ovpn_otp_user $OTP_USER | tee client/qrcode.txt
# Ensure a chart link is printed in client OTP configuration
grep 'https://www.google.com/chart' client/qrcode.txt || abort 'Link to chart not generated'
grep 'Your new secret key is:' client/qrcode.txt || abort 'Secret key is missing'
# Extract an emergency code from textual output, grepping for line and trimming spaces
OTP_TOKEN=$(grep -A1 'Your emergency scratch codes are' client/qrcode.txt | tail -1 | tr -d '[[:space:]]')
# Token should be present
if [ -z $OTP_TOKEN ]; then
abort "QR Emergency Code not detected"
fi
# Store authentication credentials in config file and tell openvpn to use them
echo -e "$OTP_USER\n$OTP_TOKEN" > client/credentials.txt
# Override the auth-user-pass directive to use a credentials file
docker run --volumes-from $OVPN_DATA --rm $IMG ovpn_getclient $CLIENT | sed 's/auth-user-pass/auth-user-pass \/client\/credentials.txt/' | tee client/config.ovpn
#
# Fire up the server
#
sudo iptables -N DOCKER || echo 'Firewall already configured'
sudo iptables -I FORWARD -j DOCKER || echo 'Forward already configured'
# run in shell bg to get logs
docker run --name "ovpn-test" --volumes-from $OVPN_DATA --rm -p 1194:1194/udp --privileged $IMG &
#for i in $(seq 10); do
# SERV_IP=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}')
# test -n "$SERV_IP" && break
#done
#sed -ie s:SERV_IP:$SERV_IP:g client/config.ovpn
#
# Fire up a client in a container since openvpn is disallowed by Travis-CI, don't NAT
# the host as it confuses itself:
# "Incoming packet rejected from [AF_INET]172.17.42.1:1194[2], expected peer address: [AF_INET]10.240.118.86:1194"
#
docker run --rm --net=host --privileged --volume $PWD/client:/client $IMG /client/wait-for-connect.sh
#
# Client either connected or timed out, kill server
#
kill %1
#
# Celebrate
#
cat <<EOF
___________
< it worked >
-----------
\ ^__^
\ (oo)\_______
(__)\ )\/\\
||----w |
|| ||
EOF