Files
firezone/rust/Cargo.toml
Thomas Eizinger 301d2137e5 refactor(windows): share src IP cache across UDP sockets (#9976)
When looking through customer logs, we see a lot of "Resolved best route
outside of tunnel" messages. Those get logged every time we need to
rerun our re-implementation of Windows' weighting algorithm as to which
source interface / IP a packet should be sent from.

Currently, this gets cached in every socket instance so for the
peer-to-peer socket, this is only computed once per destination IP.
However, for DNS queries, we make a new socket for every query. Using a
new source port DNS queries is recommended to avoid fingerprinting of
DNS queries. Using a new socket also means that we need to re-run this
algorithm every time we make a DNS query which is why we see this log so
often.

To fix this, we need to share this cache across all UDP sockets. Cache
invalidation is one of the hardest problems in computer science and this
instance is no different. This cache needs to be reset every time we
roam as that changes the weighting of which source interface to use.

To achieve this, we extend the `SocketFactory` trait with a `reset`
method. This method is called whenever we roam and can then reset a
shared cache inside the `UdpSocketFactory`. The "source IP resolver"
function that is passed to the UDP socket now simply accesses this
shared cache and inserts a new entry when it needs to resolve the IP.

As an added benefit, this may speed up DNS queries on Windows a bit
(although I haven't benchmarked it). It should certainly drastically
reduce the amount of syscalls we make on Windows.
2025-07-24 01:36:53 +00:00

255 lines
8.1 KiB
TOML

[workspace]
members = [
"apple-client-ffi",
"bin-shared",
"client-ffi",
"client-shared",
"connlib/bufferpool",
"connlib/dns-over-tcp",
"connlib/dns-types",
"connlib/etherparse-ext",
"connlib/ip-packet",
"connlib/l3-tcp",
"connlib/l4-tcp-dns-server",
"connlib/l4-udp-dns-server",
"connlib/model",
"connlib/phoenix-channel",
"connlib/snownet",
"connlib/socket-factory",
"connlib/tun",
"connlib/tunnel",
"gateway",
"gui-client/src-admx-macro",
"gui-client/src-tauri",
"headless-client",
"logging",
"relay/ebpf-shared",
"relay/ebpf-turn-router",
"relay/server",
"telemetry",
"tests/gui-smoke-test",
"tests/http-test-server",
"tools/uniffi-bindgen",
]
resolver = "2"
[workspace.package]
license = "Apache-2.0"
edition = "2024"
[workspace.dependencies]
admx-macro = { path = "gui-client/src-admx-macro" }
anyhow = "1.0.98"
apple-client-ffi = { path = "apple-client-ffi" }
arboard = { version = "3.6.0", default-features = false }
async-trait = { version = "0.1", default-features = false }
atomicwrites = "0.4.4"
axum = { version = "0.8.4", default-features = false }
aya = { git = "https://github.com/aya-rs/aya" }
aya-build = { git = "https://github.com/aya-rs/aya" }
aya-ebpf = { git = "https://github.com/aya-rs/aya" }
aya-log = { git = "https://github.com/aya-rs/aya" }
aya-log-ebpf = { git = "https://github.com/aya-rs/aya" }
backoff = { version = "0.4", features = ["tokio"] }
base64 = { version = "0.22.1", default-features = false }
bimap = "0.6"
boringtun = { version = "0.6", default-features = false }
bufferpool = { path = "connlib/bufferpool" }
bytecodec = "0.5.0"
bytes = { version = "1.9.0", default-features = false }
caps = "0.5.5"
chrono = { version = "0.4", default-features = false, features = ["std", "clock", "oldtime", "serde"] }
clap = "4.5.41"
client-shared = { path = "client-shared" }
connlib-model = { path = "connlib/model" }
dashmap = "6.1.0"
derive_more = "2.0.1"
difference = "2.0.0"
dirs = "6.0.0"
divan = "0.1.21"
dns-lookup = "2.0"
dns-over-tcp = { path = "connlib/dns-over-tcp" }
dns-types = { path = "connlib/dns-types" }
ebpf-shared = { path = "relay/ebpf-shared" }
either = "1"
etherparse = { version = "0.17", default-features = false }
etherparse-ext = { path = "connlib/etherparse-ext" }
firezone-bin-shared = { path = "bin-shared" }
firezone-headless-client = { path = "headless-client" }
firezone-logging = { path = "logging" }
firezone-relay = { path = "relay/server" }
firezone-telemetry = { path = "telemetry" }
firezone-tunnel = { path = "connlib/tunnel" }
flume = { version = "0.11.1", features = ["async"] }
futures = { version = "0.3.31" }
futures-bounded = "0.2.1"
gat-lending-iterator = "0.1.6"
glob = "0.3.2"
hex = "0.4.3"
hex-display = "0.3.0"
hex-literal = "0.4.1"
humantime = "2.2"
ip-packet = { path = "connlib/ip-packet" }
ip_network = { version = "0.4", default-features = false }
ip_network_table = { version = "0.2", default-features = false }
itertools = "0.14"
jni = "0.21.1"
keyring = "3.6.2"
known-folders = "1.2.0"
l3-tcp = { path = "connlib/l3-tcp" }
l4-tcp-dns-server = { path = "connlib/l4-tcp-dns-server" }
l4-udp-dns-server = { path = "connlib/l4-udp-dns-server" }
libc = "0.2.174"
lockfree-object-pool = "0.1.6"
log = "0.4"
lru = "0.12.5"
mio = "1.0.4"
moka = "0.12.11"
native-dialog = "0.7.0"
netlink-packet-core = "0.7"
netlink-packet-route = "0.24"
network-types = "0.0.8"
nix = "0.30.1"
nu-ansi-term = "0.50"
num_cpus = "1.17.0"
once_cell = "1.21.3"
opentelemetry = "0.29.0"
opentelemetry-otlp = "0.29.0"
opentelemetry-stdout = "0.29.0"
opentelemetry_sdk = "0.29.0"
os_info = { version = "3", default-features = false }
output_vt100 = "0.1"
parking_lot = "0.12.4"
phoenix-channel = { path = "connlib/phoenix-channel" }
png = "0.17.16"
proc-macro2 = "1.0"
proptest = "1.7.0"
proptest-state-machine = "0.3.1"
quinn-udp = { version = "0.5.12", features = ["fast-apple-datapath"] }
quote = "1.0"
rand = "0.8.5"
rand_core = "0.6.4"
rangemap = "1.5.1"
reqwest = { version = "0.12.22", default-features = false }
resolv-conf = "0.7.3"
ringbuffer = "0.15.0"
roxmltree = "0.20"
rtnetlink = { version = "0.17.0", default-features = false, features = ["tokio_socket"] }
rustls = { version = "0.23.29", default-features = false, features = ["ring"] }
sadness-generator = "0.6.0"
sd-notify = "0.4.5" # This is a pure Rust re-implementation, so it isn't vulnerable to CVE-2024-3094
secrecy = "0.8"
semver = "1.0.26"
sentry = { version = "0.41.0", default-features = false }
sentry-tracing = "0.41.0"
serde = "1.0.219"
serde_json = "1.0.141"
serde_variant = "0.1.3"
sha2 = "0.10.9"
smallvec = "1.15.1"
smbios-lib = "0.9.2"
smoltcp = { version = "0.12", default-features = false }
snownet = { path = "connlib/snownet" }
socket-factory = { path = "connlib/socket-factory" }
socket2 = { version = "0.5" }
static_assertions = "1.1.0"
str0m = { version = "0.9.0", default-features = false, features = ["sha1"] }
strum = { version = "0.27.1", features = ["derive"] }
stun_codec = "0.4.0"
subprocess = "0.2.9"
subtle = "2.5.0"
supports-color = "3.0.2"
swift-bridge = "0.1.57"
swift-bridge-build = "0.1.57"
syn = "2.0"
tauri = "2.5.1"
tauri-build = "2.1.0"
tauri-plugin-dialog = "2.3.0"
tauri-plugin-notification = "2.3.0"
tauri-plugin-opener = "2.4.0"
tauri-plugin-shell = "2.3.0"
tauri-runtime = "2.5.0"
tauri-utils = "2.2.0"
tempfile = "3.20.0"
test-case = "3.3.1"
test-strategy = "0.4.3"
thiserror = "2.0.12"
time = "0.3.37"
tokio = "1.46"
tokio-stream = "0.1.17"
tokio-tungstenite = "0.27.0"
tokio-util = "0.7.15"
tracing = { version = "0.1.40" }
tracing-appender = "0.2.3"
tracing-core = "0.1.34"
tracing-journald = "0.3.1"
tracing-log = "0.2.0"
tracing-macros = { git = "https://github.com/tokio-rs/tracing", branch = "v0.1.x" } # Contains `dbg!` but for `tracing`.
tracing-opentelemetry = "0.30.0"
tracing-stackdriver = "0.11.0"
tracing-subscriber = { version = "0.3.19", features = ["parking_lot"] }
trackable = "1.3.0"
tun = { path = "connlib/tun" }
uniffi = "0.29.3"
url = "2.5.2"
uuid = "1.17.0"
which = "4.4.2"
windows = "0.61.3"
windows-core = "0.61.1"
windows-implement = "0.60.0"
windows-service = "0.8.0"
winreg = "0.52.0"
zbus = "5.9.0"
zip = { version = "2", default-features = false }
[workspace.lints.clippy]
dbg_macro = "warn"
print_stdout = "warn"
print_stderr = "warn"
unnecessary_wraps = "warn"
unused_async = "warn"
wildcard_enum_match_arm = "warn" # Ensures we match on all combinations of `Poll`, preventing erroneous suspensions.
redundant_else = "warn"
redundant_clone = "warn"
unwrap_in_result = "warn"
unwrap_used = "warn"
[workspace.lints.rustdoc]
private-intra-doc-links = "allow" # We don't publish any of our docs but want to catch dead links.
[patch.crates-io]
boringtun = { git = "https://github.com/firezone/boringtun", branch = "master" }
ip_network = { git = "https://github.com/JakubOnderka/ip_network", branch = "master" } # Waiting for release.
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.29" } # Waiting for release.
softbuffer = { git = "https://github.com/rust-windowing/softbuffer" } # Waiting for release.
str0m = { git = "https://github.com/algesten/str0m", branch = "main" }
moka = { git = "https://github.com/moka-rs/moka", branch = "main" } # Waiting for release.
quinn-udp = { git = "https://github.com/quinn-rs/quinn", branch = "main" } # Waiting for release.
# Enforce `tracing-macros` to have released `tracing` version.
[patch.'https://github.com/tokio-rs/tracing']
tracing = "0.1.41"
[profile.release]
# Full link-time optimization. Reduces binaries by up to 3x on some platforms.
lto = "fat"
# Increases the compiler's ability to produce smaller, optimized code
# at the expense of compilation time
codegen-units = 1
[profile.release.package.firezone-gui-client]
debug = "full"
split-debuginfo = "packed"
[profile.release.package.ebpf-turn-router]
debug = 2
# Override build settings just for the GUI client, so we get a pdb/dwp
# Cargo ignores profile settings if they're not in the workspace's Cargo.toml
[profile.dev.package.firezone-gui-client]
debug = "full"
split-debuginfo = "packed"