bug(?): Wireguard should allow packets from multiple peers
Andrew Sayers
andrew-wireguard at pileofstuff.org
Fri Apr 29 17:32:54 UTC 2022
Hi,
I think this is a bug, but some of it is beyond me.
This e-mail might actually just be a request for help :)
In some cases, an address can be associated with multiple peers.
I'll describe a specific scenario below, but in short: a device might have
peers with different-length netmasks, and might send and receive packets via
different routes depending on configuration of devices across the network.
A configuration similar to the one described below causes the error
"Packet has unallowed src IP" for the kernel backend, and causes
"packet with disallowed source address" for the Go backend.
See
https://git.zx2c4.com/wireguard-linux/tree/drivers/net/wireguard/receive.c#n415
and https://git.zx2c4.com/wireguard-go/tree/device/receive.go#n437
for the start of the relevant blocks. I assume other backends behave
similarly,
but don't have relevant test devices to hand.
If I understand correctly, these blocks only accept a *single* valid peer.
I'll argue below that behaviour is incorrect, but if it's right, the message
could stand to be improved. The kernel backend message reads:
"%s: Packet has unallowed src IP (%pISc) from peer %llu (%pISpfsc)\n"
Something like the following would be more helpful:
"%s: Packet has incorrect src IP (%pISc) from peer %llu (%pISpfsc)
instead of peer %llu (%pISpfsc)\n"
Using the word "incorrect" and specifying the (single) correct value would
indicate there's only one right value and would provide a hint to fix it.
To see why multiple peers should be allowed, consider the following:
Alice and Bob each have a home server and a phone with a networked camera.
They would like their servers to regularly download pictures from the
phones,
and would occasionally like to access the other's camera from their own
phone.
Their servers are reliably accessible over the Internet,
while their phones are behind firewalls and change address frequently.
They need to create a VPN that lets all four devices communicate.
They don't want to unnecessarily forward packets between servers,
and don't want to reconfigure their phones when they add more devices.
So they create an "Alice and Bob" subnet with IPv6* prefix `fdab::`.
Alice's phone's Wireguard configuration looks like this:
[Interface]
# Alice's phone has a single IP on the VPN:
Address = fdab:A1ce::1/128
[Peer]
# Alice's phone accepts all devices verified by her server:
AllowedIPs = fdab::/16
Endpoint = alices-server.example.com:51820
[Peer]
# Connect directly to Bob's server where possible:
AllowedIPs = fdab:B0b::/64
Endpoint = bobs-server.example.com:51820
Bob's phone's configuration is the inverse:
[Interface]
# Bob's phone has a single IP on the VPN:
Address = fdab:B0b::1/128
[Peer]
# Bob's phone accepts all devices verified by his server:
AllowedIPs = fdab::/16
Endpoint = bobs-server.example.com:51820
[Peer]
# Connect directly to Alice's server where possible:
AllowedIPs = fdab:A1ce::/64
Endpoint = alices-server.example.com:51820
When Alice's server tries to access Bob's camera, it sends packets directly
to his phone. Bob's phone sees a packet with a `fdab:A1ce::` source and
peer `alices-server.example.com`. That's fine - it accepts the packet.
But when Alice tries to access Bob's camera from her phone, the phone
sends those packets via Bob's server. Bob's phone sees a packet with
a `fdab:A1ce::` source and peer `bobs-server.example.com`.
Wireguard rejects these packets in my tests, presumably because
it expects Alice's packets to come from Alice's server.
Instead, Wireguard should accept packets from any peer
with a matching IP prefix in `AllowedIPs`.
To reply in advance to some obvious counterarguments:
Yes, this creates a needlessly asymmetric route (Bob's phone receives
messages via Bob's server and replies via Alice's server). You can argue
that's bad for complexity or good for privacy. So long as the packets
get to
their destination, I'd argue it doesn't matter.
Yes, this two-user example would be better solved with a star network
around either Alice or Bob's server. The value is more obvious at scale,
as load gets distributed between multiple servers. If you prefer, you can
add Carol and Dave to the network with configurations similar to the above.
No, this can't be solved by selecting a different "correct" peer.
That would force the servers to route data between them, adding
an extra hop and wasting bandwidth.
No, this can't be solved by telling the phones about each other.
Even if we could work around whatever firewall the phone might be behind,
and we could update DNS entries quickly enough when devices change address,
Alice and Bob would have to manually update their phones for every
device on the network. That's fine with the four nodes in the example,
but not practical at any greater scale.
- Andrew Sayers
* I'm just using IPv6 addresses for readability, although IPv6's larger
address space might cause more people to notice this issue
More information about the WireGuard
mailing list