fix(bolt): replace WSL mirrored-networking with a host UDP forwarder#45
Merged
Merged
Conversation
Mirrored mode (networkingMode=mirrored + dnsTunneling/autoProxy/ hostAddressLoopback) causes recurring Hyper-V VmSwitch port-restore errors and intermittent Wsl/Service/E_UNEXPECTED catastrophic failures (vNIC flap / VM bounce) on Windows 11 24H2 and Insider builds, making the WSL2 dev path "incredibly unstable" for every contributor who followed the old doc. Replace it with a portable, hazard-free default: * scripts/wsl-bolt-udp-forward.ps1 — bidirectional userspace UDP relay on the Windows host (udp/7373 + udp/9), per-client ephemeral upstream with idle expiry, re-resolves the WSL NAT IP every 15s; -Install registers a logon scheduled task, optional -Firewall rules. netsh portproxy is TCP-only and cannot do this. * docs/developer/wsl-mirrored-networking.adoc — rewritten: NAT + forwarder is now the recommended path; bridged documented as the wired alternative; mirrored demoted to fallback-of-last-resort with an explicit 24H2/Insider instability warning. Filename kept (5 inbound refs incl. machine-readable state). * README.adoc / router-port-forward.adoc / bolt-ddns.adoc / CLAUDE.md — reference captions updated so they no longer assert mirrored mode. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Rename the local in Resolve-WslIp to $wslArgs so it no longer shadows PowerShell's automatic $args variable. Cosmetic; no behaviour change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* docs/decisions/0005-wsl-bolt-inbound-udp-no-mirrored.adoc — ADR for dropping mirrored networking in favour of the host UDP forwarder; records the proven-stun rejection rationale and the ADR-0004 link. * docs/decisions/README.adoc — was a 17-byte stub; now the actual ADR index/decision log (0001-0005 with status). * CHANGELOG.md — [Unreleased] Added/Changed entries for the forwarder and the rewritten WSL doc. * .machine_readable/6a2/STATE.a2ml — corrected the now-false "mirrored-networking prereq" claim and appended a 2026-05-19 entry so machine state matches reality. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Install-Task generated `powershell -File … -Run -Ports 7373,9`. Under -File, `7373,9` is passed as the literal string "7373,9", which cannot bind to [int[]]$Ports, so the task aborted before binding any socket (Task Scheduler LastTaskResult=1; nothing on udp/7373). Manual runs worked only because they used the default ports with no -Ports arg. Switch the generated action to `-Command "& '<self>' -Run -Ports 7373,9"` so PowerShell parses the array argument correctly. Found by validating the installed scheduled task end-to-end on Windows 11 (not just the ad-hoc -Run instance). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
🔍 Hypatia Security ScanFindings: 21 issues detected
View findings[
{
"reason": "Issue in quality.yml",
"type": "missing_workflow",
"file": "quality.yml",
"action": "create",
"rule_module": "workflow_audit",
"severity": "high"
},
{
"reason": "Issue in security-policy.yml",
"type": "missing_workflow",
"file": "security-policy.yml",
"action": "create",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Action ocaml/setup-ocaml@v3 needs attention",
"type": "unpinned_action",
"file": "affinescript-canary.yml",
"action": "pin_sha",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Action hyperpolymath/standards/.github/workflows/governance-reusable.yml@main needs attention",
"type": "unpinned_action",
"file": "governance.yml",
"action": "pin_sha",
"rule_module": "workflow_audit",
"severity": "high"
},
{
"reason": "No permissions declaration -- add permissions: read-all",
"type": "missing_permissions",
"file": "elixir-ci.yml",
"action": "add_permissions",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "binary_to_term without :safe option -- deserialization attack (1 occurrences, CWE-502)",
"type": "elixir_send_unsanitised",
"file": "/home/runner/work/burble/burble/server/lib/burble/media/lmdb_playout.ex",
"action": "flag",
"rule_module": "code_safety",
"severity": "high"
},
{
"reason": "SSL verify_none disables certificate validation -- MITM risk (1 occurrences, CWE-295)",
"type": "elixir_no_ssl_verify",
"file": "/home/runner/work/burble/burble/server/lib/burble/bridges/mumble.ex",
"action": "flag",
"rule_module": "code_safety",
"severity": "high"
},
{
"reason": "believe_me undermines formal verification (2 occurrences, CWE-704)",
"type": "believe_me",
"file": "/home/runner/work/burble/burble/src/interface/abi/Foreign.idr",
"action": "flag",
"rule_module": "code_safety",
"severity": "critical"
},
{
"reason": "Nickel file missing SPDX-License-Identifier header (1 occurrences, CWE-1104)",
"type": "ncl_missing_spdx",
"file": "/home/runner/work/burble/burble/configs/config.ncl",
"action": "flag",
"rule_module": "code_safety",
"severity": "medium"
},
{
"reason": "Lock.unwrap() without poison handling (14 occurrences, CWE-754)",
"type": "lock_unwrap",
"file": "/home/runner/work/burble/burble/tools/selur-compose/crates/selur-compose-driver/src/mock.rs",
"action": "flag",
"rule_module": "code_safety",
"severity": "high"
}
]Powered by Hypatia Neurosymbolic CI/CD Intelligence |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The WSL2 dev path for the Bolt server was incredibly unstable. Mirrored
mode (
networkingMode=mirrored+dnsTunneling/autoProxy/hostAddressLoopback), whichdocs/developer/wsl-mirrored-networking.adocinstructed every contributor to enable, causes recurring Hyper-V
VmSwitch
Failed to restore configuration for port … Object Name not founderrors and intermittentWsl/Service/E_UNEXPECTEDcatastrophicfailures (vNIC flap / VM bounce) on Windows 11 24H2 and Insider builds.
What (3 commits)
scripts/wsl-bolt-udp-forward.ps1(new) — bidirectional userspaceUDP relay on the Windows host for udp/7373 + udp/9, per-client
ephemeral upstream with idle expiry (QUIC/ack returns work, not just
fire-and-forget cold pokes), re-resolves the WSL NAT IP every 15s.
-Installregisters a logon scheduled task; optional-Firewall.netsh portproxyis TCP-only and cannot do this.docs/developer/wsl-mirrored-networking.adoc— rewritten: NAT +forwarder recommended; bridged = wired alternative; mirrored demoted
to last-resort with a 24H2/Insider warning. Filename kept (5 inbound
refs incl. machine-readable state).
docs/decisions/0005-wsl-bolt-inbound-udp-no-mirrored.adoc(new)— ADR; also turns the stub
docs/decisions/README.adocinto a realADR index/decision log.
CHANGELOG.md,.machine_readable/6a2/STATE.a2ml,CLAUDE.md,README.adoc,router-port-forward.adoc,bolt-ddns.adoc— syncedso human + machine docs no longer assert mirrored mode.
Verification
Script statically parse-checked (0 errors). End-to-end check is an
operator step: revert
~/.wslconfigto plain NAT,wsl --shutdown,just server, then a test datagram to<host-lan-ip>:7373(orscripts/check-bolt-reachability.sh). Tracked outside this PR.Considered and rejected
proven-stunNAT traversal — cold bolts target peers not in asession, so hole-punching is structurally impossible (recorded in
ADR-0005).
proven-framehardening ofBurble.Bolt.Packet— separate, lowpriority.
🤖 Generated with Claude Code