Networking: DHCP+VPN, LAN communication query
Preface: I know not what I talk about.
INSTANCE: A Unifi network with multiple VLANs, each with their own subnet. A Linux client that is assigned to a single VLAN, connected to the network via Wi-Fi, and running a full-tunnel Wireguard config which tunnels data to the provider's endpoints.
QUESTION: While running full-tunnel VPN configurations supplied by a commercial VPN provider, how might the client device talk with other devices on the same (local!) LAN as it is, including devices that are on a different (local!) VLAN, and thus a different subnet?
Let's say, for instance, that I have the following network architecture:
Name Subnet Gateway Mask
Internal 10.0.0.0/24 10.0.0.1 255.255.255.0
Hosted 10.5.0.0/24 10.5.0.1 255.255.255.0
Private 10.5.1.0/24 10.5.1.1 255.255.255.0
Guests 10.5.2.0/24 10.5.2.1 255.255.255.0
I have a device that is connected to the network via Wi-Fi, and is contained within the "Private" VLAN. It can also talk to devices that are in the "Internal" VLAN (by necessity), and devices in the "Hosted" VLAN.
Once I spin the VPN up, using a configuration gained from OVPN / PIA / NordVPN / whatever, the client can still communicate with devices on the same VLAN as it- for example, if the client is 10.5.1.132, it can still communicate with 10.5.1.42, but it cannot communicate with, say, 10.5.0.11. One would assume that is because the DHCP server has told it that it can access devices within a specific range through the correct gateway- and in-fact, this shows in the IP routing table:
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default unifi.localdoma 0.0.0.0 UG 1024 0 0 eth0
10.5.1.0 0.0.0.0 255.255.255.0 U 1024 0 0 eth0
unifi.localdoma 0.0.0.0 255.255.255.255 UH 1024 0 0 eth0
There are, as far as I can tell, a number of solutions for this problem. The first is to not use a full-tunnel VPN, and instead build a set of AllowedIPs which carve out the LAN ranges which you do not want tunneled. This, I think, is known as a split-tunnel VPN. If one wants to carve out all of the possible LAN IP ranges, as specified in RFC1918, it starts to become somewhat cumbersome:
AllowedIPs = 0.0.0.0/5, 8.0.0.0/7, 11.0.0.0/8, 12.0.0.0/6, 16.0.0.0/4, 32.0.0.0/3, 64.0.0.0/2, 128.0.0.0/3, 160.0.0.0/5, 168.0.0.0/6, 172.0.0.0/12, 172.32.0.0/11, 172.64.0.0/10, 172.128.0.0/9, 173.0.0.0/8, 174.0.0.0/7, 176.0.0.0/4, 192.0.0.0/9, 192.128.0.0/11, 192.160.0.0/13, 192.169.0.0/16, 192.170.0.0/15, 192.172.0.0/14, 192.176.0.0/12, 192.192.0.0/10, 193.0.0.0/8, 194.0.0.0/7, 196.0.0.0/6, 200.0.0.0/5, 208.0.0.0/4, 224.0.0.0/3
This might be the only solution that currently works on an Android device running the basic Wireguard APK, as found on Github.
An alternative solution is to carve out the LAN ranges you want to avoid routing through the tunnel using the PostUp/PostDown entries. For example:
PostUp = ip route add 10.5.0.0/16 via 10.5.1.1 [dev IFNAME?] [metric INT?]
PostDown = ip route del 10.5.0.0/16 via 10.5.1.1
This would work, on your local LAN, as long as you stay on the same VLAN and can connect to the correct gateway. Unfortunately, Android Wireguard cannot handle PostUp/PostDown entries, AFAICT. Small bother.
One final solution that I have heard mutterings about is known as "Classless Static Routes", or DHCP Option 121/249. This uses "CIDR" notation, and I'll be honest- here I am a little bit lost. I like the sound of this solution, as it means that I can configure the networking infrastructure itself to provide the required information for valid routing, and not have to faff about with the many, many Wireguard configurations on my devices.
Does anybody have any experience with this problem? Am I approaching this problem in an entirely stupid way? Is there a better way (insert infomercial here)?
This site will likely be of interest to you: https://www.procustodibus.com/blog/2021/03/wireguard-allowedips-calculator/
The WireGuard
allowedIPsdrawbacks are well-known, so someone's created a handy calculator. They also discuss alternatives below.Personally, I'm a WireGuard maximalist. Just use
allowedIPs, even if it's cumbersome.Oh, totally- I used that site to generate the AllowedIPs chunk above. It just feels somewhat clunky as a solution, and for some reason, one some Linux devices, it causes all sorts of instability. The PreUp and PreDown technique is also outlined above, but I'm not satisfied that it works as a global solution across different LANs. Maybe I shouldn't be searching for perfect, as always, though..
I'm having a tough time following along but it sounds like you're trying to do split tunneling, I.e.; access resources locally (both on the 10.5.1.0/24 subnet as well as 10.5.0.0/24 and have everything else go through the VPN interface?
Sounds like your client is on Android? There is an alternative wireguard frontend that has some level of split tunneling that might help you called "WG Tunnel" that might expose the features you need.