fix(windows): keep ::1 loopback and kubectl working while connected - #8
Closed
asgarihope wants to merge 3 commits into
Closed
asgarihope wants to merge 3 commits into
asgarihope wants to merge 3 commits into
Conversation
Three root causes broke localhost and kubectl on Windows while BiFlow was connected (ADR 0112): 1. Orphaned Mihomo held the controller port. spawn_mihomo uses kill_on_drop(false) so connectivity survives a helper crash, but when the helper restarts (reboot, reinstall, new session) self.child is empty and the previous Mihomo is an orphan still holding 127.0.0.1:19090 and the TUN adapter. The new Mihomo cannot bind, the desktop silently talks to the stale process, and new config is never applied. The helper now calls kill_orphaned_mihomo (taskkill /F /IM mihomo.exe on Windows, pkill -x mihomo on Linux) before every spawn to reclaim the port and adapter. 2. strict-route blocked ::1 loopback. Mihomo v1.19.29 does not apply tun.inet6-address to the Wintun adapter on Windows (GET /configs reports inet4-address but no inet6-address, adapter only gets link-local fe80::). With strict-route: true and no inet6 address, sing-tun installs an unconditional WFP block-ipv6 connect filter that only exempts Mihomo, so localhost to ::1 is refused while connected. Windows now generates strict-route: false; dns.ipv6: false already keeps AAAA out of fake-ip so the IPv6 leak surface is minimal. 3. Sniffer override-destination broke kubectl. With override-destination: true, when kubectl connected to a cluster API IP (78.109.203.123:443) with a tls-server-name SNI, the sniffer resolved the SNI through fake-ip DNS and overrode the destination to 198.18.x.x. Even a PROCESS-NAME,kubectl.exe,DIRECT rule then connected to the fake-ip and the TLS handshake failed with EOF. The sniffer now generates override-destination: false so the connection keeps its original destination IP; domain-based rules still use the sniffed SNI. Co-authored-by: Cursor <cursoragent@cursor.com>
Node 26 ships an experimental localStorage global that stays undefined unless --localstorage-file is passed, and jsdom 26 defers to it instead of providing its own, so window.localStorage is also absent under vitest. i18n/config.ts read the saved language at module-load time, so every frontend test failed with "Cannot read properties of undefined (reading getItem')". - Add a minimal in-memory Storage shim in its own setupFiles entry that runs before src/test/setup.ts (ES module imports are hoisted, so the shim must live in its own file listed first). - Guard the i18n read with typeof localStorage !== "undefined". - Keep the shim returning string | undefined (not false from &&) so the lng option stays typed string | undefined. - Set environmentOptions.jsdom.url in vite.config.ts so jsdom has a valid origin and order setupFiles with the shim first. Co-authored-by: Cursor <cursoragent@cursor.com>
Version sync from root version file via pnpm version:sync. Updates package.json, Cargo.toml, tauri.conf.json, and lockfiles. Co-authored-by: Cursor <cursoragent@cursor.com>
asgarihope
added a commit
to asgarihope/BiFlow
that referenced
this pull request
Oct 2, 2026
Combine PR devlifeX#8 (strict-route off, inet6-address, orphan Mihomo kill, sniffer override-destination, Node 26 localStorage shim) with the macOS port so one PR covers both platforms. Keep localhost fake-ip-filter and macOS TUN loopback exclusions. Co-authored-by: Cursor <cursoragent@cursor.com>
Contributor
Author
|
Closing in favor of a single combined PR. The Windows loopback/kubectl/orphan-Mihomo work from this branch is now merged into |
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.
Summary
Three root causes broke
localhostandkubectlon Windows while BiFlow was connected (ADR 0112).1. Orphaned Mihomo held the controller port (6.2.54)
spawn_mihomouseskill_on_drop(false)so connectivity survives a helper crash, but when the helper itself restarts (machine reboot, helper reinstall, or a new desktop session),self.childis empty and the previous Mihomo is an orphan still holding127.0.0.1:19090and the TUN adapter. The new Mihomo cannot bind, the desktop silently talks to the stale process, and new config is never applied.Fix: The helper now calls
kill_orphaned_mihomo(taskkill /F /IM mihomo.exeon Windows,pkill -x mihomoon Linux) before every spawn to reclaim the port and adapter.2.
strict-routeblocked::1loopback (6.2.55)Mihomo v1.19.29 does not apply
tun.inet6-addressto the Wintun adapter on Windows —GET /configsreportsinet4-addressbut noinet6-address, and the adapter only gets a link-localfe80::address. Withstrict-route: trueand no inet6 address, sing-tun installs an unconditional WFP "block ipv6" connect filter that only exempts Mihomo, solocalhost→::1is refused while connected.Fix: Windows now generates
strict-route: false.dns.ipv6: falsealready keeps AAAA out of fake-ip, so the IPv6 leak surface is minimal. Theinet6-addressand loopbackroute-exclude-addressare kept for when a Mihomo build that actually sets the inet6 address is available.3. Sniffer
override-destinationbroke kubectl (6.2.56)With
override-destination: true, when kubectl connected to a cluster API IP (78.109.203.123:443) with atls-server-nameSNI, the sniffer resolved the SNI through fake-ip DNS and overrode the destination to198.18.x.x. Even aPROCESS-NAME,kubectl.exe,DIRECTrule then connected to the fake-ip and the TLS handshake failed with EOF. The connection never appeared in the live connections list because the override happened before rule evaluation.Fix: The sniffer now generates
override-destination: falseso the connection keeps its original destination IP; domain-based rules still use the sniffed SNI.Bonus: localStorage shim for Node 26 / jsdom 26
Node 26 ships an experimental
localStorageglobal that staysundefinedunless--localstorage-fileis passed, and jsdom 26 defers to it instead of providing its own, sowindow.localStorageis also absent under vitest. Added a minimal in-memoryStorageshim in its ownsetupFilesentry that runs beforesrc/test/setup.ts, and guarded the i18n read withtypeof localStorage !== "undefined".Testing
cargo test -p iran-split-helper— 27 passed (includingkill_orphaned_mihomo_swallows_missing_process)cargo test -p iran-split-mihomo— 33 passed (includingwindows_disables_strict_route_to_keep_loopback_ipv6)cargo clippy -p iran-split-helper --all-targets -- -D warnings— cleancargo clippy -p iran-split-mihomo --all-targets -- -D warnings— cleancargo fmt --all --check— cleanpnpm check— 90 passedpnpm build— OKlocalhost:6379,::1:6379,kubectl get nodesall work while connected with the 6.2.56 build.