feat(mihomo): keep unproxiable ranges out of TUN, fix the startup DNS race (#419)

* feat(mihomo): keep ranges that can never be proxied out of TUN

The list lives in policy.yaml as tun_exclude_address; sources.yaml may override
it. 198.18.0.0/15 stays in TUN: that is the fake-ip range itself.

* feat(mihomo): match Valve's content servers by ASN

The 20 hand-copied prefixes had drifted from what AS32590 announces. The rule
type needs GeoLite2-ASN.mmdb, so geox-url.asn points at the same mirror.

* feat(mihomo): render the gateway config from the same sources

The hand-kept copy had drifted: a manual sync carried the desktop's secret onto
the gateway and dropped external-ui-url. --redact yields a shareable template.

* fix(mihomo): open the link DNS takeover only once the core serves it

The core opens :1053 after parsing rules, and rule parsing is where missing
geodata gets fetched. Flipping at fork time made that fetch SERVFAIL, the config
fatal, and the unit unstartable.

* fix(justfile): keep local endpoints out of the agent proxy

With only HTTP_PROXY set, a request to this host's own llama-swap endpoint went
to mihomo. Node matches exact hosts only, so the literals carry it; the CIDRs
serve curl and Go.

* feat(justfile): seed mihomo geodata into the service state dir

So a cold start never needs the download that the DNS takeover made unstartable.
This commit is contained in:
ryan4yin | 二花 authored and GitHub committed 2026-10-09 12:31:59 +08:00
1 parent fe302fa950
commit 63b7183381
7 files changed
+184 -51

No files matched your search

+40 -6
View File
@@ -276,12 +276,46 @@ k3s-test mode="switch":
[group('agents')]
dsh-web:
#!/usr/bin/env nu
# dsh's web fetch refuses a DNS answer it does not call public, and a fake-ip
# resolver answers with 198.18.0.0/15. A proxied hop lets mihomo resolve the
# origin instead, which skips that check and leaves fake-ip acceleration
# intact. The policy reaches every Node fetch the harness makes, so mihomo
# becomes a dependency for LLM, web search and HTTP MCP traffic too.
with-env { HTTPS_PROXY: "http://127.0.0.1:7897", HTTP_PROXY: "http://127.0.0.1:7897" } { ^dsh web --no-open }
# no_proxy keeps local endpoints out of the proxy; the proxy is here for fake-ip.
# dsh's web fetch refuses a DNS answer it does not call public and fake-ip answers
# with 198.18.0.0/15, so a proxied hop makes mihomo resolve the origin instead.
# That makes mihomo a dependency of every Node fetch the harness makes, so it has
# to stop at the LAN: without no_proxy this host's own llama-swap endpoint goes
# through it too. Node reads only lowercase `no_proxy` and matches exact hosts,
# not CIDR; curl and Go do honor CIDR.
with-env {
HTTPS_PROXY: "http://127.0.0.1:7897"
HTTP_PROXY: "http://127.0.0.1:7897"
no_proxy: "localhost,127.0.0.1,::1,[::1],192.168.5.100,192.168.5.178,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"
NO_PROXY: "localhost,127.0.0.1,::1,[::1],192.168.5.100,192.168.5.178,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"
} { ^dsh web --no-open }
# Seed mihomo's geodata into the service's state dir, so a cold start needs no DNS.
[linux]
[group('services')]
mihomo-geo:
#!/usr/bin/env nu
# Copy geodata in by hand, so a cold start never has to fetch it. The core
# fetches it while parsing rules, before its own DNS is up and while the link
# DNS points at it -- that fetch can only fail.
let src = ($env.HOME | path join .config mihomo)
let dst = "/var/lib/private/mihomo"
sudo mkdir -p $dst
mut seeded = []
for f in [GeoSite.dat geoip.metadb ASN.mmdb] {
let p = ($src | path join $f)
if ($p | path exists) {
sudo cp $p $dst
$seeded = ($seeded | append ($dst | path join $f))
} else {
print $"(!) ($f) is not in ($src) -- fetch it first: mihomo -t -d ($src) -f ($src)/config.yaml"
}
}
if ($seeded | is-not-empty) {
sudo chmod 644 ...$seeded
let names = ($seeded | path basename | str join ', ')
print $"seeded ($names) -- restart mihomo to pick them up"
}
# =================================================
#