How does it work?
The crypto protocols and primitives are the following :
- ChaCha20 for symmetric encryption, authenticated with Poly1305, using RFC7539’s AEAD construction
- Curve25519 for ECDH which is a very fast Elliptic curve Diffie-Hellman with 128 bits of security and 256 bits of key.
- BLAKE2s for hashing and keyed hashing, described in RFC7693
- SipHash24 for hash-table keys
- HKDF for key derivation, as described in RFC5869
WireGuard works by creating a tunnelled network interface, usually called wg0 (users can add one or more, the other ones will becalled wg1, wg2, wg3, etc). This interface can then be configured normally like any other, using the standard tools just like the classical
The specific aspects of WireGurard’s interfaces such as the creation or removal of interfaces are done by using the wg tool.
WireGuard associates tunnel IP addresses with public keys and remote endpoints. From the network interface point of view this is what happens:
- Interface sends a packet: WireGuard finds the peer and encrypts the package with its public key and finally sends it to the current endpoint IP address and port.
- Interface receives a packet: WireGuard tries to decrypt it using the public key of the peer associated with the underlying endpoint IP address.
Behind the scenes there is much happening to provide proper privacy, authenticity, and perfect forward secrecy but this part will not be covered by this article.
WireGuard implements the concept called Cryptokey Routing, which associates public keys with a list of tunnel IP addresses that are allowed inside the tunnel. This is implemented by a Cryptokey Routing Table: a simple association of public keys and allowed IPs as it can be read on the example configurations at the end of this article.
Each network interface has a public, private key pair and a list of peers. Each peer has its own public key.
These keys are , and are used by peers to authenticate each other. The public ones can be passed around to be used in configuration files by any out-of-band methods, similarly to how one might send their SSH public key.
When sending packets, the list of allowed IPs behaves as a sort of routing table, and when receiving packets, the list of allowed IPs behaves as a sort of access control list.
WireGuard is now supported by many tools even graphical ones but internally its configuration boils down to something simple as the following. These files must be stored safely, usually under /etc/wireguard and are used by the wg tool in order to setup the needed network interfaces.
Server configuration wg0.conf :
PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk=
ListenPort = 51820
PublicKey = xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=
AllowedIPs = 10.192.122.3/32, 10.192.124.1/24
PublicKey = TrMvSoP4jYQlY6RIzBgbssQqY3vxI2Pi+y71lOWWXX0=
AllowedIPs = 10.192.122.4/32, 192.168.0.0/16
PresharedKey = <pre shared key from server for this client>
Client configuration wg0.conf :
DNS = <your_dns_ip>
PrivateKey = gI6EdUSYvn8ugXOt8QQD6Yc+JyiZxIhp3GInSWRfWGE=
ListenPort = 21841
PublicKey = HIgo9xNzJMWLKASShiTqIybxZ0U3wGLiUeJ1PKf8ykw=
Endpoint = 184.108.40.206:51820
AllowedIPs = 0.0.0.0/0
PresharedKey = <pre shared key for this server>
PersistentKeepalive = 25
As you can see the keys are something very manageable. The pre shared key is optional but it can give a paranoic post-quantum resistance.
The keys are generated simply using these commands:
|wg genkey > privkey
# Derive the public key from the private one
cat privkey | wg pubkey > pubkey
# Optionally, create a pre-shared key
wg genpsk > presharedkey
A brand new VPN software is here to stay and it looks very promising. Let us know if you are already using it and eventually what you think.
WireGuard and the WireGuard logo are registered trademarks of Jason A. Donenfeld.