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.