Building Secure Networks with Wireguard

Wireguard is an exciting new open source VPN networking project that lets you build encrypted networks without the overhead and performance penalty. What makes it interesting is it does it at near line speed.

Alternatives include Ipsec and applications like Openvpn, Peervpn or Tinc. Ipsec doesn't have the performance overhead but is relatively complex to setup. Openvpn and Peervpn are easier but can take a significant toll on performance.

For instance on Peervpn we see gigabit networks operating at 140/160 Mbs compared to Wireguard which can operate at around 870/900 Mbs which is close to line speed. This is extremely fast.

Wireguard is a layer 3 technology. It lets you build an encrypted overlay or private network over existing network connections. You connect servers with Wireguard and can further share any subnets residing on these servers which makes it useful for connecting containers and VMs across servers. Wireguard also gives you the flexibility to segment and isolate networks as required.

Flockport has builtin support for Wireguard and automates setting up Wireguard networks. But in this article we are going to look at how Wireguard networks are built so users have a clear idea of the underlying technology and configuration.

Before we proceed its important to understand why you would need a private network. Encryption is rarely needed for internal networks but is useful when building networks that span the public internet for instance connecting across cloud providers or data centres or networks that will cross the public internet or untrusted networks.

Installing and Configuring Wireguard

The first step is to install Wireguard on the hosts you intend to connect to a Wireguard network. Fortunately Wireguard has packages for the popular Linux distributions.

Once Wireguard is installed the configuration files are placed in /etc/wireguard and you can use standard Linux networking tools to build Wireguard networks. Wireguard also provides a number of utilities to generate keys and other Wireguard functions in the wireguard-tools package.

Setting up a Wireguard Network

Let's assume we want to create a private network that connects 2 cloud providers or data centers. Network design is important here.

You can create a point to point connection and share routes on either side. In this case connection between the 2 edge servers will be secure and each side will act as routers. Or alternatively you can create a network than spans multiple hosts across networks.

For this guide let's create a private network of 3 servers located in 3 cloud providers. The Wireguard network will be built over their public IPs and connect all 3 servers in a secure network. Let's call the servers s1, s2, s3 with public IPs 107.100.10.10, 108.100.10.10, 109.100.10.10 respectively.

Before building the network we need to select a private subnet for the Wireguard network and a master server. In our case lets use 192.168.100.0/24 as the Wireguard subnet with server s1 as the master. Let's also use 192.168.100.10, 192.168.100.11 and 192.168.100.12 as the private IPs for s1, s2 and s3.

The first step is to generate keys pairs for each server. This can be easily done by running the bundled wg utility on each server

wg genkey | tee private.key | wg pubkey > public.key

On the master create a wg0.conf file in /etc/wireguard like below and add the private IPs of the other servers along with their public keys and public IP.

Server S1

[Interface]
Address = 192.168.100.10
PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk=
ListenPort = 51820

[Peer]
PublicKey = xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=
AllowedIPs = 192.168.100.11
Endpoint = 108.100.10.10:51820

[Peer]
PublicKey = TrMvSoP4jYQlY6RIzBgbssQqY3vxI2Pi+y71lOWWXX0=
AllowedIPs = 192.168.100.12
Endpoint = 109.100.10.10:51820

On each of the clients create a wg0.conf file in /etc/Wireguard. The clients are peering with the server so add the servers public key and IP, 107.100.10.10 in this case, like the configuration below. We are using 51280 as the wireguard port, ensure the port is open in the firewall.

Client S2

[Interface]
Address = 192.168.100.11
PrivateKey = oK56DE9Ue9zK76rAc8pBl6opph+1v36lm7cXXsQKrQM=
ListenPort = 51820

[Peer]
PublicKey = HIgo9xNzJMWLKASShiTqIybxZ0U3wGLiUeJ1PKf8ykw=
Endpoint = 107.100.10.10
AllowedIPs = 192.168.100.0/24

Client S3

[Interface]
Address = 192.168.100.12
PrivateKey = gI6EdUSYvn8ugXOt8QQD6Yc+JyiZxIhp3GInSWRfWGE=
ListenPort = 51820

[Peer]
PublicKey = HIgo9xNzJMWLKASShiTqIybxZ0U3wGLiUeJ1PKf8ykw=
Endpoint = 107.100.10.10
AllowedIPs = 192.168.100.0/24

We will examine the configuration in more detail shortly but lets bring up the network first. On each of the servers run the wg-quick command.

wg-quick up wg0.conf

This will bring up the Wireguard network. You can use the wg show command to get an overview of the wireguard network status.

At this point you should be able to ping the servers from each other over the 192.168.100.0/24 private network. Any services that need to use a secure network can use this network.

To add more servers to the network you can replicate the client configuration. For instance to add host s4 with public IP 110.100.10.10 simply install Wireguard on the s4, replicate the client config and add it to the server under peer.

[Interface]
Address = 192.168.100.10
PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk=
ListenPort = 51820

[Peer]
PublicKey = xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=
AllowedIPs = 192.168.100.11
Endpoint = 108.100.10.10:51820

[Peer]
PublicKey = TrMvSoP4jYQlY6RIzBgbssQqY3vxI2Pi+y71lOWWXX0=
AllowedIPs = 192.168.100.12
Endpoint = 109.100.10.10:51820

[Peer]
PublicKey = GtL7fZc/bLnqZldpVofMCD6hDjrK28SsdLxevJ+qtKU=
AllowedIPs = 192.168.100.14
Endpoint = 110.100.10.10:51820
Adding Container Subnets to the Network

You can also share subnets on each of the servers for instance any container subnets to the network. To enable this simply add the container subnets to the AllowedIPs config on the server and clients and the subnets will be able to reach each other over the secure network. In this case Wireguard will automatically set up the required routes.

For instance suppose s1, s2 and s3 host container subnets 10.0.4.0/24, 10.0.5.0/24 and 10.0.7.0/24 respectively. You can add each of the subnets to the peer config on the server like below.

Server S1

[Interface]
Address = 192.168.100.10
PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk=
ListenPort = 51820

[Peer]
PublicKey = xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=
AllowedIPs = 192.168.100.11, 10.0.5.0/24

[Peer]
PublicKey = TrMvSoP4jYQlY6RIzBgbssQqY3vxI2Pi+y71lOWWXX0=
AllowedIPs = 192.168.100.12, 10.0.7.0/24

And then add all the container subnets to the clients config on each of the servers except it's own like below.

Client S2

[Interface]
PrivateKey = oK56DE9Ue9zK76rAc8pBl6opph+1v36lm7cXXsQKrQM=
ListenPort = 51820

[Peer]
PublicKey = HIgo9xNzJMWLKASShiTqIybxZ0U3wGLiUeJ1PKf8ykw=
Endpoint = 107.100.50.10
AllowedIPs = 192.168.100.0/24, 10.0.4.0/24, 10.0.7.0/24

Client S3

[Interface]
PrivateKey = gI6EdUSYvn8ugXOt8QQD6Yc+JyiZxIhp3GInSWRfWGE=
ListenPort = 51820

[Peer]
PublicKey = HIgo9xNzJMWLKASShiTqIybxZ0U3wGLiUeJ1PKf8ykw=
Endpoint = 107.100.50.10
AllowedIPs = 192.168.100.0/24, 10.0.4.0/24, 10.0.5.0/24

Now restart the Wireguard network in each of the servers and the container subnets should be able to ping each other.

wg-quick down wg0.conf
wg-quick up wg0.conf

Using the individual subnets in the configuration gives you the flexibility to segment and isolate networks when required. Alternatively you can also use wider network ranges on the client configuration instead of individual subnets for simplicity.

Client S2

[Interface]
PrivateKey = oK56DE9Ue9zK76rAc8pBl6opph+1v36lm7cXXsQKrQM=
ListenPort = 51820

[Peer]
PublicKey = HIgo9xNzJMWLKASShiTqIybxZ0U3wGLiUeJ1PKf8ykw=
Endpoint = 107.100.50.10
AllowedIPs = 192.168.100.0/24, 10.0.0.0/16

Using the wide 10.0.0.0/16 subnet here means any traffic from 10.0.* will be accepted by the network.

Now lets get back to the configuration and undertand what 'AllowedIPs' is doing on the server and the client. There is a subtle distinction and is important to understand.

On the server the AllowedIPs is like an router, and tells the server where to route traffic.

On the client the AllowedIPs functions like an access control list. If the network is not listed under AllowedIPs then incoming traffic is simply dropped

The wq-quick command is a shell script that automates a number of networking commands used to bring up the Wireguard network. it creates the wg0 Wireguard network devices, configures the IP, brings it up and parses the wg.conf configuration at /etc/Wireguard to set up routes. You can do this manually by adding the interfaces and necesary routes, wgquick simplifies this.

Flockport automates the process of setting up and managing Wireguard networks and lets you build secure networks on demand.

Flockport also lets you build overlay networks with Vxlan and BGP.


RELATED POSTS