Routing Traffic From Kubernetes Cluster Using the Twingate Client

Introduction

The purpose of this guide is to demonstrate how the Twingate headless Client can be used as a router to connect to your remote resources from within a GKE cluster.

The general idea is to use the Twingate Headless Client in a dedicated Virtual Machine that acts as a Router from the perspective of the GKE Cluster:

We can then enter the required details:

You can leave the remaining default settings and click create.

Twingate Router Setup

We must first setup the virtual machine which will run the Twingate client and also act as a router for any internal services which need to communicate to resources within Twingate. This virtual machine will run in “headless” mode and therefore require a service account to be created.

Setting up a service account

To create a service account, open your Twingate admin page, select Team and then the services tab:

Click on Create Service Account and give it a sensible name:

You should then generate a dedicated service key:

Once you generate the key, take a copy of the Key Object as this is what the headless client uses to authenticate.

Setting up the virtual machine

Again, use the GCP console to search for ”VM instances”, then select ”Create Instance“.

Enter a suitable name and place the virtual machine in the same region you setup the subnet in the VPC previously.

Scrolling down to Boot Disk, select change:

Change the OS to Ubuntu:

And pick the version to the x86/64 image

Then click Select to select this as your machine image.

Next expand the networking section.

Expand the Networking section and tick the IP Forwarding checkbox:

Scroll down to Network Interfaces and delete the pre-configured interface:

Click Add Network Interface and select the network and subnet you created previously:

(The remaining settings can be changed to suit your requirements but for the purpose of this guide we will just click the create button with no added configuration.)

Configuring the virtual machine

To enable access to the virtual machine we will need to configure a firewall rule to allow SSH, navigate back to the VPC networking section and select the VPC network you created earlier.

Scrolling to the bottom of the page, select Firewalls and then click Add firewall rule.

Create a new firewall rule with a name of your choice. We will want to change the Targets to All instances in the network, the source IP to 0.0.0.0/0 and specifying tcp port 22.

This rule will expose port 22 to the internet, if you would like to restrict this further please see this official guide.

Now we can connect to the virtual machine by going back to the VM instance screen and clicking on the SSH button.

This will popup a new window and you should now have access to the virtual machine shell.

Installing Twingate

We will be installing the Twingate Client in “headless” mode which means that it will authenticate using the service account we created earlier. It also means that it can be run in the background without any interaction.

The following steps are taken from the official guide here. If you are having issues with these steps, please refer to the official guide.

Installation

Enter the following command in the terminal / shell:

curl https://binaries.twingate.com/client/linux/install.sh | sudo bash

After a few moments the installation will complete.

Next we need to create the file which will be used to configure the headless client, create a new file and copy the contents of the key you saved earlier:

nano /tmp/service_key.json

Save this file.

We can then use this file in the Twingate setup by running the following:

sudo twingate setup --headless /tmp/service_key.json

You will see that this has completed the setup:

Twingate Setup 1.0.58.46266 | 0.129.0
Copying service key
Setup is complete.

We can now start Twingate:

sudo twingate start

You should see that it has successfully started and connected:

Starting Twingate service in headless mode
Twingate has been started
Waiting for status...
online

Next we will need to setup the virtual machine so it can route the traffic from inside the network via the new Twingate connection.

First we need to allow ip forwarding:

sudo nano /etc/sysctl.conf

Scroll down this file and uncomment net.ipv4.ip_forward=1:

Save the file.

Then we need to run the following command to apply the changes:

sudo sysctl -p

Next we need to make changes to iptables on the virtual machine by entering the following commands:

sudo iptables --append FORWARD --in-interface ens4 --out-interface sdwan0 --jump ACCEPT

sudo iptables --append FORWARD --in-interface sdwan0 --out-interface ens4 --match state --state RELATED,ESTABLISHED --jump ACCEPT

sudo iptables -t nat --append POSTROUTING --out-interface sdwan0 --jump MASQUERADE

To ensure these rules remain when the VM is restarted we can install the following:

sudo apt install iptables-persistent -y

Enter YES on both screens when they popup.

That is all the configuration required on the router.

The remote environment

We will need a remote network and resource which we allow our headless client to communicate with. Setting up the remote network in Twingate is beyond the scope of this guide, but you can find information on how to do this here.

For the purpose of this guide we will use a remote network with a simple application deployed with an internal IP address of 10.43.40.159:

Click the Add Access button and give the GKE-Router service access to the resource you have created.

We can now test this access by going back to the VM in GCP and running a simple CURL command:

This can take a few minutes to update the permissions so you may need to wait a few minutes for this to work.

curl 10.43.40.159

Depending on what your resource is serving may mean you need to run a different command.

Which then returns the HTML from the Ghost web site:

...
<!DOCTYPE html>
<html lang="en">
<head>

    <title>GHOST BLOG</title>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="HandheldFriendly" content="True" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <link rel="stylesheet" type="text/css" href="/assets/built/screen.css?v=4c7ae18aa5" />
...

This shows the router has access to the Twingate resource, now we can create a GKE cluster and setup access from it.

Setting up the GKE cluster

Again using the search facility in the GCP console, search for GKE.

Click on create to create a new cluster, selecting a standard cluster.

Name the cluster and make sure it is in the same region and zone as the router.

This is minimal configuration for this guide so you may want to alter other settings in the GKE cluster to suit your requirements.

Select Networking and make sure the cluster is in the network and subnet you created earlier.

Click create to start creating the new GKE cluster, this process will take a few minutes.

Adding the static route

In order for the traffic to route properly from outside of the router VM (ie from the Kubernetes Cluster), we need to add a static route to the Twingate Resource IP address and ensure this is sent via the router.

Navigate back to the VPC network settings page and click on routes.

Click on create route.

Enter in the relevant details for your new route, below is an example based on the configuration in this guide.

You will see that the destination IP range is the IP address used in the example above: This should be your own resource IP address or range used in the remote network.

As shown below, make sure you specify the correct network and the next hop as the VM instance created earlier.

Click the create route button.

Updating firewall rules

By default the GKE cluster and pods will not have access to “talk” to the router VM. Therefore we need to add firewall rules to allow this.

On the VPC network page click on Firewall and Create Firewall Rule.

Inbound from the cluster IPs:

You can find the IP addresses of the GKE nodes from the VM instances page

Inbound from the pod IP range:

You can find the pod and service IP range from the GKE cluster information page:

Then we can add these to a firewall rule:

Then click on the create button.

Testing the route from GKE

We will deploy a simple pod to the GKE cluster to allow us to test the route. First we need to access the cluster, the following command will copy the connection information and authentication to your local KUBECONFIG.

Setting up the gcloud cli and kubectl is beyond the scope of this guide.

gcloud container clusters get-credentials twingate-demo --region europe-west1-b

Check you have access to the cluster:

kubectl get pods -A

We can then create a simple pod, create a new file called ubuntu.yaml with the following contents:

apiVersion: v1
kind: Pod
metadata:
  name: ubuntu
  labels:
    app: ubuntu
spec:
  containers:
  - name: ubuntu
    image: ubuntu:18.04
    command: ["/bin/sleep", "3650d"]
    imagePullPolicy: IfNotPresent
    resources:
      limits:
        memory: "128Mi"
        cpu: "500m"
    securityContext:
      capabilities:
        add:
          - NET_ADMIN
  restartPolicy: Always

Then we can apply this to the cluster:

kubectl apply -f ubuntu.yaml

You should see the pod being created and in a running state:

NAMESPACE     NAME                                                      READY   STATUS    RESTARTS   AGE
default       ubuntu                                                    1/1     Running   0          45m

We can then access the pod with the following command:

kubectl exec -it ubuntu /bin/bash

Once inside the pod we need to install CURL by running the following:

apt update
apt install curl -y

Once CURL is installed we can test the connection to our remote resource:

curl 10.43.40.159

All being well you should see a response back from the remote resource:

As mentioned previously, depending on what the remote resource is, you may need to use a different command to test connectivity.

...
<!DOCTYPE html>
<html lang="en">
<head>

    <title>GHOST BLOG</title>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="HandheldFriendly" content="True" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <link rel="stylesheet" type="text/css" href="/assets/built/screen.css?v=4c7ae18aa5" />
...

Thank you for taking the time to read this guide, if you have any questions or issues when using this guide, please contact us, we appreciate any feedback.

Last updated 3 minutes ago