Skip to content

feat(gateway): translate TimeExceeded ICMP messages - #9812

Merged
thomaseizinger merged 17 commits into
mainfrom
contrib-icmp-ttl
Jul 12, 2025
Merged

thomaseizinger merged 17 commits into
mainfrom
contrib-icmp-ttl

Conversation

@thomaseizinger

@thomaseizinger thomaseizinger commented Jul 9, 2025 •

Copy link
Copy Markdown
Member

In the DNS resource NAT table, we track parts of the layer 4 protocol of the connection in order to map packets back to the correct proxy IP in case multiple DNS names resolve to the same real IP. The involvement of layer 4 means we need to perform some packet inspection in case we receive ICMP errors from an upstream router.

Presently, the only ICMP error we handle here is destination unreachable. Those are generated e.g. when we are trying to contact an IPv6 address but we don't have an IPv6 egress interface. An additional error that we want to handle here is "time exceeded":

Time exceeded is sent when the TTL of a packet reaches 0. Typically, TTLs are set high enough such that the packet makes it to its destination. When using tools such as tracepath however, the TTL is specifically only incremented one-by-one in order to resolve the exact hops a packet is taking to a destination. Without handling the time exceeded ICMP error, using tracepath through Firezone is broken because the packets get dropped at the DNS resource NAT.

With this PR, we generalise the functionality of detecting destination unreachable ICMP errors to also handle time-exceeded errors, allowing tools such as tracepath to somewhat work:

❯ sudo docker compose exec --env RUST_LOG=info -it client /bin/sh -c 'tracepath -b example.com'
 1?: [LOCALHOST]                      pmtu 1280
 1:  100.82.110.64 (100.82.110.64)                         0.795ms
 1:  100.82.110.64 (100.82.110.64)                         0.593ms
 2:  example.com (100.96.0.1)                              0.696ms asymm 45
 3:  example.com (100.96.0.1)                              5.788ms asymm 45
 4:  example.com (100.96.0.1)                              7.787ms asymm 45
 5:  example.com (100.96.0.1)                              8.412ms asymm 45
 6:  example.com (100.96.0.1)                              9.545ms asymm 45
 7:  example.com (100.96.0.1)                              7.312ms asymm 45
 8:  example.com (100.96.0.1)                              8.779ms asymm 45
 9:  example.com (100.96.0.1)                              9.455ms asymm 45
10:  example.com (100.96.0.1)                             14.410ms asymm 45
11:  example.com (100.96.0.1)                             24.244ms asymm 45
12:  example.com (100.96.0.1)                             31.286ms asymm 45
13:  no reply
14:  example.com (100.96.0.1)                            303.860ms asymm 45
15:  no reply
16:  example.com (100.96.0.1)                            135.616ms (This broken router returned corrupted payload) asymm 45
17:  no reply
18:  example.com (100.96.0.1)                            161.647ms asymm 45
19:  no reply
20:  no reply
21:  no reply
22:  example.com (100.96.0.1)                            238.066ms reached
     Resume: pmtu 1280 hops 22 back 45

We say "somewhat work" because due to the NAT that is in place for DNS resources, the output does not disclose the intermediary hops beyond the Gateway.

Co-authored-by: Antoine Labarussias antoinelabarussias@gmail.com

@vercel

vercel Bot commented Jul 9, 2025 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
firezone ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 12, 2025 8:44pm

@thomaseizinger thomaseizinger left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Intuinewin I've given this a review, I think it looks good so far. Thank you! Only a few minor things that need tweaking which should also fix CI. Would you mind opening a new PR against the contrib-icmp-ttl branch to address these?

Comment thread rust/connlib/ip-packet/src/lib.rs Outdated
Comment thread rust/connlib/tunnel/src/peer.rs Outdated
Comment thread rust/connlib/tunnel/src/tests/icmp_error_hosts.rs Outdated
Comment thread rust/connlib/tunnel/src/peer/nat_table.rs Outdated
Comment thread rust/connlib/ip-packet/src/icmp_error.rs Outdated
Comment thread rust/connlib/tunnel/src/peer/nat_table.rs Outdated
@thomaseizinger

Copy link
Copy Markdown
Member Author

Currently blocked by #9834.

@thomaseizinger

Copy link
Copy Markdown
Member Author

We say "somewhat work" because due to the NAT that is in place for DNS resources, the output does not disclose the intermediary hops beyond the Gateway.

@Intuinewin Does this match the behaviour in your testing? I guess it is better than not working at all but I do wonder whether there is a way we can make tracepath work to show the route beyond the Gateway.

@thomaseizinger
thomaseizinger added this pull request to the merge queue Jul 12, 2025
Merged via the queue into main with commit 66455ab Jul 12, 2025

This branch was successfully deployed

1 active deployment
Preview — ad1fcb6a Deployed Jul 12, 2025 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants