Exit nodes on Windows: use a member as exit node via destination bypass routes
Choosing an exit node on Windows did nothing: the using side was refused, because Windows has no per-user routing and the agent's own traffic would loop into the tunnel it carries. Now the overlay interface gets 0.0.0.0/1 and 128.0.0.0/1 routes (and ::/1, 8000::/1 as an IPv6 blackhole), and every underlay address the agent talks to directly gets a /32 route through the physical default gateway, marked with route metric 7373 so stale ones are found and removed. Bypass routes are written before the halves and removed after them; a failed step removes what was written. All routes are in the active store. The addresses come from the runtime: each network runtime hands the interface the verified direct IPv4 paths of its control connections and the relay hosts in use (Interface::set_underlay, refreshed every dial round); relay names are resolved when the rules are applied. ExitHostRules::needs_bypass (true only on Windows) gates it, so Linux and macOS plans never carry or re-apply on path changes. ExitHostPlan gains `bypass` and `bypass_hosts`; networks leaving forget their entry. Limits: a path that appears after the last apply goes through the tunnel until the next apply; data-plane-only addresses are not collected separately (the data links ride the same iroh paths). Nothing was run on Windows. Checks: cargo fmt --check, cargo clippy --locked --workspace --all-targets -D warnings and cargo test --locked --workspace --all-targets passed on macOS; scripts and ordering are unit-tested with an injected runner and resolver, and Interface::set_underlay with the mock host. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
637915600e
commit
7c176e0b74
8 files changed
+659
-45
No files matched your search
+19
-12
@@ -82,18 +82,25 @@ is built from `pf` and `route`. The agent runs as root there.
|
||||
|
||||
## Windows
|
||||
|
||||
Offering only. Each offered range gets a WinNAT object
|
||||
`tsunagi-exit:<interface>:<range>` (`New-NetNat`), removed with the offer, the
|
||||
network and the agent. Forwarding is read for the overlay interface and never
|
||||
changed; Windows forwards per interface, so enable it on the ones involved
|
||||
(`Get-NetIPInterface | Set-NetIPInterface -Forwarding Enabled`, administrator
|
||||
PowerShell). Some Windows versions allow one NAT per host; a second range then
|
||||
reports its own failure.
|
||||
|
||||
Using one is **not available**: Windows has no per-user routing, so the agent's
|
||||
own traffic cannot be kept out of a default route through the overlay and would
|
||||
loop. `tsng exit-node <name>` reports that and installs nothing. This was
|
||||
written without a Windows host to run it on.
|
||||
- **Offering:** each offered range gets a WinNAT object
|
||||
`tsunagi-exit:<interface>:<range>` (`New-NetNat`), removed with the offer, the
|
||||
network and the agent. Forwarding is read for the overlay interface and never
|
||||
changed; Windows forwards per interface, so enable it on the ones involved
|
||||
(`Get-NetIPInterface | Set-NetIPInterface -Forwarding Enabled`, administrator
|
||||
PowerShell). Some Windows versions allow one NAT per host; a second range then
|
||||
reports its own failure.
|
||||
- **Using:** Windows has no per-user routing, so the agent's own traffic is kept
|
||||
off the tunnel *by destination*. `0.0.0.0/1` and `128.0.0.0/1` go through the
|
||||
overlay interface; a `/32` route with metric 7373 (the marker for "ours")
|
||||
through the physical default gateway is added for every address the agent
|
||||
talks to directly: verified direct paths of its connections, plus the relays
|
||||
it uses, resolved when the rules are applied. The set follows path changes. A
|
||||
path that appears after the last apply goes through the tunnel until the next
|
||||
one. IPv6 is blackholed with `::/1` and `8000::/1` on the overlay interface,
|
||||
so applications fall back to IPv4 after a delay rather than at once.
|
||||
Everything is in the active store: a reboot clears it.
|
||||
- Not verified on a live host when this was written. To inspect:
|
||||
`Get-NetRoute -PolicyStore ActiveStore | ? { $_.RouteMetric -eq 7373 -or $_.InterfaceAlias -like 'tsun*' }`.
|
||||
|
||||
## What it does not do
|
||||
|
||||
|
||||
Reference in new issue
Block a user