2013-09-03 00:42:05 +00:00
|
|
|
# OpenVPN for Docker
|
|
|
|
|
2014-06-05 15:52:51 +00:00
|
|
|
OpenVPN server in a Docker container complete with an EasyRSA PKI CA.
|
2014-06-04 22:41:24 +00:00
|
|
|
|
2014-06-05 15:52:51 +00:00
|
|
|
## Quick Start
|
2014-06-04 22:41:24 +00:00
|
|
|
|
2014-07-09 07:07:35 +00:00
|
|
|
* Create the `$OVPN_DATA` volume container, i.e. `OVPN_DATA="ovpn-data"`
|
2014-06-04 22:41:24 +00:00
|
|
|
|
2014-07-09 07:07:35 +00:00
|
|
|
docker run --name $OVPN_DATA -v /etc/openvpn busybox
|
2014-07-06 06:35:19 +00:00
|
|
|
|
2014-07-09 07:07:35 +00:00
|
|
|
* Initalize the `$OVPN_DATA` container that will hold the configuration files and certificates
|
2014-07-06 06:35:19 +00:00
|
|
|
|
2014-07-09 19:19:15 +00:00
|
|
|
docker run --volumes-from $OVPN_DATA --rm kylemanna/openvpn ovpn_genconfig -u udp://VPN.SERVERNAME.COM:1194
|
|
|
|
docker run --volumes-from $OVPN_DATA --rm -it kylemanna/openvpn ovpn_initpki
|
2014-06-04 22:41:24 +00:00
|
|
|
|
2014-06-05 15:52:51 +00:00
|
|
|
* Start OpenVPN server process
|
2014-06-04 22:41:24 +00:00
|
|
|
|
2014-07-09 07:07:35 +00:00
|
|
|
docker run --volumes-from $OVPN_DATA -d -p 1194:1194/udp --privileged kylemanna/openvpn
|
2014-06-04 22:41:24 +00:00
|
|
|
|
2014-06-05 15:52:51 +00:00
|
|
|
* Generate a client certificate without a passphrase
|
2013-09-03 00:42:05 +00:00
|
|
|
|
2014-07-09 07:07:35 +00:00
|
|
|
docker run --volumes-from $OVPN_DATA --rm -it kylemanna/openvpn easyrsa build-client-full CLIENTNAME nopass
|
2013-09-03 00:42:05 +00:00
|
|
|
|
2014-06-05 15:52:51 +00:00
|
|
|
* Retrieve the client configuration with embedded certificates
|
2013-09-03 00:42:05 +00:00
|
|
|
|
2014-07-09 07:07:35 +00:00
|
|
|
docker run --volumes-from $OVPN_DATA --rm kylemanna/openvpn ovpn_getclient CLIENTNAME > CLIENTNAME.ovpn
|
2013-09-03 00:42:05 +00:00
|
|
|
|
2013-09-04 21:22:24 +00:00
|
|
|
|
2014-06-05 15:52:51 +00:00
|
|
|
## How Does It Work?
|
2013-09-03 00:42:05 +00:00
|
|
|
|
2014-06-05 15:52:51 +00:00
|
|
|
Initialize the volume container using the `kylemanna/openvpn` image with the
|
2014-07-06 07:24:54 +00:00
|
|
|
included scripts to automatically generate:
|
2013-09-03 00:42:05 +00:00
|
|
|
|
2014-06-05 15:52:51 +00:00
|
|
|
- Diffie-Hellman parameters
|
|
|
|
- a private key
|
|
|
|
- a self-certificate matching the private key for the OpenVPN server
|
|
|
|
- an EasyRSA CA key and certificate
|
|
|
|
- a TLS auth key from HMAC security
|
2013-09-03 00:42:05 +00:00
|
|
|
|
2014-06-05 15:52:51 +00:00
|
|
|
The OpenVPN server is started with the default run cmd of `ovpn_run`
|
2013-09-03 00:42:05 +00:00
|
|
|
|
|
|
|
The configuration is located in `/etc/openvpn`, and the Dockerfile
|
|
|
|
declares that directory as a volume. It means that you can start another
|
2014-05-23 22:31:46 +00:00
|
|
|
container with the `--volumes-from` flag, and access the configuration.
|
2014-06-05 15:52:51 +00:00
|
|
|
The volume also holds the PKI keys and certs so that it could be backed up.
|
|
|
|
|
|
|
|
To generate a client certificate, `kylemanna/openvpn` uses EasyRSA via the
|
|
|
|
`easyrsa` command in the container's path. The `EASYRSA_*` environmental
|
|
|
|
variables place the PKI CA under `/etc/opevpn/pki`.
|
|
|
|
|
|
|
|
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.
|
2013-09-03 00:42:05 +00:00
|
|
|
|
|
|
|
|
2014-06-05 15:52:51 +00:00
|
|
|
## OpenVPN Details
|
2013-09-03 00:42:05 +00:00
|
|
|
|
|
|
|
We use `tun` mode, because it works on the widest range of devices.
|
|
|
|
`tap` mode, for instance, does not work on Android, except if the device
|
|
|
|
is rooted.
|
|
|
|
|
|
|
|
The topology used is `net30`, because it works on the widest range of OS.
|
|
|
|
`p2p`, for instance, does not work on Windows.
|
|
|
|
|
2014-07-01 06:45:36 +00:00
|
|
|
The UDP server uses`192.168.255.0/24` for dynamic clients by default.
|
2013-09-03 00:42:05 +00:00
|
|
|
|
|
|
|
The client profile specifies `redirect-gateway def1`, meaning that after
|
|
|
|
establishing the VPN connection, all traffic will go through the VPN.
|
|
|
|
This might cause problems if you use local DNS recursors which are not
|
|
|
|
directly reachable, since you will try to reach them through the VPN
|
|
|
|
and they might not answer to you. If that happens, use public DNS
|
|
|
|
resolvers like those of Google (8.8.4.4 and 8.8.8.8) or OpenDNS
|
|
|
|
(208.67.222.222 and 208.67.220.220).
|
|
|
|
|
|
|
|
|
2014-06-05 15:52:51 +00:00
|
|
|
## Security Discussion
|
|
|
|
|
|
|
|
The Docker container runs its own EasyRSA PKI Certificate Authority. This was
|
|
|
|
chosen as a good way to compromise on security and convenience. The container
|
|
|
|
runs under the assumption that the OpenVPN container is running on a secure
|
|
|
|
host, that is to say that an adversary does not have access to the PKI files
|
|
|
|
under `/etc/openvpn/pki`. This is a fairly reasonable compromise because if an
|
|
|
|
adversary had access to these files, the adversary could manipulate the
|
|
|
|
function of the OpenVPN server itself (sniff packets, create a new PKI CA, MITM
|
|
|
|
packets, etc).
|
|
|
|
|
|
|
|
* The certificate authority key is kept in the container by default for
|
|
|
|
simplicity. It's highly recommended to secure the CA key with some
|
|
|
|
passphrase to protect against a filesystem compromise. A more secure system
|
|
|
|
would put the EasyRSA PKI CA on an offline system (can use the same Docker
|
|
|
|
image to accomplish this).
|
|
|
|
* It would be impossible for an adversary to sign bad or forged certificates
|
|
|
|
without first cracking the key's passphase should the adversary have root
|
|
|
|
access to the filesystem.
|
|
|
|
* The EasyRSA `build-client-full` command will generate and leave keys on the
|
|
|
|
server, again possible to compromise and steal the keys. The keys generated
|
|
|
|
need to signed by the CA which the user hopefully configured with a passphrase
|
|
|
|
as described above.
|
|
|
|
* Assuming the rest of the Docker container's filesystem is secure, TLS + PKI
|
|
|
|
security should prevent any malicious host from using the VPN.
|
|
|
|
|
|
|
|
|
|
|
|
## Differences from jpetazzo/dockvpn
|
|
|
|
|
|
|
|
* No longer uses serveconfig to distribute the configuration via https
|
|
|
|
* Proper PKI support integrated into image
|
|
|
|
* OpenVPN config files, PKI keys and certs are stored on a storage
|
|
|
|
volume for re-use across containers
|
|
|
|
* Only offer UDP support for now, I don't have a good use case for TCP
|
|
|
|
* Addition of tls-auth for HMAC security
|
|
|
|
|
|
|
|
## Tested On
|
|
|
|
|
|
|
|
* Docker hosts:
|
|
|
|
* server a Digitial Ocean Droplet with 512 MB RAM running Ubuntu 14.04
|
|
|
|
* Clients
|
|
|
|
* Android App OpenVPN Connect 1.1.14 (built 56)
|
|
|
|
* 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
|