Make your VPN work EVERYWHERE
Published: July 7, 2020
Making wireguard work perfectly when I'm not at home is a priority for me. When it doesn't work it is very frustrating.
The problem you're likely to have is that your home network's IP range overlaps with the network you're connected to. For example, my home network was configured to use the 10.0.0.0/24 subnet because it was easy to type. Lot of other people use that network too. If your home network is the same as mine, or perhaps configured to use something like 192.168.0.0/24, you'll run in to this problem all the time.
Here is how to fix this problem - use a network that isn't common, and route the smallest, most specific prefixes possible, and avoid IP address assignment conflicts. Sound hard? Actually, it's not that bad. Read on to learn how to build a bulletproof VPN.
IPv4 Subnet Address Choices
There are only 3 ranges of IPv4 addresses available for local networks. You've probably heard them called RFC 1918 networks.
- 10.0.0.0/8 (10.0.0.0 - 10.255.255.255)
- 172.16.0.0/12 (172.16.0.0 - 172.31.255.255)
- 192.168.0.0/16 (192.168.0.0 - 192.168.255.255)
Most people are familiar with 192.168.0.0/16. It's commonly used in consumer grade hardware by default. Many small businesses also use it because they use consumer grade hardware too. Larger companies might choose to use the 10.0.0.0/8 network because it has an immense range of available addresses. The 172.16.0.0/12 networks are in my experience used much less frequently.
Fixing our conflicted subnet routing problem
We need to pick a subnet that is seldom used so we can avoid routing problems. Doing this is a four step process:
- Pick a Random VPN tunnel address range.
- Pick a Random LAN tunnel address range.
- Use the MOST SPECIFIC prefixes possible.
- Avoid using IP addresses likely to be used as a gateway on other networks.
Step 1/4: Picking a very uncommon IPv4 VPN Network Range
For our VPN, we want something uncommon. So I'll choose something in the 126.96.36.199/12 range. I also want to avoid even numbered networks because many network administrators like to use .10, .20, .30, etc. I'm going to choose 172.19.13.0/24 for my VPN. 19 is far enough from 172.16.0.0/16 which many admins would choose simply because it's the first available subnet in this RFC 1918 range. I choose 13 because it seems unlikely that someone else would pick it for their network.
For our example, I'm going to choose 172.19.13.0/24 for the range of IP addresses that we'll use for our Wireguard tunnels. In my configs, I'll pick one address for each device. For example:
- Router/Gateway: 172.16.13.11/32
- Windows Laptop: 172.16.13.12/32
- MacBook: 172.16.13.13/32
- Android: 172.16.13.14/32
- iPhone: 172.16.13.15/32
Step 2/4: Picking an uncommon IPv4 LAN Network Range
In step 1, we picked out a small set of addresses to use in our network tunnel. This doesn't solve the larger problem which is this: Our LAN network conflicts with many other networks because it uses 10.0.0.0/24 or some other very common IPv4 address space. Let's pick a different subnet. I bet you already know what I'm going to do. We're going to reconfigure the LAN to use uncommon subnets too. For this, I'll pick 172.23.0.0/16 as my address space. For my primary LAN let's say I use 172.23.26.0/24.
Now I have my VPN running on 172.19.13.0/24 and my local LAN will be in 172.23.26.0/24. Most people would stop here. To make routing multiple networks easy, in wireguard (or any other VPN for that matter) they'd route 172.23.0.0/16 through the tunnel and everything works... usually. We do this in the wireguard configuration file by writing: AllowedIPs = 172.23.0.0/16
There is one more step we can take to make it even more likely that our VPN will succeed when most others would fail.
Step 3/4: The Secret SAUCE. Use the most specific prefixes possible
When routing happens, the most specific prefix will always "win". This means that the more specific you can be in your VPN prefixes, the better. Routing 172.23.0.0/16 is good and will work, usually. However, routing 172.23.26.0/24 is even better and routing a single host such as 172.26.23.101/32 is best and will be the most reliable.
If we know we're only actually using 172.23.26.0/24, then we should create a route specifically for that instead of the full 172.23.0.0/16 range that we're planning to build our network in. So we change our AllowedIPs list to this: AllowedIPs = 172.23.26.0/24
We can go crazy here. If we know specific IP addresses that we want accessible, we can route only those (and skip routing the /16 or the /24).
- Server 1: 172.23.26.101/32
- Switch 1: 172.23.26.99/32
- Raspberry PI: 172.23.26.105/32
Our route list if we only want and need to use these devices could look like this:
AllowedIPs = 172.23.23.101/32, 172.23.26.99/32, 172.23.26.105/32
By being very specific, we're unlikely to have a conflict EVEN if the network we're connected to happens to utilze the address ranges we've chosen for our LAN and VPN. I personally don't take it this far because listing each device is tedious and usually not necessary. I'm content to set AllowedIPs = 172.23.26.0/24. This will work perfectly unless I happen to be on someone else's 172.23.26.0/24 subnet. In that case, the more specific /32 routes have a better chance to work because they're less likely create a conflict.
Step 4/4: Avoid addresses that are likely to be used as the default gateway
If you really want your VPN to work anywhere there is one more step you can take. Avoid x.x.x.1 and x.x.x.254 and any other common addresses that a network administrator might have configured as a gateway. You don't have to use 172.23.26.1 for your gateway. Pick a different address! Now if you happen to be on a network that manages to conflict with your carefully chosen vpn and lan networks, your very carefully chosen specific prefixes chosen in step 3 still have a good chance to work.
Avoiding conflicts for IPv6 is easy. All you need to do is randomly generate a ULA Prefix. That's it, problem solved!
Thanks for reading. You can reach me by email. My name is greg, and you'll be able to guess my email from there... :)