This tutorial will explain how to setup and run an OpenVPN container with the help of Docker.
OpenVPN provides a way to create virtual private networks (VPNs) using TLS (evolution of SSL) encryption. OpenVPN protects the network traffic from eavesdropping and man-in-the-middle (MITM) attacks. The private network can be used to securely connect a device, such as a laptop or mobile phone running on an insecure WiFi network, to a remote server that then relays the traffic to the Internet. Private networks can also be used to securely connect devices to each other over the Internet.
Docker provides a way to encapsulate the OpenVPN server process and configuration data so that it is more easily managed. The Docker OpenVPN image is prebuilt (source is available) and includes all of the necessary dependencies to run the server in a sane and stable environement. Scripts are included to significantly automate the standard use case, but still allow for full manual configuration if desired. A Docker volume container is used to hold the configuration and EasyRSA PKI certificate data as well.
- Securely route to the Internet when on untrusted public (WiFi) networks.
- Private network to connect a mobile laptop, office computer, home PC, and mobile phone.
- Private network for secure services behind NAT routers that don't have NAT traversal capabilities.
- Setup the Docker daemon on Ubuntu 14.04 LTS.
- Setup a Docker volume container to hold the configuration data.
- Generate a EasyRSA PKI certificate authority (CA).
- Extract auto generated client configuration files.
- Configure a select number of OpenVPN clients.
- Handle starting the Docker container on boot.
- Introduce advanced topics.
- Linux shell knowledge. This guide largely assumes that the user is capable of setting up and running Linux daemons in the traditional sense.
- Shell access on a remote server. A DigitalOcean 1 CPU / 512 MB RAM droplet running Ubuntu 14.04 is assumed for this tutorial. Docker makes running the image on any host Linux distribution easy. Any virtual host will work as long as the host is running QEMU/KVM or Xen virtualization technology, OpenVZ will not work.
- A local client such as an Android phone, laptop or PC. Almost all operating systems are supported via various OpenVPN clients.
Docker is moving fast and Ubuntu's long term support (LTS) policy doesn't keep up. To work around this we'll install a PPA that will get us the latest version of Docker.
-
Add the upstream Docker repository package signing key:
curl https://get.docker.io/gpg | sudo apt-key add - -
Add the upstream Docker repository to system list:
echo deb http://get.docker.io/ubuntu docker main | sudo tee /etc/apt/sources.list.d/docker.list -
Update the package list and install the Docker package:
sudo apt-get update && sudo apt-get install -y lxc-docker -
Add your user to the
dockergroup to enable communication with the Docker daemon as a normal user, where $USER is your username. Re-login for the new group to take affect:sudo usermod -aG docker $USER -
Optional: Run
bashin a simple Debian Docker image (--rmto cleanup container after exit and-itfor interactive) to verify Docker operation on host:docker run --rm -it debian:jessie bash -lExpected response with additional check of Debian version:
test0@tutorial0:~$ docker run --rm -it debian:jessie bash -l Unable to find image 'debian:jessie' locally debian:jessie: The image you are pulling has been verified 511136ea3c5a: Pull complete 36fd425d7d8a: Pull complete aaabd2b41e22: Pull complete Status: Downloaded newer image for debian:jessie root@de8ffd8f82f6:/# cat /etc/issue.net Debian GNU/Linux jessie/sid root@de8ffd8f82f6:/# logout
This step is usually a headache for those familiar with OpenVPN or any services utilizing PKI. Luckily Docker and the scripts in the Docker image simplify this step by generating configuration files and all the necessary certificate files for us.
-
Create a volume container, this tutorial will use
$OVPN_DATAenvironmental variable to make it copy-paste friendly. Set as appropriate:OVPN_DATA="ovpn-data" -
Create an empty Docker volume container using busybox as a minimal Docker image:
docker run --name $OVPN_DATA -v /etc/openvpn busybox -
Initalize the
$OVPN_DATAcontainer that will hold the configuration files and certificates, replaceVPN.SERVERNAME.COMwith your FQDN:docker run --volumes-from $OVPN_DATA --rm kylemanna/openvpn ovpn_genconfig -u udp://VPN.SERVERNAME.COM:1194 -
Generate the EasyRSA PKI certificate authority, you will be prompted for a passphrase for the CA private key. Pick a good one and remember it, without the passphrase it will be impossible to issue and sign client certificates:
docker run --volumes-from $OVPN_DATA --rm -it kylemanna/openvpn ovpn_initpki
Note, the security of the $OVPN_DATA container is important. It contains all the private keys to impersonate the server and ability to steal client certificates. Keep this in mind and control access as appropriate. The default OpenVPN scripts use a passphrase for the CA key to increase security and prevents issuing bogus certificates.
See Advanced Topics below for more details on how to backup the certificate store.
-
To autostart the Docker container that runs OpenVPN server process (see Docker Host Integration for more) create an upstart init file:
cat <<EOF | sudo tee /etc/init/docker-openvpn.conf description "Docker container for OpenVPN server" start on filesystem and started docker stop on runlevel [!2345] respawn script exec docker run --volumes-from ovpn-data --rm -p 1194:1194/udp --cap-add=NET_ADMIN kylemanna/openvpn end script EOF -
Start the process using upstart init mechanism:
sudo start docker-openvpn -
Verify that the container started and didn't immediately crash by looking at the
STATUScolumn:test0@tutorial0:~$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c3ca41324e1d kylemanna/openvpn:latest "ovpn_run" 2 seconds ago Up 2 seconds 0.0.0.0:1194->1194/udp focused_mestorf
Create a client certificate using the PKI CA setup above for each client, replace CLIENTNAME as appropriate (this doesn't have to be a FQDN):
docker run --volumes-from $OVPN_DATA --rm -it kylemanna/openvpn easyrsa build-client-full CLIENTNAME nopass
After each client is created the server is ready to accept connections.
The clients need the certificates and a configuration file to connect. The embedded scripts automate this task and enable the user to write out a configuration to a single file that can then be transfered to the client, again replace CLIENTNAME as appropriate:
docker run --volumes-from $OVPN_DATA --rm kylemanna/openvpn ovpn_getclient CLIENTNAME > CLIENTNAME.ovpn
The resulting CLIENTNAME.ovpn file contains the private keys and certificates necessary to connect to the VPN. Keep these files secure and not lying around. You'll need to securely transport the *.ovpn files to the clients that will use them. Avoid using public services like e-mail or cloud storage if possible when transfering the files due to security concerns.
Recommend methods of transfer are ssh/scp, https, USB, and microSD card where available.
On Ubuntu 12.04/14.04 and Debian wheezy/jessie clients (and similar):
-
Install OpenVPN:
sudo apt-get install openvpn -
Copy the client configuration file from the server and set secure permissions:
sudo install -o root -m 400 CLIENTNAME.ovpn /etc/openvpn/CLIENTNAME.conf -
Configure the init scripts to autostart all configurations matching
/etc/openvpn/*.conf:echo AUTOSTART=all | sudo tee -a /etc/default/openvpn -
Restart the OpenVPN client's server process:
sudo /etc/init.d/openvpn restart
-
Install OpenVPN:
pacman -Sy openvpn -
Copy the client configuration file from the server and set secure permissions:
sudo install -o root -m 400 CLIENTNAME.ovpn /etc/openvpn/CLIENTNAME.conf -
Start OpenVPN client's server process:
systemctl start openvpn@CLIENTNAME -
Optional: configure systemd to start
/etc/openvpn/CLIENTNAME.confat boot:systemctl enable openvpn@CLIENTNAME
- Download and install TunnelBlick.
- Copy
CLIENTNAME.ovpnfrom the server to the Mac. - Import the configuration by double clicking the
*.ovpnfile copied earlier. TunnelBlick will be invoked and the import the configruation. - Open TunnelBlick, select the configuration, select connect.
- Install the OpenVPN Connect App from the Google Play store.
- Copy
CLIENTNAME.ovpnfrom the server to the Android device in a secure manner. USB or microSD cards are safer. Place the file on your SD card to aid in opening it. - Import the configuration: Menu -> Import -> Import Profile from SD card
- Select connect.
If routing all the traffic to the web via the OpenVPN, check a website and the IP address of the OpenVPN server. Try Google or ifconfig.me.
Review your network interface configuration. On Unix based operating systems this is as simple as running ifconfig in a terminal, look for OpenVPN's tunX interface when it's connected.
Review logs. On Unix systems check /var/log on old distributions or journalctl on systemd distributions.
The Docker image built to run this is open source and capable of much more then described here.
The docker-openvpn source repository is available for review of the code as well as forking for modifications. Pull requests for general features or bugfixes are welcome.
Advanced topics such as backup and static client IPs are discussed under the docker-openvpn/docs folder.
Report bugs to the docker-openvpn issue tracker.
good job, I will try this with my linode ;)