Repository navigation
feat: macOS support plus Windows localhost/kubectl fixes (6.2.57) - #10
Merged
Merged
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>
…mihomo support - New crate iran-split-platform-macos implementing PlatformBackend with macOS paths, Hiddify/Happ .app bundle discovery, system_proxy via networksetup, TUN detection via GET /configs (ADR 0104 mirror) - New helper module macos.rs: launchd daemon, socket permissions, apply_system_dns/restore_system_dns (networksetup → 127.0.0.1), using absolute /usr/sbin/networksetup path for launchd's minimal PATH - Config: normalize TUN name to utun9 and DNS port to 53 on macOS (kernel rejects non-utun names; LAN router DNS bypasses TUN) - Mihomo: add Platform::Macos, routing-mark Linux-only, process bypass - Clients: add DriverPlatform::Macos variant - Core: add helper_version to RuntimeHealth/StackSnapshot for auto-reinstall on version mismatch; populate on all backends + CLI - Helper: start() calls apply_system_dns, cleanup() calls restore_system_dns (cfg macOS); spawn_local_proxy uses open for .app bundles; reject Linux ELF binaries in resolve_macos_binary; double start timeout Co-authored-by: Cursor <cursoragent@cursor.com>
…ironment - helper_install: install_macos stages helper+mihomo+plist via osascript admin prompt, computes real mihomo_sha256 (not empty), writes tun_name into helper.toml - lib.rs: prepare_stack_start version-mismatch check auto-reinstalls stale helper on Connect; macOS NativeBackend + paths wiring - diagnostics: macOS gate for environment snapshot trigger - deps: macOS dependency discovery (Hiddify/Happ .app bundles) - github_update: macOS update flow (DMG/AppImage path) - hiddify_reset: macOS Fresh Hiddify start (kill by Mach-O image match) - environment/mod.rs: macOS collector gate - tauri.macos.conf.json: .app/.dmg bundle config, icon.icns - tauri.conf.json: macOS bundle resources Co-authored-by: Cursor <cursoragent@cursor.com>
- build.sh: ci-macos target, macOS packaging stages (compile/dmg/collect), prefetch, xwin alignment - scripts/build-plan.mjs: macOS bundle config - scripts/check-bundled-assets.mjs: macOS asset verification - scripts/stage-helper.sh: macOS helper staging (no cross-compile needed) - resources/external-assets.toml: macOS mihomo asset entry - Cargo.toml/Cargo.lock: iran-split-platform-macos workspace member - vendor/mihomo/darwin/mihomo: macOS arm64 mihomo binary Co-authored-by: Cursor <cursoragent@cursor.com>
…ent lessons - presets.ts: macOS download URLs for Hiddify, OpenVPN, Happ, v2rayN, Windscribe - AGENTS.md: append macOS lessons — utun naming, .app launch via open, mihomo_sha256 fix, networksetup absolute path for launchd PATH, DNS system resolver redirect, Mach-O binary validation, start timeout - version: 6.2.52 → 6.2.54 (pnpm version:sync) Co-authored-by: Cursor <cursoragent@cursor.com>
Skip fake-ip for localhost, exclude loopback from the TUN, and actually turn Hiddify's system proxy off so browsers stop getting 502 on local dev servers. Also make the DMG fallback survive leftover hdiutil files. Co-authored-by: Cursor <cursoragent@cursor.com>
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>
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
One PR for both platforms. Replaces #8 (closed) and supersedes the earlier macOS-only #9.
.app/.dmg).localhost/::1andkubectlworking while connected.Windows (#8)
inet6-addresson Wintun, sostrict-route: trueinstalled a WFP “block ipv6” filter andlocalhost→::1failed. Windows now usesstrict-route: false, emitstun.inet6-address: fdfe:dcba:9876::1/126, and keepsdns.ipv6: false(ADR 0112).kill_orphaned_mihomobefore every spawn so a leftover Mihomo cannot hold:19090/ the TUN.override-destination: falseso kubectl to a real cluster IP is not rewritten to a fake-ip from TLS SNI.localStorageshim so frontend tests load.macOS
iran-split-platform-macos, helpermacos.rs(launchd +/usr/sbin/networksetupDNS).tun_name→utun9,dns_port→53.localhost/+.localhostinfake-ip-filter;route-exclude-addressfor127.0.0.0/8and::1/128on Windows and macOS.localhost)../build.sh macosDMG fallback deletes leftoverrw.*.dmgand runs fromtarget/release/bundle/dmg.Testing
cargo test/clippyforiran-split-mihomoandiran-split-helperpnpm check(198 UI tests + 90 script tests)BiFlow_6.2.55_aarch64.dmgon Apple Silicon; version is now 6.2.57 after the mergeCross-platform
Linux TUN routing unchanged (no loopback
route-exclude).helper_versionis#[serde(default)]. Windows-only and macOS-only paths staycfg-gated.