mirror of
https://github.com/outbackdingo/firezone.git
synced 2026-01-27 18:18:55 +00:00
When calculating preferences for candidates, `str0m` currently always prefer IPv6 over IPv4. This is as per the ICE spec. Howver, this can lead to sub-optimal situations when a connection ends up using a TURN server. TURN allows a client to allocate an IPv4 and an IPv6 address in the same allocation. This makes it possible for e.g. an IPv4-only client to connect to an IPv6-only peer as long as the TURN server runs in dual-stack AND the client requests an IPv6 address in addition to an IPv4 address with the `ADDITIONAL-ADDRESS-FAMILY` attribute. Assume that a client sits behind symmetric NAT and therefore needs to rely on a TURN server to communicate with its peers. The TURN server as well as all the peers operate in dual-stack mode. The current priority calculation will yield a communication path that uses IPv4 to talk to the TURN server (as that is the only one available) but due to the preference ordering of IPv6 over IPv4, will use an IPv6 path to the peer, despite the peer also supporting IPv4. This isn't a problem per-se but makes our life unnecessarily difficult. Our TURN servers use eBPF to efficiently deal with TURN's channel-data messages. This however is at present only implemented for the IPv4 <> IPv4 and IPv6 <> IPv6 path. Implementing the other paths is possible but complicates the eBPF code because we need to also translate IP headers between versions and not just update the source and destination IPs. We have since patched `str0m` to extend the `Candidate::relayed` constructor to also take a `base` address which is - similar to the other candidate types - the address the client is sending from in order to use this candidate. In the context of relayed candidates, this is the address the client is using to talk to the TURN server. We can use this information in the candidate's priority calculation to prefer candidates that allow traffic to remain within one IP version, i.e. if the client talks to the TURN server over IPv4, the candidate with an allocated IPv4 address will have a higher priority than the one with the IPv6 address because we are applying a "punishment" factor as part of the local-preference component in the priority formula. Staying within the same IP version whilst relaying traffic allows our TURN servers to use their eBPF kernel which results in a better UX due to lower latency and higher throughput. The final candidate ordering is ultimately decided by the controlling ICE agent which in our case is the Firezone Client. Thus, we don't necessarily need to update Gateways in order to test / benefit from this. Building a Client with this patch included should be enough to benefit from this change. Related: https://github.com/algesten/str0m/pull/640 Related: https://github.com/algesten/str0m/pull/644
Connlib
Firezone's connectivity library shared by all clients.
Building Connlib
You shouldn't need to build connlib directly; it's typically built as a dependency of one of the other Firezone components. See READMEs in those directories for relevant instructions.