How to setup a VPN connection from inside a pod in Kubernetes

by

So your corporation want to move an application inside your awesome cluster, but the application requires access to another network. So how do we setup a VPN client from our docker container running in our Kubernetes cluster? I’ll explain how I managed to setup a point-to-point connection from inside a pod in Kubernetes using OpenVPN and a little scripting.

First off, we need a base image to start with. The best approach is using the base image your application requiring VPN runs on.

I’ll use the microsoft/aspnetcore:1.1.1 image as my base image.

There are two approaches to this.

  1. build a new image from our base image, that our application then will use moving forward.
  2. setup the whole thing in 1 Dockerfile and build the whole thing every time.

The first one is probably preferred since you’ll save time on every build going forward. It’s the one I would go with. But to start off, we’ll just use a single Dockerfile.

The Dockerfile

So let’s start by adding OpenVPN to our base image and adding our credentials to it.

Two approaches as to how you wanna add your VPN informations to the container.

  1. Copy it in when you build it
  2. Mount it as a volume in Kubernetes

The second approach is the more secure and correct way of doing so. But the first one is the easiest and the one I will be using for the sake of simplicity.

So nothing fancy here really. We install OpenVPN and copy the content of our vpn folder to the openvpn folder.

Other than that we copy the path for your app inside the app folder together with a startup.sh script and then run the script to start the container.

You’ll want to put all your OpenVPN files in the vpn folder. Now I am no expert here. My setup was an  .ovpn followed by a ca.crt, ca.key, client.crt and a client.key file for my point-to-point VPN connection.

The startup script

Now the startup.sh script makes the necessary steps that make it possible for OpenVPN to communicate out of the container. The tun device driver allows packet reception and transmission for user space programs e.g OpenVPN. You can read more about it in the Kernel TUN device driver documentation.

On line 7, OpenVPN is started using our .opvn file. It is run as a background process with the --daemon flag.

On line 8, we start up the application in need of our VPN connection.

Now after building the image. You should run it, but it needs NET_ADMIN capabilities like this:

Making the VPN container work in Kubernetes

Now when the container is build the way it is. It is pretty simple to make it work with Kubernetes. Basically we just need to add the same capabilities to the container in Kubernetes, as we did in Docker.

The important part is on line 17-20. Those 4 lines do the same thing as --cap-add=NET_ADMIN did when running the container with Docker.

Thats it! You should now have a container with a VPN connection running inside your Kubernetes cluster!

I hope you found this useful! Please do not hesitate to reach out in the comments or at @karnich.

  • Soundz

    Thanks for the great post!
    Do you know how you would add a second network and allow other containers to route through this one?

    • Jesper Christensen

      Glad you liked it! Unfortunately no. Since i only needed VPN for 1 application i did it this way and did not look into the other possible solutions. Hit me up if you manage to do it and let me know how! 🙂

      • Sounds

        It looks like since each Pod shares the same network namespace, having another container in the same pod should just work