Skip to content

feat(proto): Discover NAT candidates from off-path PATH_CHALLENGEs#647

Draft
Frando wants to merge 1 commit into
mainfrom
Frando/feat-discover-off-path-probes
Draft

feat(proto): Discover NAT candidates from off-path PATH_CHALLENGEs#647
Frando wants to merge 1 commit into
mainfrom
Frando/feat-discover-off-path-probes

Conversation

@Frando
Copy link
Copy Markdown
Member

@Frando Frando commented May 12, 2026

Description

This is claude's attempt at fixing holepunching when the server is behind a hard NAT - not yet reviewed.
See n0-computer/iroh#4254 for the iroh PR using this to unignore two so-far failing patchbay NAT tests.

When the server is behind a symmetric NAT, its ADD_ADDRESS-advertised reflexive address is mapped only against the relay and is unreachable from the client. The server's own probes do reach the client when the client's NAT is permissive, but they come from a different, NAT-rebound source address. Until now we replied with PATH_RESPONSE and forgot that source, so no path was ever opened.

On the client side, treat the source of an incoming off-path PATH_CHALLENGE as a fresh probe target. The client probes back on the 4-tuple the server's NAT just opened, the response matches one of the client's own sent challenges, and the existing client-only path-opening flow opens the path.

Sequence ids for discovered addresses walk down from VarInt::MAX so they cannot collide with peer-advertised ADD_ADDRESS ids (which start at 0).

Breaking Changes

Notes & open questions

Change checklist

  • Self-review.
  • Documentation updates following the style guide, if relevant.
  • Tests if relevant.
  • All breaking changes documented.

When the server is behind a symmetric NAT, its ADD_ADDRESS-advertised
reflexive address is mapped only against the relay and is unreachable
from the client. The server's own probes do reach the client when the
client's NAT is permissive, but they come from a different,
NAT-rebound source address. Until now we replied with PATH_RESPONSE
and forgot that source, so no path was ever opened.

On the client side, treat the source of an incoming off-path
PATH_CHALLENGE as a fresh probe target. The client probes back on the
4-tuple the server's NAT just opened, the response matches one of the
client's own sent challenges, and the existing client-only
path-opening flow opens the path.

Sequence ids for discovered addresses walk down from VarInt::MAX so
they cannot collide with peer-advertised ADD_ADDRESS ids (which start
at 0).
@github-actions
Copy link
Copy Markdown

Documentation for this PR has been generated and is available at: https://n0-computer.github.io/noq/pr/647/docs/noq/

Last updated: 2026-05-12T09:31:01Z

@github-actions
Copy link
Copy Markdown

Performance Comparison Report

75496b54101f42bf1e4c0ccd5d87d50f7617482e - artifacts

Raw Benchmarks (localhost)

Scenario noq upstream Delta CPU (avg/max)
large-single 5631.1 Mbps 7985.4 Mbps -29.5% 96.0% / 101.0%
medium-concurrent 5504.5 Mbps 7970.0 Mbps -30.9% 94.5% / 101.0%
medium-single 3899.4 Mbps 4749.5 Mbps -17.9% 97.4% / 151.0%
small-concurrent 3804.0 Mbps 5344.1 Mbps -28.8% 99.4% / 152.0%
small-single 3511.1 Mbps 4754.8 Mbps -26.2% 91.0% / 101.0%

Netsim Benchmarks (network simulation)

Condition noq upstream Delta
ideal 3067.8 Mbps 4064.7 Mbps -24.5%
lan 782.4 Mbps 810.3 Mbps -3.4%
lossy 69.8 Mbps 69.9 Mbps ~0%
wan 83.8 Mbps 83.8 Mbps ~0%

Summary

noq is 26.5% slower on average

@n0bot n0bot Bot added this to iroh May 12, 2026
@github-project-automation github-project-automation Bot moved this to 🚑 Needs Triage in iroh May 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: 🚑 Needs Triage

Development

Successfully merging this pull request may close these issues.

1 participant