mirror of
https://github.com/ryan4yin/nix-config.git
synced 2026-11-13 12:13:36 +01:00
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:
1 parent
fe302fa950
commit
63b7183381
7 files changed
+184
-51
No files matched your search
@@ -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"
|
||||
}
|
||||
|
||||
# =================================================
|
||||
#
|
||||
|
||||
+26
-10
@@ -138,17 +138,33 @@ in
|
||||
linkConfig.RequiredForOnline = "routable";
|
||||
};
|
||||
|
||||
# Dynamic DNS takeover: sing-tun normally asks resolved to use the TUN DNS
|
||||
# address through resolvectl. That built-in call is not usable from nixpkgs'
|
||||
# DynamicUser+hardened unit: the D-Bus socket is blocked, and resolve1's
|
||||
# SetLinkDNS/SetLinkDomains methods require privileged authorization. Without
|
||||
# it, resolved's upstream queries bypass dns-hijack and leave via the NIC.
|
||||
# Run the takeover as a privileged lifecycle hook instead. ExecStopPost also
|
||||
# runs on crashes, so a dead mihomo leaves the network usable.
|
||||
# The '+' prefix escapes the unit's sandbox; without it, resolvectl's D-Bus
|
||||
# connect fails and a failed ExecStartPost kills the otherwise healthy service.
|
||||
# Point this link's DNS at mihomo while it runs, and revert it when it stops.
|
||||
#
|
||||
# Why a lifecycle hook: mihomo's sing-tun stack would call resolvectl itself,
|
||||
# but nixpkgs' DynamicUser+hardened unit closes the D-Bus socket and SetLinkDNS
|
||||
# needs privileged authorization; without the takeover resolved's upstream
|
||||
# queries bypass dns-hijack and leave via the NIC. The '+' prefix escapes that
|
||||
# sandbox -- a failed ExecStartPost would kill a healthy service -- and
|
||||
# ExecStopPost also runs on crashes, so a dead mihomo leaves the network usable.
|
||||
#
|
||||
# Why the probe: the core opens :1053 only after parsing the rules, and rule
|
||||
# parsing is where missing geodata gets fetched. Flipping at fork time pointed
|
||||
# that fetch at a port nobody was listening on -- SERVFAIL, a fatal config
|
||||
# error, a unit that could never start.
|
||||
systemd.services.mihomo.serviceConfig = {
|
||||
ExecStartPost = lib.mkDefault "+${pkgs.systemd}/bin/resolvectl dns ${iface} 127.0.0.1:1053";
|
||||
ExecStartPost = lib.mkDefault "+${pkgs.writeShellScript "mihomo-dns-takeover" ''
|
||||
probe() { (exec 3<>/dev/tcp/127.0.0.1/1053) 2>/dev/null; }
|
||||
up=0
|
||||
for ((i = 0; i < 100; i++)); do
|
||||
if probe; then up=1; break; fi
|
||||
sleep 0.1
|
||||
done
|
||||
if [ "$up" = 0 ]; then
|
||||
echo "mihomo never opened 127.0.0.1:1053; leaving ${iface} on its own DNS" >&2
|
||||
exit 0
|
||||
fi
|
||||
exec ${pkgs.systemd}/bin/resolvectl dns ${iface} 127.0.0.1:1053
|
||||
''}";
|
||||
ExecStopPost = lib.mkDefault "+${pkgs.systemd}/bin/resolvectl revert ${iface}";
|
||||
};
|
||||
|
||||
|
||||
@@ -24,10 +24,15 @@ config before enabling the module, or the service will not start.
|
||||
| `default.nix` | the service: `services.mihomo` + TUN + `metacubexd` |
|
||||
| `policy.yaml` | portable routing policy: ads, CN services, local ranges, tail |
|
||||
| `generate.nu` | renders `config.yaml` from `sources.yaml` + `policy.yaml` |
|
||||
| `gateway-config.nu` | the same output plus the gateway deltas |
|
||||
| `sources.example.yaml` | schema for `sources.yaml` |
|
||||
|
||||
Rule order: `private_domains`, your `rules`, imported rules, then `policy.yaml`, ending in `MATCH`.
|
||||
|
||||
The gateway (`suzi`, not a host in this flake) runs the same config with a fixed set of deltas --
|
||||
`gateway-config.nu` renders it, `--redact` for a shareable template. Its output carries the
|
||||
subscriptions, so never commit it; the secret is filled in on the box, not here.
|
||||
|
||||
## Why generate
|
||||
|
||||
`proxy-provider` imports proxies only — a subscription's rules and groups are dropped by the core.
|
||||
@@ -45,12 +50,15 @@ targets instead of writing a config the core rejects.
|
||||
media still stalls: `tun_exclude_process: [wechat, WeChatAppEx, qq]` (Linux names; the fix that
|
||||
won clash-verge-rev#1762).
|
||||
- `find-process-mode: off` unless `PROCESS-*` rules or `tun_exclude_process` need it.
|
||||
- `tun_exclude_address`: a destination that can never be a proxy target should not pay a fake-ip
|
||||
round trip -- RFC1918, RFC 6598's `100.64.0.0/10` (where Tailscale addresses come from),
|
||||
link-local, multicast, reserved and documentation prefixes, `fc00::/7`, `fe80::/10`. Never exclude
|
||||
`198.18.0.0/15`, the fake-ip range itself; `tun_exclude_address: []` puts everything back in TUN.
|
||||
- Steam's download caches follow the public IP Steam sees on the login (CM) connection, so a proxied
|
||||
Steam downloads from Tokyo/Singapore/HK/Los Angeles. `policy.yaml` pins the CM hosts,
|
||||
`steamcontent.com` and Valve's AS32590 ranges DIRECT and keeps `steamcommunity.com` on the proxy;
|
||||
the IP rules are not decoration, Steam dials cached CM addresses without a lookup. Not
|
||||
`GEOSITE,steam` -- that category includes the community. Sources and how to verify: "Steam
|
||||
download region" below.
|
||||
`steamcontent.com` and `IP-ASN,32590` DIRECT and keeps `steamcommunity.com` on the proxy -- Steam
|
||||
dials cached CM addresses without a lookup, so that rule is not decoration. Not `GEOSITE,steam`:
|
||||
that category includes the community. Sources and how to verify: "Steam download region" below.
|
||||
- CDN selection depends on launcher probes, not the patch download route. On this host,
|
||||
`launcher-webstatic.hoyoverse.com` went through a US proxy node while `autopatchcn.bhsr.com` was
|
||||
DIRECT; the download rose from ~0.5 to 102 MB/s after the proxy group was switched to DIRECT.
|
||||
@@ -76,19 +84,15 @@ foreign download caches. Nothing in the Steam client overrides that. What the St
|
||||
| Source | Establishes | Trust |
|
||||
| --------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------- |
|
||||
| [Valve's content-server directory API](https://api.steampowered.com/IContentServerDirectoryService/GetServersForSteamPipe/v1/?cell_id=0&max_servers=2000) | the list is keyed by `cell_id`; `cell_id=0` means "use geolocation". Ask for any cell with `?cell_id=<n>&max_servers=2000` | Valve, live, authoritative |
|
||||
| [xPaw's Web API reference](https://steamapi.xpaw.me/IContentServerDirectoryService) | the endpoint and its parameters | community, mirrors the shipped client |
|
||||
| [steam-lancache-prefill: CDN Regions](https://tpill90.github.io/steam-lancache-prefill/en/steam-docs/CDN-Regions/) | the `CellId` to city table, and that since 2024-10-04 the Download Region override selects no CDN at all | community; the page calls itself "non-exhaustive and likely inaccurate", so trust the API over the table |
|
||||
| `~/.local/share/Steam/logs/content_log.txt` | what this host actually got: 2024 (CellID 201) came from mainland CDN partners, 2025-2026 (CellID 171/177) from the `tyo3`/`sgp1`/`hkg1`/`lax1` Valve caches | your own client, the strongest evidence here |
|
||||
| [羽翼城 / Dogfight360](https://www.dogfight360.com/blog/knowledge-base/fix_steamdl_region/) | the trick itself: pin `*.cm.steampowered.com`, `*.steamserver.net` and Valve's ranges direct; 2022 article, still maintained (2026-05) | the origin every other recipe copies; single-operator, but the mechanism checks out against the API and the local log |
|
||||
| [femoon](https://femoon.top/blog/steam-slow-download-clash-split-routing), [teapotium](https://teapotium.com/2024/12/let-steam-downloads-bypass-proxy/) | the same rules for Clash/mihomo, and the CM-IP-cached-without-DNS detail | derivative reports; the IP list in both is stale, regenerate it |
|
||||
| [RIPE stat: AS32590 announced prefixes](https://stat.ripe.net/data/announced-prefixes/data.json?resource=AS32590) | which ranges Valve actually owns today | registry data; regenerate the IP rules from it, never hand-copy a blog's list |
|
||||
| [femoon](https://femoon.top/blog/steam-slow-download-clash-split-routing), [teapotium](https://teapotium.com/2024/12/let-steam-downloads-bypass-proxy/) | the same rules for Clash/mihomo, and the CM-IP-cached-without-DNS detail | derivative reports; their prefix lists are stale, which is why the config matches on the ASN |
|
||||
| [RIPE stat: AS32590 announced prefixes](https://stat.ripe.net/data/announced-prefixes/data.json?resource=AS32590) | which ranges Valve actually owns today | registry data; cross-checks what the ASN match covers |
|
||||
| [meta-rules-dat](https://github.com/MetaCubeX/meta-rules-dat) | geosite category names: `steam` and `category-games` exist, `category-games@cn` (in several guides) does not | upstream data, checked against `GeoSite.dat` (2026-10) |
|
||||
| [Steam support: slow downloads and content servers](https://help.steampowered.com/en/faqs/view/5AC5-8056-E88F-F3FF) | Valve's own troubleshooting page | canonical, but JS-rendered, so nothing scrapes it |
|
||||
| [Steam forum: honour the download region setting](https://steamcommunity.com/discussions/forum/10/6741412150961222653/) | users have failed to pin a region for years | Valve forum, anecdotal |
|
||||
| [PAM 2024 measurement of Steam's CDN (PDF)](https://www.iijlab.net/en/members/romain/pdf/chris_pam2024.pdf) | how Steam picks caches, measured | peer-reviewed background; no rule here depends on it |
|
||||
|
||||
Two things that look like levers and are not: the Download Region dropdown, and
|
||||
`CellIDServerOverride` in `config.vdf` -- this host has it pinned to 35 (Singapore) while the log
|
||||
Two things that look like levers and are not: the Download Region dropdown -- since 2024-10-04 it
|
||||
[selects no CDN at all](https://tpill90.github.io/steam-lancache-prefill/en/steam-docs/CDN-Regions/)
|
||||
-- and `CellIDServerOverride` in `config.vdf`, pinned to 35 (Singapore) on this host while the log
|
||||
shows downloads arriving from Tokyo. The IP Steam sees is the only lever.
|
||||
|
||||
Check the result with `steam://open/console` then `user_info` (`IPCountry` must read `CN`), and by
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env nu
|
||||
# Render the gateway config (suzi, /etc/mihomo/config.yaml) from the same sources
|
||||
# as the desktop config: generate.nu's output plus the keys a gateway needs. The
|
||||
# gateway is not a host in this flake, so this script is the only place its shape
|
||||
# lives. Never commit the output -- it carries the subscriptions and the private
|
||||
# domains. `secret` stays a placeholder; the deploy fills it in on the box.
|
||||
#
|
||||
# nu gateway-config.nu [-o gateway.yaml] [--address 192.168.5.178] [--redact]
|
||||
# scp gateway.yaml root@<gateway>:/tmp/ # fill the secret in on the box, -t, restart
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
const UI_URL = "https://github.com/MetaCubeX/metacubexd/archive/refs/heads/gh-pages.zip"
|
||||
|
||||
def main [
|
||||
--out (-o): path = "/tmp/gateway.yaml"
|
||||
--sources (-s): path = "~/.config/mihomo/sources.yaml"
|
||||
--policy (-p): path
|
||||
--address (-a): string = "192.168.5.178"
|
||||
--redact # replace the secret and the subscription URLs: what a shareable template needs
|
||||
] {
|
||||
let out = ($out | path expand)
|
||||
let tmp = ($out + ".base")
|
||||
|
||||
let gen = ($env.FILE_PWD | path join "generate.nu")
|
||||
let args = if $policy == null {
|
||||
["-s", ($sources | path expand), "-o", $tmp]
|
||||
} else {
|
||||
["-s", ($sources | path expand), "-p", ($policy | path expand), "-o", $tmp]
|
||||
}
|
||||
nu $gen ...$args
|
||||
|
||||
let gw = (open --raw $tmp
|
||||
| from yaml
|
||||
| update ipv6 true
|
||||
| update allow-lan true
|
||||
| update external-controller $"($address):9090"
|
||||
| insert tproxy-port 7893
|
||||
| insert external-ui "ui"
|
||||
| insert external-ui-url $UI_URL
|
||||
| update secret "GATEWAY-SECRET-PLACEHOLDER"
|
||||
| update tun.stack "mixed"
|
||||
| update tun.strict-route false
|
||||
| insert tun.route-address ["0.0.0.0/1", "128.0.0.0/1", "::/1", "8000::/1"]
|
||||
| update dns.listen ":1053"
|
||||
| update dns.ipv6 true)
|
||||
|
||||
let gw = (if $redact {
|
||||
# a file-backed provider (localyaml) has no url to hide
|
||||
let pp = ($gw.proxy-providers
|
||||
| items {|k, v| {
|
||||
name: $k,
|
||||
conf: (if ($v | columns | any {|c| $c == "url" }) {
|
||||
$v | update url "https://xx.xx.xx.xx"
|
||||
} else {
|
||||
$v
|
||||
})
|
||||
} })
|
||||
$gw
|
||||
| update secret "NOTE-PLEASE-CHANGE-ME"
|
||||
| update proxy-providers ($pp | reduce -f {} {|it, acc| $acc | insert $it.name $it.conf })
|
||||
} else {
|
||||
$gw
|
||||
})
|
||||
|
||||
$gw | to yaml | save -f $out
|
||||
rm $tmp
|
||||
print $"gateway config -> ($out)"
|
||||
}
|
||||
@@ -366,6 +366,8 @@ def main [
|
||||
let policy_rules = (sanitize-rules ($policy_doc | get -o rules | default []) "policy.yaml" true)
|
||||
let policy_rp = ($policy_doc | get -o rule_providers | default {})
|
||||
let node_groups = ($policy_doc | get -o node_groups | default [])
|
||||
# kept out of TUN; sources.yaml may override the whole list
|
||||
let policy_exclude = ($policy_doc | get -o tun_exclude_address | default [])
|
||||
|
||||
let spec = (open $src)
|
||||
# an empty secret leaves the dashboard open to anything on the machine
|
||||
@@ -520,6 +522,7 @@ def main [
|
||||
"strict-route": ($spec | get -o tun_strict_route | default true)
|
||||
"auto-detect-interface": true
|
||||
"dns-hijack": ["any:53"]
|
||||
"route-exclude-address": ($spec | get -o tun_exclude_address | default $policy_exclude)
|
||||
} | upsert 'exclude-process' $excluded)
|
||||
)
|
||||
dns: {
|
||||
@@ -550,6 +553,8 @@ def main [
|
||||
geoip: "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/geoip.dat"
|
||||
geosite: "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/geosite.dat"
|
||||
mmdb: "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/country.mmdb"
|
||||
# backs the IP-ASN rules in policy.yaml
|
||||
asn: "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/GeoLite2-ASN.mmdb"
|
||||
}
|
||||
"proxy-providers": $providers_map
|
||||
"proxy-groups": $groups
|
||||
|
||||
@@ -47,6 +47,27 @@ dns_filters:
|
||||
- +.market.xiaomi.com
|
||||
- "*.tailscale.com"
|
||||
|
||||
# CIDRs kept out of TUN: a destination that can never be proxied should not pay
|
||||
# the fake-ip round trip. Never add `198.18.0.0/15` -- that is the fake-ip range.
|
||||
# Override per machine with `tun_exclude_address:` in sources.yaml.
|
||||
tun_exclude_address:
|
||||
- 0.0.0.0/8 # this network on this host
|
||||
- 10.0.0.0/8
|
||||
- 100.64.0.0/10 # RFC 6598 shared space: Tailscale, cloud metadata
|
||||
- 169.254.0.0/16 # link-local: 169.254.169.254
|
||||
- 172.16.0.0/12
|
||||
- 192.0.2.0/24 # documentation prefixes
|
||||
- 192.88.99.0/24 # deprecated 6to4 relay anycast
|
||||
- 192.168.0.0/16
|
||||
- 198.51.100.0/24
|
||||
- 203.0.113.0/24
|
||||
- 224.0.0.0/4 # multicast: mDNS, SSDP
|
||||
- 240.0.0.0/4 # reserved, includes limited broadcast
|
||||
- fc00::/7 # ULA: home network and Tailscale IPv6
|
||||
- fe80::/10
|
||||
- 2001:db8::/32 # IPv6 documentation
|
||||
- 2002::/16 # deprecated 6to4
|
||||
|
||||
# Optional extra rule-sets, usable by the rules below:
|
||||
# rule_providers:
|
||||
# my_list:
|
||||
@@ -80,28 +101,9 @@ rules:
|
||||
- DOMAIN-SUFFIX,nsclouds.cn,DIRECT
|
||||
- DOMAIN-SUFFIX,wanwang.space,DIRECT
|
||||
- DOMAIN-SUFFIX,baishancdnx.cn,DIRECT
|
||||
# Steam dials cached CM IPs on 27018/27020/27024 without a lookup, so domain rules
|
||||
# leak. Regenerate: stat.ripe.net/data/announced-prefixes/data.json?resource=AS32590
|
||||
- IP-CIDR,45.121.184.0/24,DIRECT,no-resolve
|
||||
- IP-CIDR,103.10.124.0/23,DIRECT,no-resolve
|
||||
- IP-CIDR,103.28.54.0/24,DIRECT,no-resolve
|
||||
- IP-CIDR,146.66.152.0/24,DIRECT,no-resolve
|
||||
- IP-CIDR,146.66.155.0/24,DIRECT,no-resolve
|
||||
- IP-CIDR,155.133.224.0/21,DIRECT,no-resolve
|
||||
- IP-CIDR,155.133.236.0/22,DIRECT,no-resolve
|
||||
- IP-CIDR,155.133.240.0/23,DIRECT,no-resolve
|
||||
- IP-CIDR,155.133.244.0/24,DIRECT,no-resolve
|
||||
- IP-CIDR,155.133.246.0/24,DIRECT,no-resolve
|
||||
- IP-CIDR,155.133.248.0/22,DIRECT,no-resolve
|
||||
- IP-CIDR,155.133.252.0/24,DIRECT,no-resolve
|
||||
- IP-CIDR,155.133.254.0/23,DIRECT,no-resolve
|
||||
- IP-CIDR,162.254.192.0/21,DIRECT,no-resolve
|
||||
- IP-CIDR,185.25.180.0/24,DIRECT,no-resolve
|
||||
- IP-CIDR,185.25.182.0/23,DIRECT,no-resolve
|
||||
- IP-CIDR,192.69.96.0/22,DIRECT,no-resolve
|
||||
- IP-CIDR,205.196.6.0/24,DIRECT,no-resolve
|
||||
- IP-CIDR,208.64.200.0/22,DIRECT,no-resolve
|
||||
- IP-CIDR,208.78.164.0/22,DIRECT,no-resolve
|
||||
# Match Valve by ASN so its content servers stay direct. Steam dials cached CM
|
||||
# IPs without a lookup, so domain rules leak; needs ASN.mmdb via `geox-url.asn`.
|
||||
- IP-ASN,32590,DIRECT,no-resolve
|
||||
- DOMAIN,launcher-webstatic.hoyoverse.com,DIRECT
|
||||
|
||||
# CN consumer services: proxied they fail in ways that look like app bugs --
|
||||
|
||||
@@ -29,6 +29,10 @@ tun_strict_route: true
|
||||
tun_exclude_process:
|
||||
# - some-app
|
||||
|
||||
# CIDRs kept out of TUN; the default is policy.yaml's list. Setting this replaces
|
||||
# the whole list, and `[]` puts everything back through TUN.
|
||||
# tun_exclude_address: [192.168.0.0/16]
|
||||
|
||||
providers:
|
||||
# The core imports a subscription's proxies only; `rules_from` carries its
|
||||
# rules and groups over from a local snapshot copy. Only worth it when the
|
||||
|
||||
Reference in new issue
Block a user