Need help with kubewg?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

munnerz
146 Stars 5 Forks 21 Commits 3 Opened issues

Description

Use Kubernetes to manage & distribute Wireguard configuration

Services available

!
?

Need anything else?

Contributors list

No Data

kubewg

kubewg is a Kubernetes controller that allows you to configure and manage [Wireguard] VPN configuration using a Kubernetes API server.

It introduces the following [CustomResourceDefinition] resources:

  • Network: Represents a Wireguard VPN network.
  • Peer: Represents a single Peer in a a Network. Each peer will be allocated an address in the network's subnet.
  • RouteBinding: Represents additional route configuration that should be used by all members of the VPN network.

How it works

kubewg is comprised of two core components:

  • The control plane - which stores and generates wireguard configuration in the form of Peer resources

  • guardlet
    - this component runs on each peer in your VPN. It watches the Kubernetes API for configuration stored on a Peer resource and applies it to the local Wireguard installation.

Quick start

Prerequisites:

  • 2 Linux or Darwin (OS X) systems, to test out the VPN
  • Kubernetes 1.10+
  • At least one peer must have an accessible network address for the Wireguard peers to connect to. If multiple have accessible network addresses, a mesh will be automatically formed.

Installing wireguard on each peer

Currently, kubewg does not bundle an installation of wireguard.

Therefore you must install Wireguard according to your system/platform installation method of choice.

You can find more information on install Wireguard on the [Wireguard website].

Generating private keys and public keys

Currently, kubewg does not handle generation of private or public keys.

This guide will set up two VPN peers,

laptop
and
server
.

On each of these two VPN peers, you must generate a private key and the corresponding public key to be used in later parts of the instructions.

After installing Wireguard, you can generate a private & public key using:

$ mkdir -p /etc/wireguard
$ wg genkey | tee /etc/wireguard/privatekey | wg pubkey > /etc/wireguard/publickey

This will create two files, named

privatekey
and
publickey
respectively.

You will need to repeat this step on each VPN peer you intend to add to the network.

Deploying the control plane

To get started, first install the kubewg controller into your Kubernetes cluster:

$ kustomize build ./config | kubectl apply -f

This will install the Network, Peer and RouteBinding CustomResourceDefinitions as well as the

kubewg-manager
controller into the
kubewg-system
namespace.

Creating a Network

To configure your first VPN network, you must create a Network resource. A network defines the CIDR that all VPN peers in the network should be assigned addresses from.

This example will configure two VPN peers,

laptop
and
server
, both with a static IP address.
apiVersion: wg.mnrz.xyz/v1alpha1
kind: Network
metadata:
  name: examplenet
spec:
  subnet: 10.20.40.0/24
  allocations:
  - address: 10.20.40.10
    selector:
      names:
      - server
  - address: 10.20.40.20
    selector:
      names:
      - laptop

This defines a simple network with 2 configured peers, using the 10.20.40.0/24 subnet.

You must specify IP allocations for each Peer in the network using the

allocations
stanza.

Creating a Peer resource

Now that we have configured a Network, we must create Peer resources for each peer that will be a member of the VPN network.

A Peer's

spec
stanza contains configuration detailing how to connect to the particular peer, including the peer's public key and connection endpoint.

We first configure a

laptop
peer:
apiVersion: wg.mnrz.xyz/v1alpha1
kind: Peer
metadata:
  name: laptop
spec:
  # We omit the 'host' portion of the listen address for the wireguard listener
  # to signal that this peer does not accept incoming connections from other
  # peers.
  # This is typically done when the peer sits behind a NAT firewall, e.g.
  # laptops and phones that may be portable.
  endpoint: :12345
  # Enter the public key of the 'laptop' wireguard peer here.
  # This public key is generated in the 2nd step of the guide.
  # You should be able to find this file at /etc/wireguard/publickey.
  publicKey: 

The

server
peer will need to specify an accessible network address for the
spec.address
field for the
laptop
peer to connect to:
apiVersion: wg.mnrz.xyz/v1alpha1
kind: Peer
metadata:
  name: server
spec:
  endpoint: wg.example.com:12345
  # Enter the public key of the 'server' wireguard peer here.
  # This public key is generated in the 2nd step of the guide.
  # You should be able to find this file at /etc/wireguard/publickey.
  publicKey: 

You must ensure that

wg.example.com:12345
is accessible from the
laptop
peer for the laptop peer to successfully connect to the Wireguard server.

Verifying route configuration has been generated

Once all the resources have been created, we can verify that peers have been configured correctly by checking the

status
stanza of the resources:
$ kubectl describe network examplenet
...
Status:
  Allocations:
    Address:  10.20.40.10
    Name:     server
    Address:  10.20.40.20
    Name:     laptop
...

$ kubectl describe peer laptop Status: Address: 10.20.40.20 Network: examplenet Peers: Allowed I Ps: 10.20.40.10/32 Endpoint: wg.example.com:12345 Name: server Public Key: ...

$ kubectl describe peer server ... Status: Address: 10.20.40.10 Network: examplenet Peers: Allowed I Ps: 10.20.40.20/32 Name: laptop Public Key: ...

If you cannot see output similar to the above, check the logs from the

kubewg-manager
component for indications of what may be failing.

Configuring the guardlet on each VPN peer

Now that we have verified our Wireguard configuration for each peer is being generated correctly, we must run the

guardlet
component on each VPN peer.

The

guardlet
is run using the
--peer-name
flag, and will automatically apply the Wireguard configuration on the named Peer resource to the local Wireguard installation, in order to configure the VPN network.

First, fetch a copy of

guardlet
, replacing OS with either
darwin
or
linux
and ARCH with
amd64
or
mips64
appropriately:
$ curl -LO https://github.com/munnerz/kubewg/releases/download/v0.1.1/guardlet-OS_ARCH
$ chmod +x guardlet-OS_ARCH
$ sudo mv guardlet-OS_ARCH /usr/local/bin/guardlet

You can check for a full list of available releases on the [release pages].

There are a number of command line options that can be passed to the guardlet to configure its behaviour:

$ guardlet --help
Usage of guardlet:
  -device-name string
        Wireguard network interface name (default "utun9")
  -kubeconfig string
        Paths to a kubeconfig. Only required if out-of-cluster.
  -master string
        The address of the Kubernetes API server. Overrides any value in kubeconfig. Only required if out-of-cluster.
  -metrics-addr string
        The address the metric endpoint binds to. (default ":8080")
  -os string
        Host OS, used to determine commands to use to configure wireguard. Currently only darwin is supported. (default "darwin")
  -peer-name string
        The name of this wireguard peer
  -private-key-file string
        Path to a file containing the wireguard private key for this peer (default "/Users/James/go/src/github.com/munnerz/kubewg/privatekey")
  -sync-period duration
        Adjust how often interface configuration is periodically resynced (default 5s)
  -use-kernel-module
        If true, the 'ip' command will be used to create a wireguard interface using the Linux kernel driver
  -wg-binary string
        Path to the wireguard 'wg' binary (default "wg")

There are a few special flags you must set when running the guardlet on different platforms. You can see these detailed below.

You must configure the guardlet with a

kubeconfig
file that gives it permissions to
get
,
list
and
watch
Peer resources.

The easiest way to do this is to create a ServiceAccount resource and grant it permission with RBAC roles, and then retrieve the service account token from the generated Secret resource:

$ kubectl create serviceaccount 
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: wireguard-peer
rules:
  - apiGroups:
      - wg.mnrz.xyz
    resources:
      - peers
    verbs:
      - get
      - list
      - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: 
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: wireguard-peer
subjects:
  - kind: ServiceAccount
    name: 
    # update this if you created the service account in a different namespace
    namespace: default

You can then retrieve the service account token using

kubectl get secret
:
$ kubectl get secret -o yaml -token-

The token will be displayed, base64 encoded, as the

data.token
key.

You can use this secret to generate a

kubeconfig
file that can be passed to guardlet.

Flags for OSX

$ sudo guardlet \
    --device-name utun9 \
    --kubeconfig path/to/kubeconfig/file \
    --private-key-file /etc/wireguard/privatekey \
    --os darwin \
    --peer-name  \

When running on OSX, the [wireguard-go] userspace Wireguard implementation is used.

Flags for Linux

$ sudo guardlet \
    --device-name wg0 \
    --kubeconfig path/to/kubeconfig/file \
    --private-key-file /etc/wireguard/privatekey \
    --os linux \
    --peer-name  \
    --use-kernel-module true

When running on Linux, the native kernel module can be used to configure the Wireguard interface for improved performance.

We must also set the

--device-name
flag to
wg[0-9]
, as the default of
utun9
is only appropriate for
wireguard-go
systems.

Verifying the VPN network is up

Once the guardlet has successfully reconciled its Peer configuration, you should see the following message:

{"level":"info","ts":1552945374.877612,"logger":"controller","msg":"Reconciled wireguard configuration"}

This indicates that the configuration has been successfully applied to the Wireguard peer.

From the

laptop
peer, you should now be able to ping the IP address of the
server
Wireguard peer:
# Run this command from the 'laptop' Wireguard peer
$ ping 10.20.40.10

Adding additional static routes

The kubewg

RouteBinding
resource can be used to configure static routes within a VPN network.

This can be used to expose local networks that are routable via VPN peers, or to create bridge points where traffic can be switched for the VPNs local subnet.

An example of a RouteBinding that exposes the network

192.168.1.0/24
that is local to the
server
VPN peer:
apiVersion: wg.mnrz.xyz/v1alpha1
kind: RouteBinding
metadata:
  name: server-localnet-route
spec:
  routes:
  - 192.168.1.0/24
  network: examplenet
  selector:
    names:
    - server

This configuration will be automatically propagated to all VPN peers in the examplenet network.

Configuring a static route for the VPN subnet

In cases where you have multiple remote clients connecting to a central Wireguard server that need to be able to communicate with each other, it can be useful to set up a static route for the VPN network's subnet via the central Wireguard server:

apiVersion: wg.mnrz.xyz/v1alpha1
kind: RouteBinding
metadata:
  name: examplenet-subnet-default-route
spec:
  routes:
  - 10.20.40.0/24
  network: examplenet
  selector:
    names:
    - server

If a peer has a more direct route to another peer in the Wireguard mesh, it will automatically take the shortest path to that peer.

Otherwise, this route will be used, allowing the central server to attempt to route packets to the destination host.

Generating a Wireguard .conf file

Some platforms may not support wireguard-go, such as tables and smartphones.

In order to provide support for managing configuration for these devices using kubewg, an addtional

mkconf
command is provided.

This command should be passed a

--peer-name
and
--private-key
argument which will be used to generate a .conf file that can be used by tools such as
wg-quick
.
# Run this command from within a checked out copy of the kubewg repository
$ go run ./cmd/mkconf \
    --peer-name  \
    --peer-namespace  \
    --private-key "$(cat privatekey)"

The generated config file will be outputted to stdout.

Generating a Wireguard config QR code

The

qrencode
utility can be used to generate a QR code containing the generated .conf file.

This is especially useful when generating configuration for a mobile device with a camera.

You can pipe the output of

mkconf
into
qrencode
in order to print a QR code to your terminal display:
# Run this command from within a checked out copy of the kubewg repository
$ go run ./cmd/mkconf \
    --peer-name  \
    --peer-namespace  \
    --private-key "$(cat privatekey)" | qrencode -t ansiutf8

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.