Years ago I set up OpenVPN for a customer. It works but is a bit cumbersome to get running. WireGuard is a new alternative, that is very easy to set up and maintain and also is very well designed from the technical point of view. It is also very performant.
A nice kind-of-vpn alternative is sshuttle.
Setting it up
- Install WireGuard: https://www.wireguard.com/install/
- And configure it…
There is actually no difference between client and server, except that the server listens on a fixed port (UPD), so there is a well defined point for the client to connect to.
On the server create
[Interface] Address = 192.168.10.1/24, fd10::1/64 ListenPort = 51820 PrivateKey = <server_private_key> [Peer] PublicKey = <client_public_key> AllowedIPs = 192.168.10.2, fd10::2
[Interface] block makes the server listen on port
51820 (IPv4 and 6) and assigns the interface
wg0 the given IP adresses (4 and 6 in this case). Use
wg genkey to generate a private key. (Setup UPD port forwarding in your router if the machine running the WG server is behind a NAT.)
[Peer] block allows incoming packages from a peer with the given public key and IP adresses (VPN internal). The public key can be derived from the private key with
You find more details in the man page of
On the client create
600 permissions, too.
[Interface] Address = 192.168.10.2/24, fd10::2/64 PrivateKey = <client_private_key> [Peer] PublicKey = <server_public_key> Endpoint = <server_fqdn_or_ip>:51820 AllowedIPs = 192.168.10.0/24, fd10::/64
This is the matching opposite to the server configuration with different IP addresses for the client. The
Endpoint tells WG where it can reach the server. The
AllowedIPs also causes routes to be set up, which cause the traffic for the specified address ranges to be routed through the VPN.
Now start the VPN with
sudo wg-quick up wg0 on client and server. That’s it.
sudo wg show shows the current status. Due to IP roaming and cryptokey routing, there is no need to reconnect, when the client’s IP addresses changes or the connection is lost. Stop the VPN with
sudo wg-quick down wg0 (on the client, leave it up on the server).
You can add more clients, each with it’s own IP addresses and keys. Create a config and private key for each client and add the client’s pubkey key to the server config in another
Change the addresses ranges to whatever you like.
It is possible to have
systemd keeping the VPN up, enable it with
sudo systemctl enable wg-quick@wg0.
The example above allows a connection between client and server only (dashed line). Usually you want the client to be able to access the entire local network of server (the Ms). To make this possible, the configuration hast to be extended (the ugly part).
graph LR C[client] -.-> I((internet)) I -.-> R(router/NAT) subgraph local network R -.-> S[server] R --- M1 R --- M2 R --- M3 end
Let’s assume the server is connected to the local network on
fd00::10/64. Then we change the
AllowedIPs in the client config:
AllowedIPs = 192.168.10.0/24, fd10::/64, 10.0.0.0/24, fd00::/64
This does the following
- It allows traffic from the local network to reach the client through the VPN and
- sets up a route on the client, which directs traffic to these IP ranges through the VPN.
On the server we need to configure forwarding and masquerading, to the
[Interface] section we add:
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -A FORWARD -i %i -j ACCEPT; ip6tables -A FORWARD -o %i -j ACCEPT; ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE; ip6tables -D FORWARD -i %i -j ACCEPT; ip6tables -D FORWARD -o %i -j ACCEPT; ip6tables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
eth0 with the actual name of the interface.
It is also possible to route the entire traffic (internet access) through the VPN by setting
AllowedIPs = 0.0.0.0/0, ::/0
on the client. And adding
DNS = 10.0.0.1, fd00::1
[Interface] section of the client (assuming the router is the DNS server for the local network with IP addresses
fd00::1) sets the client’s primary DNS. This way DNS is performed through the VPN and even the names of machines in the local network are resolved.
It is possible to do this without IP masquerading as well, but this requires static routes to the VPN with the server as gateway to be configured on the router of the local network.