Setting up WireGuard VPN on Linux, without configuring any additional IP addresses
I've been setting up WireGuard for Linux server-to-server communication in a possibly novel way - it seems to works well for my specific use case, but I haven't seen any other documentation pointing out that this is possible. So I thought I'd quickly describe what I've been doing.
The common way of using WireGuard is to configure the tun interfaces with different IP addresses. If your "real" network interfaces have addresses in the range 203.0.113.0/24 (e.g. hostA eth0 has 203.0.113.6), you would assign addresses to the wireguard interfaces from another range - typically from a reserved range such as 10.0.0.0/8 (e.g. hostA wg0 has 10.1.2.6).
To access services through WireGuard, you must then use the IP of the virtual interface. Even if hostA is 203.0.113.6 in DNS, you have to make sure to configure clients to use 10.1.2.6 when connecting.
Instead, I use the same IP address on both interfaces, with some additional routing config to make sure encapsulation happens "transparently".
- WG interfaces are configured with the same IP as the real network interface
- WireGuard listen port is set to 61234 on both peers
- A special routing table is set up to make sure that traffic to WG peers is routed to the WG interface
- An "ip rule" exception is set up to ensure that the WG udp traffic on port 61234 is NOT routed to the WG interface (which would cause a routing loop)
- No management of additional IP addresses are required. In fact we only use public IPv6 addresses, and so we don't really need to worry about IP space at all - just launch my servers in the cloud, RIPE and the cloud vendors take care of it for me, and the possibility of any IP conflicts should be eliminated.
- Clients can be configured to connect to the "original" DNS hostname of the server. You don't need to use raw IP addresses or set up alternate DNS names for each server.
- No rewrite / configuration changes are required for any existing software, outside of the WG setup itself.
- No IP roaming - this setup hardcodes endpoint IP addresses in the routing table, so it won't work if either peer changes it's IP address. For my server-to-server use case, this is not an issue.
- Fail open - As the destination addresses are potentially directly reachable, if the WireGuard setup is removed, traffic may be routed across the network without being encapsulated/encrypted. This risk may be somewhat mitigated by firewall rules that explicitly disallow directly routed non-WG traffic, and also by ensuring all your traffic is already encrypted anyway (e.g. using https/tls).
It's probably a pretty narrow use case, but for my specific situation I think this is a reasonable solution. I can connect servers placed in different networks (AWS/GCP VPCs in different cloud accounts) in a completely transparent way to our existing software - through the WG connection they can talk to each other on multiple ports, initiating connections both ways, etc. But in fact I only need a single open UDP port - in fact, only one side of the connection is reachable on a single UDP port. The other side relies on default stateful firewall rules to achieve full connectivity back to the mothership without requiring any open incoming ports at all.
I'd love to hear anything you have to say about this, especially about potential disadvantages I may not have considered. 😄