fix(connlib): _always_ use one IP stack for relayed connections (#9018)

At the moment, Firezone already attempts to prefer the same IP stack
across relayed connections all the way through to the Gateway. This is
achieved with a feature in str0m implemented in
https://github.com/algesten/str0m/pull/640 where the `IceAgent` computes
the local preference of an added candidate such that an IPv4 candidate
allocated over an IPv4 network has a higher preference than an IPv6
candidate allocated over an IPv4 network.

If a candidate gets accepted by the local agent, it is signaled to the
remote via our control protocol. The remote peer then adds the candidate
as a remote candidate and the ICE process starts by pairing them with
local ones and testing connectivity.

Currently, str0m's API consumes the candidate and only returns a `bool`
whether it should be sent signaled to the remote. This means the local
preference computed as part of `add_local_candidate` **is not**
reflected in the priority of the candidate sent to the remote. As a
result, if the controlled agent (i.e. the Gateway) is behind symmetric
NAT and therefore only has relay candidates available, the preference of
IPv4 over IPv6 candidates on an IPv4 network is lost. This is what we
are seeing in #8998.

This changes with https://github.com/algesten/str0m/pull/650 being
merged to `main` which we are updating to with this PR. Now,
`add_local_candidate` returns an `Option<&Candidate>` which has been
modified with the local preference of the `IceAgent` around the
preferred IP stack of relay candidates. As such, the priority calculated
and signaled to the remote embeds this information and will be taken
into account by the controlling agent (i.e. the Client) when nominating
a pair.

Resolves: #8998
This commit is contained in:
Thomas Eizinger
2025-05-05 11:11:28 +10:00
committed by GitHub
parent 56a4cad124
commit 2d802edf6a
3 changed files with 9 additions and 9 deletions

2
rust/Cargo.lock generated
View File

@@ -6597,7 +6597,7 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "str0m"
version = "0.8.0"
source = "git+https://github.com/firezone/str0m?branch=main#8401a07556ee930866768d3993514fedb455b0b3"
source = "git+https://github.com/algesten/str0m?branch=main#6025dfde2e48905539255ec88f1350ab50428d50"
dependencies = [
"combine",
"crc",

View File

@@ -215,7 +215,7 @@ ip_network = { git = "https://github.com/JakubOnderka/ip_network", branch = "mas
ip_network_table = { git = "https://github.com/edmonds/ip_network_table", branch = "some-useful-traits" } # For `Debug` and `Clone`
tracing-stackdriver = { git = "https://github.com/thomaseizinger/tracing-stackdriver", branch = "bump-otel-0.26" } # Waiting for release.
softbuffer = { git = "https://github.com/rust-windowing/softbuffer" } # Waiting for release.
str0m = { git = "https://github.com/firezone/str0m", branch = "main" }
str0m = { git = "https://github.com/algesten/str0m", branch = "main" }
# Enforce `tracing-macros` to have released `tracing` version.
[patch.'https://github.com/tokio-rs/tracing']

View File

@@ -1387,14 +1387,14 @@ fn add_local_candidate<TId>(
return;
}
let is_new = agent.add_local_candidate(candidate.clone());
let Some(candidate) = agent.add_local_candidate(candidate) else {
return;
};
if is_new {
pending_events.push_back(Event::NewIceCandidate {
connection: id,
candidate: candidate.to_sdp_string(),
})
}
pending_events.push_back(Event::NewIceCandidate {
connection: id,
candidate: candidate.to_sdp_string(),
})
}
fn invalidate_allocation_candidates<TId, RId>(