--- myst: html_meta: "description lang=en": "Configure VPN sidecar containers for Kasm Workspaces, a single network container to route traffic from many Workspaces through a VPN tunnel. " "keywords": "Kasm, How to, How-to, VPN, Container, OpenVPN, TailScale, NordVPN" "property=og:locale": "en_US" --- ```{title} VPN Sidecar Containers ``` # VPN Sidecar Containers ## Intro For security reasons or to gain access to a remote network it might be required to give specific Kasm Workspaces access to a VPN. One way to do that would be to customize an existing Kasm core image with VPN tools, but then it requires many network level permissions and becomes a configuration nightmare. The Kasm team's recommended configuration would be to use an off the shelf or custom VPN docker container running alongside Kasm Workspaces while leveraging the existing desktop and application containers. Their traffic can then be forced through the external VPN container using a custom Docker exec config. This document will be covering three different ways to achieve this. Deployment time ~10 minutes. * [Option 1 Create a standalone openvpn setup](#option-1-create-a-standalone-openvpn-setup) + [The OpenVPN server](#the-openvpn-server) + [The OpenVPN sidecar container](#the-openvpn-sidecar-container) + [Finding the public IP OpenVPN](#finding-the-public-ip-openvpn) * [Option 2 using a popular VPN Vendor container](#option-2-using-a-popular-vpn-vendor-container) + [Setting up a VPN container (NordVPN)](#setting-up-a-vpn-container) + [Nord VPN Testing](#nord-vpn-testing) * [Option 3 Tailscale](#option-3-tailscale) + [Getting the Tailscale auth key](#getting-the-tailscale-auth-key) + [Setting up a Tailscale Docker container](#setting-up-a-tailscale-docker-container) + [Tailscale testing](#tailscale-testing) ## Option 1 Create a standalone openvpn setup This configuration is going to be using an off the shelf OpenVPN container for the server as the assumption is most users will already have an OpenVPN endpoint available. Then the example will show building a custom client container to act as the sidecar. ### The OpenVPN server Here [kylemanna/openvpn](https://hub.docker.com/r/kylemanna/openvpn/) is being used to be able to quickly spin up an endpoint on a remote server. Use the following commands to deploy and dump a usable client config file: ``` sudo docker volume create --name Kasm_vpn sudo docker run -v Kasm_vpn:/etc/openvpn --rm kylemanna/openvpn ovpn_genconfig -u udp://IP_OR_HOSTNAME sudo docker run -v Kasm_vpn:/etc/openvpn --rm -it kylemanna/openvpn ovpn_initpki sudo docker run -v Kasm_vpn:/etc/openvpn -d -p 1194:1194/udp --cap-add=NET_ADMIN kylemanna/openvpn sudo docker run -v Kasm_vpn:/etc/openvpn --rm -it kylemanna/openvpn easyrsa build-client-full Kasm nopass sudo docker run -v Kasm_vpn:/etc/openvpn --rm kylemanna/openvpn ovpn_getclient Kasm > Kasm.ovpn ``` Please substitute the `IP_OR_HOSTNAME` for the actual server IP or hostname for the server. After filling out the prompted information for password protecting the certificates the `Kasm.ovpn` configuration file needed to connect the VPN sidecar client will be written to disk. ### The OpenVPN sidecar container Build a custom docker container to act as the VPN sidecar container on the Kasm Workspaces host. ``` mkdir openvpn-client cd openvpn-client mkdir root ``` Here is the `Dockerfile`: ``` FROM debian:latest RUN apt update && \ apt install -y \ iptables \ openvpn && \ apt clean # add local files COPY /root / VOLUME [ "/vpn/config" ] ENTRYPOINT [ "/entrypoint.sh" ] ``` And custom `root/entrypoint.sh`: ``` #! /bin/sh # create tun device if [ ! -c /dev/net/tun ]; then mkdir -p /dev/net mknod /dev/net/tun c 10 200 fi # Enable devices MASQUERADE mode iptables -t nat -A POSTROUTING -o tun+ -j MASQUERADE # start vpn client openvpn --config /vpn/config/${VPN_CONFIG} ``` Make sure the entrypoint is executable: ``` chmod +x root/entrypoint.sh ``` The directory structure should look like this: ``` openvpn-client/ ├─ root/ │ ├─ entrypoint.sh ├─ Dockerfile ``` Now build the container: ``` sudo docker build -t openvpn-client . ``` On the Docker host running Kasm Workspaces (or Agent Server if using a Mult-Server Deploy) create a custom docker network: ``` sudo docker network create \ --driver=bridge \ --opt icc=true \ --subnet=172.20.0.0/16 \ vpn-1 ``` And finally navigate to the folder containing the `Kasm.ovpn` config file and run the container: ``` sudo docker run -d \ --cap-add NET_ADMIN \ --name open-vpn \ --net vpn-1 \ --ip 172.20.0.2 \ -e VPN_CONFIG=Kasm.ovpn \ -v $(pwd):/vpn/config \ --restart unless-stopped \ openvpn-client ``` ### Customizing Workspaces ```{include} /how_to/vpn_sidecar/customizing_workspaces.md ``` ### Testing Testing the VPN configuration in the container will vary depending on the provider or use case, but here are some tips. These examples will be using the `AlmaLinux 8 - VPN` Workspace configured earlier. #### Finding the public IP OpenVPN Click on Applications -> Terminal Emulator and enter: ``` curl icanhazip.com ``` Make sure the IP returned is not the current public IP of the Kasm Workspaces Agent the container is running on. ## Option 2 using a popular VPN Vendor container This example will be using an off the shelf VPN container here specifically geared for [NordVPN](https://nordvpn.com/), but the steps should be similar depending on the desired provider or configuration. ### Setting up a VPN container On the Docker host running Kasm Workspaces (or Agent Server if using a Mult-Server Deploy) first create a custom docker network: ``` docker network create \ --driver=bridge \ --opt icc=true \ --subnet=172.20.0.0/16 \ vpn-1 ``` Now spinup a NordVPN Docker container: A NordVPN token is required and can be obtained following these [instructions](https://support.nordvpn.com/1905092252) ``` docker run -d \ --cap-add NET_ADMIN \ --cap-add NET_RAW \ --name nord-vpn \ --net vpn-1 \ --ip 172.20.0.2 \ -e TOKEN=NORDVPNTOKEN \ -e TECHNOLOGY=NordLynx \ --restart unless-stopped \ ghcr.io/bubuntux/nordvpn ``` ### Customizing Workspaces ```{include} /how_to/vpn_sidecar/customizing_workspaces.md ``` ### Testing Testing the VPN configuration in the container will vary depending on the provider or use case, but here are some tips. These examples will be using the `AlmaLinux 8 - VPN` Workspace configured earlier. #### Nord VPN Testing Most VPN providers' webpages will give some kind of indication that the browsing session is "protected" from their home page. This example uses a NordVPN, so open up Firefox from the desktop and navigate to [https://nordvpn.com](https://nordvpn.com), The page should display a `Protected` status: ```{figure} /images/vpn_sidecar/protected.png :align: center **NordVPN Protected** ``` ## Option 3 Tailscale [Tailscale](https://tailscale.com/) is a zero configuration VPN solution that allows users to quickly connect to a network of remote computers by their Tailscale IP addresses. This example will be configuring a sidecar container to route traffic to the machines on the Tailscale network. It is important to note here this example does not configure an exit node here simply allowing configured VPN containers to route traffic out to the Tailscale network. ### Getting the Tailscale auth key Most users can skip this step when trying to connect Workspaces containers to existing Tailscale infrastructure. For those who are new to Tailscale sign up for an account with them [here](https://login.tailscale.com/start). After signed up a login screen will be presented: ```{figure} /images/vpn_sidecar/welcome.png :align: center **Add device Tailscale** ``` Ignore the setup wizard and click the avatar on the top right of the screen and select "Billing": ```{figure} /images/vpn_sidecar/billing.png :align: center **Billing Location** ``` From here click on "Keys" under "Personal Settings": ```{figure} /images/vpn_sidecar/keys.png :align: center **Keys Setting Location** ``` Click on "Generate auth key...": ```{figure} /images/vpn_sidecar/generate.png :align: center **Generate a Key** ``` The Kasm team recommends setting "Reusable" and "Ephemeral" but ultimately review the settings and decide the best settings: ```{figure} /images/vpn_sidecar/keysettings.png :align: center **Generate Settings** ``` Copy the key created and move on to the next step. ### Setting up a Tailscale Docker container On the Kasm Workspaces host build a custom docker container to act as the VPN sidecar container. ``` mkdir tailscale cd tailscale mkdir root ``` Here is the `Dockerfile`: ``` FROM alpine:3.15 RUN \ apk add --no-cache \ bind-tools \ tailscale # add local files COPY /root / ENTRYPOINT [ "/entrypoint.sh" ] ``` And custom `root/entrypoint.sh`: ``` #! /bin/sh # create tun device if [ ! -c /dev/net/tun ]; then mkdir -p /dev/net mknod /dev/net/tun c 10 200 fi # Enable devices MASQUERADE mode iptables -t nat -A POSTROUTING -o eth+ -j MASQUERADE iptables -t nat -A POSTROUTING -o tailscale+ -j MASQUERADE # start vpn client tailscaled ``` Make sure the entrypoint is executable: ``` chmod +x root/entrypoint.sh ``` The directory structure should look like this: ``` tailscale/ ├─ root/ │ ├─ entrypoint.sh ├─ Dockerfile ``` Now build the container: ``` sudo docker build -t tailscaled . ``` On the Docker host running Kasm Workspaces (or Agent Server if using a Mult-Server Deploy) create a custom docker network: ``` sudo docker network create \ --driver=bridge \ --opt icc=true \ --subnet=172.20.0.0/16 \ vpn-1 ``` Now spinup a Tailscale Docker container: ``` sudo docker run -d \ --cap-add NET_ADMIN \ --name tailscaled \ --net vpn-1 \ --ip 172.20.0.2 \ --restart unless-stopped \ tailscaled ``` Now login using the auth key: ``` sudo docker exec tailscaled tailscale up --authkey= ``` Now navigate [here](https://login.tailscale.com/admin/machines) and ensure the machine is listed: ```{figure} /images/vpn_sidecar/machine.png :align: center **Machine View** ``` ### Customizing Workspaces ```{include} /how_to/vpn_sidecar/customizing_workspaces.md ``` ### Testing Testing the VPN in the container will vary depending on the provider or use case, but here are some tips. These examples will be using the `AlmaLinux 8 - VPN` Workspace configured earlier. #### Tailscale testing An easy way to test is to simply run a ping to another device on the Tailscale network from the workspace. In order to test this at least one other device connected to the Tailscale network will be needed. From the Tailscale dashboard [here](https://login.tailscale.com/admin/machines) the IPs of other connected devices can be seen. This example will be using `100.86.224.182`. Assuming the Workspace is a modified desktop Workspace and in particular that this container is using the AlmaLinux 8 example from above. Once launched into the session go ahead and open a terminal from Applications -> Terminal Emulator: ```{figure} /images/vpn_sidecar/openterminal.png :align: center **Opening a Terminal** ``` Now run a ping command: ``` ping 100.86.224.182 ``` There should be acks printed to the screen: ```{figure} /images/vpn_sidecar/pings.png :align: center **Ping Response** ``` Any container with this configuration will have access to other machines on the connected Tailscale network.