diff --git a/bin/ovpn_genconfig b/bin/ovpn_genconfig index 894133d..974c344 100755 --- a/bin/ovpn_genconfig +++ b/bin/ovpn_genconfig @@ -171,8 +171,6 @@ port 1194 dev tun0 status /tmp/openvpn-status.log -client-config-dir $OPENVPN/ccd - user nobody group nogroup EOF diff --git a/bin/ovpn_getclient b/bin/ovpn_getclient index 0906886..b2055b3 100755 --- a/bin/ovpn_getclient +++ b/bin/ovpn_getclient @@ -45,7 +45,7 @@ remote $OVPN_CN $OVPN_PORT $OVPN_PROTO $(cat $EASYRSA_PKI/private/${cn}.key) -$(cat $EASYRSA_PKI/issued/${cn}.crt) +$(openssl x509 -in $EASYRSA_PKI/issued/${cn}.crt) $(cat $EASYRSA_PKI/ca.crt) diff --git a/bin/ovpn_run b/bin/ovpn_run index 5a2c95a..b91da3a 100755 --- a/bin/ovpn_run +++ b/bin/ovpn_run @@ -10,6 +10,9 @@ fi set -e +# Build runtime arguments array based on environment +ARGS=("--config" "$OPENVPN/openvpn.conf") + source "$OPENVPN/ovpn_env.sh" mkdir -p /dev/net @@ -17,8 +20,8 @@ if [ ! -c /dev/net/tun ]; then mknod /dev/net/tun c 10 200 fi -if [ ! -d "$OPENVPN/ccd" ]; then - mkdir -p /etc/openvpn/ccd +if [ -d "$OPENVPN/ccd" ]; then + ARGS+=("--client-config-dir" "$OPENVPN/ccd") fi # Setup NAT forwarding if requested @@ -40,11 +43,21 @@ if [ -r "$EASYRSA_PKI/crl.pem" ]; then ln "$EASYRSA_PKI/crl.pem" "$OPENVPN/crl.pem" chmod 644 "$OPENVPN/crl.pem" fi - ARGS=("--crl-verify" "$OPENVPN/crl.pem") + ARGS+=("--crl-verify" "$OPENVPN/crl.pem") +fi + +ip -6 route show default 2>/dev/null +if [ $? = 0 ]; then + echo "Enabling IPv6 Forwarding" + # 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 + sysctl net.ipv6.conf.all.forwarding=1 fi if [ "$#" -gt 0 ]; then exec openvpn "$@" else - exec openvpn ${ARGS[@]} --config "$OPENVPN/openvpn.conf" + exec openvpn ${ARGS[@]} fi diff --git a/docs/docker.md b/docs/docker.md new file mode 100644 index 0000000..2313504 --- /dev/null +++ b/docs/docker.md @@ -0,0 +1,52 @@ +# Install Latest Docker Service + +Docker included with some distributions lags far behind upstream. This guide aims to provide a quick and reliable way to install or update it. + +It is recommended to use platforms that support systemd as future versions of this docker image may require systemd to help with some tasks: + +* Fedora +* Debian 8.1+ + +## Debian / Ubuntu + +### Step 1 — Set Up Docker + +Docker is moving fast and Debian / 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. + +Ensure dependencies are installed: + + sudo apt-get update && sudo apt-get install -y apt-transport-https curl + +Add the upstream Docker repository package signing key. The apt-key command uses elevated privileges via sudo, so a password prompt for the user's password may appear: + + curl https://get.docker.io/gpg | sudo apt-key add - + +Add the upstream Docker repository to the system list: + + echo deb https://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 `docker` group to enable communication with the Docker daemon as a normal user, where `$USER` is your username. Exit and log in again for the new group to take effect: + + sudo usermod -aG docker $USER + +After **re-logging in** verify the group membership using the id command. The expected response should include docker like the following example: + + uid=1001(test0) gid=1001(test0) groups=1001(test0),27(sudo),999(docker) + +### Step 2 — Test Docker + +Run a Debian jessie docker container: + + docker run --rm -it debian:jessie bash -l + +Once inside the container you'll see the `root@:/#` prompt signifying that the current shell is in a Docker container. To confirm that it's different from the host, check the version of Debian running in the container: + + cat /etc/issue.net + +Expected result: + + Debian GNU/Linux 8 diff --git a/docs/faqs.md b/docs/faqs.md index 4805836..7ed633d 100644 --- a/docs/faqs.md +++ b/docs/faqs.md @@ -1,5 +1,12 @@ # Frequently Asked Questions +## How do I edit `openvpn.conf`? + +Use a Docker image with a text editor pre-installed (i.e. Ubuntu) and connect the volume container: + + docker run --volumes-from $OVPN_DATA --rm -it ubuntu vi /etc/openvpn/openvpn.conf + + ## Why not keep everything in one image? 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. diff --git a/docs/ipv6.md b/docs/ipv6.md new file mode 100644 index 0000000..0916d10 --- /dev/null +++ b/docs/ipv6.md @@ -0,0 +1,91 @@ +# IPv6 Support + +This is a work in progress, more polish to follow. Use the `dev` git branch and `dev` docker image tag for testing. + +## Tunnel IPv6 Address To OpenVPN Clients + +This feature is advanced and recommended only for those who already have a functioning IPv4 tunnel and know how IPv6 works. + +Systemd is used to setup a static route and Debian 8.1 or later is recommended as the host distribution. Others probably work, but haven't been tested. + + +### Step 1 — Setup IPv6 on the Host Machine + +The tutorial uses a free tunnel from [tunnelbroker.net](https://tunnelbroker.net/) to get a /64 and /48 prefix allocated to me. The tunnel endpoint is less then 3 ms away from Digital Ocean's San Francisco datacenter. + +Place the following in `/etc/network/interfaces`. Relace `PUBLIC_IP` with your host's public IPv4 address and replace 2001:db8::2 and 2001:db8::1 with the corresponding tunnel endpoints: + + auto he-ipv6 + iface he-ipv6 inet6 v4tunnel + address 2001:db8::2 + netmask 64 + endpoint 72.52.104.74 + local PUBLIC_IP + ttl 255 + gateway 2001:db8::1 + +Bring the interface up: + + ifup he-ipv6 + +Test that IPv6 works on the host: + + ping6 google.com + +If this doesn't work, figure it out. It may be necessary to add an firewall rule to allow IP protocol 41 through the firewall. + + +### Step 2 — Update Docker's Init To Enable IPv6 Support + +Copy the system's existing docker file and append the `--ipv6` argument to the end of the command line: + + sed -e 's:^\(ExecStart.*\):\1 --ipv6:' /lib/systemd/system/docker.service | tee /etc/systemd/system/docker.service + +Reload the daemon and restart docker so that it takes affect: + + systemctl daemon-reload && systemctl restart docker.service + + +### Step 3 — Setup the systemd Unit File + +Copy the systemd init file from the docker-openvpn /init directory of the repository and install into `/etc/systemd/system/docker-openvpn.service` + + curl -o /etc/systemd/system/docker-openvpn.service https://raw.githubusercontent.com/kylemanna/docker-openvpn/dev/init/docker-openvpn.service + +Edit the file, replace `IP6_PREFIX` value with the value of your /64 prefix. + + vi /etc/systemd/system/docker-openvpn.service + +Finally, reload systemd so the changes take affect: + + systemctl daemon-reload + +### Step 4 — Start OpenVPN + +Ensure that OpenVPN has been initialized and configured as described in the top level `README.md`. + +Start the systemd service file: + + systemctl start docker-openvpn + +Verify logs if needed: + + systemctl status docker-openvpn + docker logs openvpn0 + +### Step 4 — Modify Client Config for IPv6 Default Route + +Append the default route for the public Internet: + + echo "route-ipv6 2000::/3" >> clientname.ovpn + +### Step 5 — Start up Client + +If all went according to plan, then `ping6 2600::` and `ping6 google.com` should work. + +Fire up a web browser and attempt to navigate to [https://ipv6.google.com](https://ipv6.google.com). + + +## Connect to the OpenVPN Server Over IPv6 + +Not implemented, yet. diff --git a/init/docker-openvpn@.service b/init/docker-openvpn@.service new file mode 100644 index 0000000..f855e94 --- /dev/null +++ b/init/docker-openvpn@.service @@ -0,0 +1,44 @@ +[Unit] +Description=OpenVPN Docker Container +Documentation=https://github.com/kylemanna/docker-openvpn +After=network.target docker.socket +Requires=docker.socket + +[Service] +RestartSec=10 +Restart=always + +# Modify IP6_PREFIX to match network config +#Environment="IP6_PREFIX=2001:db8::/64" +#Environment="ARGS=--config openvpn.conf --server-ipv6 2001:db8::/64" +Environment="NAME=ovpn-%i" +Environment="DATA_VOL=ovpn-data-%i" +Environment="IMG=kylemanna/openvpn:dev" +Environment="PORT=1194:1194/udp" + +# To override environment variables, use local configuration directory: +# /etc/systemd/system/docker-openvpn@foo.d/local.conf +# http://www.freedesktop.org/software/systemd/man/systemd.unit.html + +# Clean-up bad state if still hanging around +ExecStartPre=-/usr/bin/docker rm -f $NAME + +# Attempt to pull new image for security updates +ExecStartPre=-/usr/bin/docker pull $IMG + +# IPv6: Ensure forwarding is enabled on host's networking stack (hacky) +# Would be nice to use systemd-network on the host, but this doens't work +# http://lists.freedesktop.org/archives/systemd-devel/2015-June/032762.html +ExecStartPre=/bin/sh -c 'test -z "$IP6_PREFIX" && exit 0; sysctl net.ipv6.conf.all.forwarding=1' + +# Main process +ExecStart=/usr/bin/docker run --rm --privileged --volumes-from ${DATA_VOL}:ro --name ${NAME} -p ${PORT} ${IMG} ovpn_run $ARGS + +# IPv6: Add static route for IPv6 after it starts up +ExecStartPost=/bin/sh -c 'test -z "${IP6_PREFIX}" && exit 0; sleep 1; ip route replace ${IP6_PREFIX} via $(docker inspect -f "{{ .NetworkSettings.GlobalIPv6Address }}" $NAME ) dev docker0' + +# IPv6: Clean-up +ExecStopPost=/bin/sh -c 'test -z "$IP6_PREFIX" && exit 0; ip route del $IP6_PREFIX dev docker0' + +[Install] +WantedBy=multi-user.target diff --git a/upstart.init b/init/upstart.init similarity index 100% rename from upstart.init rename to init/upstart.init