5 Commits

Author SHA1 Message Date
Thomas Eizinger
3226d434c2 chore(connlib): clarify Protocol::Icmp as IcmpEcho (#10988)
Firezone's DNS resource NAT can only route certain ICMP packets. In
particular, we can only route ICMP _echo_ packets as only those have a
stable identifier that we can use in our NAT table.

To clarify that, rename the enum variant to `IcmpEcho` from `Icmp`.
2025-11-27 04:25:51 +00:00
Thomas Eizinger
e490de7729 fix(gateway): don't route outbound ICMP errors (#10989)
ICMP errors like "Destination unreachable" can be sent by both ends of a
network connection. For DNS resources, handling these packets requires
special care as we also need to translate the failed packet embedded
within these ICMP messages such that the recipient can correctly relate
them to the network socket that has sent the original packet.

We do this for inbound ICMP errors already to alert the Client of e.g.
unreachable paths such as unreachable IPv6 networks. Outbound ICMP
errors, that is, ICMP errors generated by the Client for a packet sent
by a resource are currently not handled and result in warnings such as:

> Failed to translate outbound packet: Unsupported ICMPv4 type:
DestinationUnreachable(Port)

Whilst it is possible to correctly handle and translate these packets,
doing so requires a fair amount of work and changes to a very critical
part of the Gateway. As such, we simply drop these packets for now as
"unroutable packets" which downgrades their log level to DEBUG.

Resolves: #10983
2025-11-27 04:19:54 +00:00
Thomas Eizinger
e1c13d448a fix(connlib): retry sending packet on ENOBUFS (#10965)
In #9798, we added a check to map `ENOBUFS` to `WOUDLBLOCK` on MacOS.
More experimentation on that front revealed that this was actually
incorrect and the UDP sending task will hang as the OS does **not**
notify us once there are new buffers available.

This may explain some random connection hangs that some users have
recently complained about. I've already disabled the feature flag in
production, this PR therefore only removes code that is now inactive.

In order to make this as robust as possible, we implement a retry loop
with an exponential backoff, starting a 2ns. At most, we will be
retrying such a packet for 16ms. Local experiments on my Macbook have
shown that most of the time, new buffer space is available within 1ms.
The exponential backoff ensures we retry very quickly on faster machines
but still successfully send the packet on slower machines.

According to the linked mailing list, the link-speed of the attached
network has nothing to do with this which makes sense. UDP has no
congestion control so sending packets is merely a function of how fast
the CPU can process them.

Related:
https://lists.freebsd.org/pipermail/freebsd-hackers/2004-January/005369.html

---------

Signed-off-by: Thomas Eizinger <thomas@eizinger.io>
Co-authored-by: Jamil <jamilbk@users.noreply.github.com>
2025-11-26 04:36:36 +00:00
Thomas Eizinger
cbe07caaea fix(gateway): always map all proxy IPs (#10972)
In a recent refactor, we appear to have broken DNS resources that are
IPv6 only. This was caused by a change in how we iterate over the proxy
IP mappings. By bailing out as soon as we "run out" of IP mappings, we
actually never get to the IPv6 mappings.

This PR fixes this behaviour and adds a regression test to ensure we
always insert an entry for all proxy IPs.
2025-11-26 03:30:18 +00:00
Thomas Eizinger
b7dc897eea refactor(rust): introduce libs/ directory (#10964)
The current Rust workspace isn't as consistent as it could be. To make
navigation a bit easier, we move a few crates around. Generally, we
follow the idea that entry-points should be at the top-level. `rust/`
now looks like this (directories only):

```
.
├── cli             # Firezone CLI
├── client-ffi      # Entry point for Apple & Android
├── gateway         # Gateway
├── gui-client      # GUI client
├── headless-client # Headless client
├── libs            # Library crates
├── relay           # Relay
├── target          # Compile artifacts
├── tests           # Crates for testing
└── tools           # Local tools
```

To further enforce this structure, we also drop the `firezone-` prefix
from all crates that are not top-level binary crates.
2025-11-25 10:59:11 +00:00