Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.Sign up
Use same source address for UDP packets that is used for TCP packets #2623
This PR changes ServerHandler to bind our UDP socket to the same address that our TCP socket is bound to locally.
Murmur actually requires this for UDP to work, due to the way checkDecrypt in Murmur works.
It only tries to look up potential users by the address they're mapped to in qhUsers, which is the TCP address that user is connected with.
This PR also adds a config option. This is to allow users to switch back to the old behavior, if necessary.
This fixes some of the problems raised in #1377. Before this change, Murmur would immediately switch to using a new temporary address as the source address for UDP packets, once a new preferred temporary address was available.
That is, for IPv6 privacy addresses, in a scenario where a given temporary address has a validity of 1 day, but a preferred lifetime of only 4 hours, Mumble would keep connected (via TCP) for the whole day, but voice would only work during the initial 4 hour window. After the 4 hours, Mumble would switch to using whichever new temporary address was made available to it (or even a regular address... we let the kernel decide.)
I can see we bind to the same local address now. But how does that change the behaviour of the UDP socket? Wouldn’t the same problem still occur once the local hostname expires, UDP switch but TCP not?
The scenario is this:
For TCP, we bind to whichever address the kernel gives picks for the connection.
In general, this "works". But it breaks in subtle ways when you use IPv6 privacy addresses.
An IPv6 privacy address has a "preferred lifetime" (default 4h in Ubuntu) and a "valid lifetime" (default 24h in Ubuntu).
When you start up your Mumble client and connect to an IPv6 server, it'll use the privacy address (in a typical configuration, at least -- the kernel can be configured to not prefer the temporary privacy addresses).
(5 hours later)...
At this point, the "preferred lifetime" of the privacy address has expired. At this point, the kernel has created a new privacy address that is now "preferred". But the existing address will still be available for a good ~19h. It just won't be used for new connections.
Now comes the "unfortunate" part:
Since TCP is connection-oriented, even though the original privacy address has expired, the connection is still there -- and it will be for another ~19h. Good. And: it still uses the original privacy address.
For UDP, it's a different story. Since we used the "Any" address, at this point any UDP packets we send will be sent with a source address of the new preferred privacy address.
Now there's a mismatch between the TCP source address and the UDP source address, and Murmur doesn't like that.
Voice packets won't be delivered.
What this patch does is change the UDP address we bind to, to be the same as the TCP address.
The result is both the TCP and the UDP sockets now keep working until the address is fully expired, when the validity lifetime has passed.