IPSec on Linux using wireguard

Description

In this post I'll show you how to install, configure and test IPSec for a site-to-site configuration on Linux using wireguard. (https://www.wireguard.io/).

In this P.O.C. we are using Ubuntu 16.04 LTS as the operating system, the configurations will be the same in all Linux OS's.  The main differences will be in the installation part.

Installation on all instances

 add-apt-repository -y ppa:wireguard/wireguard 
 apt update 
 apt install -y wireguard-dkms wireguard-tools

Scenario

___________________________________
server 1 -> 192.168.122.1 ( 3.4.4.0/24 and 2.4.4.0/24 behind it )  |

___________________________________

<-----------------IPSec connection ------>

___________________________________

 | server 2 -> 192.168.122.157 ( 5.4.4.0/24 and 4.4.4.0/24 behind it |

___________________________________

Initialization

On local instance

 ip link add dev wg0 type wireguard
 ip address add dev wg0 192.168.2.1/24
 wg setconf wg0 wireguard.conf
 ip link set up dev wg0

Adding routes on the first instance

 ip route add 5.4.4.4/32 dev wg0
 ip route add 4.4.4.4/32 dev wg0

On remote instance

 ip link add dev wg0 type wireguard
 ip address add dev wg0 192.168.2.2/24
 wg setconf wg0 wireguard.conf
 ip link set up dev wg0

Adding routes on the remote instance

ip route add 3.4.4.4/32 dev wg0
ip route add 2.4.4.4/32 dev wg0

See the config.

#wg

Generating the keys

On the local machine and remote machine we have to generate the crypto keys (public and private).

WireGuard requires base64-encoded public and private keys. These can be generated using the wg(8) utility as follows:

umask 077
wg genkey | tee privatekey | wg pubkey > publickey

On local machine define the configuration for wireguard  ( in wireguard.conf file)
Note: You have to generate your own private/public keys.

cat wireguard.conf

 [Interface]
 ListenPort = 4820
 PrivateKey = sPgiJvHsqEQLAUjEfZ+n/ZF1DUDRdrA146O1zAtLREk=

 [Peer]
 #Endpoint = 192.168.122.157:4820
 PublicKey = 69gpght0ZElLn82ClzU/gCGcfFVbautzo4nhZ5pgrzI=
 AllowedIPs = 192.168.122.157/32, 5.4.4.0/24, 4.4.4.0/24, 192.168.2.0/24

On remote machine define the configuration for wireguard ( in wireguard.conf)

 [Interface]
 ListenPort = 4820
 PrivateKey = oH7s+wvwonsXmgkSSt+G3/QPo2bq8OwAQ1rzFB/Z10Y=
 
 [Peer]
 Endpoint = 192.168.122.1:4820
 PublicKey = 5M5L68Qdgs51n/hT1QbSMN4Obpy0ViH5oEXME/cgA0s=
 AllowedIPs = 0.0.0.0/0

 

Testing the implementation

From local machine

ping 5.4.4.1
ping 4.4.4.1

From remote machine

ping 2.4.4.1
ping 3.4.4.1

 

Adding peers on the fly

Create a configuration file for the new peer called add_peer_a.cfg

 [Peer]
 PublicKey = gabBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=
 AllowedIPs = 11.11.11.0/24
 Endpoint = 44.44.44.44:4820

Activate it

 #wg addconf wg0 add_peer_a.cfg

Removing peers on the fly

wg set wg0 peer yTBBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg= remove

Reset the wireguard interface and the routes

ip link set down dev wg0
ip link del dev wg0

Key points from the author of wireguard

At the heart of WireGuard is a concept called Cryptokey Routing, which works by associating public keys with a list of tunnel IP addresses that are allowed inside the tunnel. Each network interface has a private key and a list of peers. Each peer has a public key. Public keys are short and simple, and are used by peers to authenticate each other. They can be passed around for use in configuration files by any out-of-band method, similar to how one might send their SSH public key to a friend for access to a shell server."

Built-in Roaming - The client configuration contains an initial endpoint of its single peer (the server), so that it knows where to send encrypted data before it has received encrypted data. The server configuration doesn't have any initial endpoints of its peers (the clients). This is because the server discovers the endpoint of its peers by examining from where correctly authenticated data originates. If the server itself changes its own endpoint, and sends data to the clients, the clients will discover the new server endpoint and update the configuration just the same. Both client and server send encrypted data to the most recent IP endpoint for which they authentically decrypted data. Thus, there is full IP roaming on both ends.

It is ready for containers.

 

References

Description of the protocol  - https://www.wireguard.io/protocol/
Benchmark  - https://www.wireguard.io/performance/
Complete documentation - https://www.wireguard.io/papers/wireguard.pdf

Personal opinion

The concepts behind wireguard are very interesting and are out there, but it requires a very good comprehension of a lot of modern concepts.

According to the  wireguard's author the implementation is finished, but the project is alive and still in developing phase.

I think, even in the current phase, it can be a great alternative to the classic IPSec  implementations, since it has a lot of modern principles in it, like:

- The interface appears stateless to the system administrator.

-  Endpoints roam, like in mosh.

- Identities are just the static public keys, just like SSH.

- Everything else, like session state, connections, and so forth, is invisible to admin.

- Simplicity in management.

 Wireguard reminds me, somehow of gif interface implementation from FreeBSD (https://www.freebsd.org/doc/handbook/ipsec.html), but this looks more compact to me since, it also includes  the cryptographyc part and is not relying on external implementation (OpenSSL).

If I had to describe the project i one word it would be: GREAT.

 

Author: techwritter