Files
ShadowsocksX-NG/docs/rule-snapshots.md
T

5.0 KiB

Bundled Rule Snapshots

Project home | 简体中文

Bundled snapshots used by rule mode are explicitly maintained artifacts:

  • geolocation-cn (issue #63): after manually reviewing the upstream source, run Scripts/update-geolocation-cn.sh. It parses typed entries from the pinned geosite.dat release of Loyalsoldier/domain-list-custom and generates Vendor/rules/geolocation-cn/snapshot.json.
  • china-ipv4 (issue #64): run Scripts/update-china-ipv4.sh to normalize and deduplicate IPv4 CIDRs from the pinned china.txt version of gaoyifan/china-operator-ip, generating Vendor/rules/china-ipv4/snapshot.json.
  • gfwlist (issue #65): run Scripts/update-gfwlist.sh to decode the official Base64 AutoProxy list from a pinned gfwlist.txt version of gfwlist/gfwlist, generating Vendor/rules/gfwlist/snapshot.json. ||host and ||host^ are converted to domain-suffix matches. A |scheme://host rule (optionally with a valid port) is converted to an exact-domain match when its path is empty or /, it has no query, fragment, or user information, and its host is a valid domain without wildcards; the scheme and port are ignored. Only a root path is eligible; rules with a specific path are skipped. @@ retains the direct-routing action. Other URL prefixes, paths, wildcards, regular expressions, single-label prefixes, and IP-literal rules are counted by category in the loss report. A @@ exception completely covered by proxy rules is not written as an ineffective ACL entry (sslocal domain matching gives proxy_list priority over bypass_list). The proxy rule is retained, and the number of shadowed exceptions is included only in absorbedCount. The maintenance script prints per-rule evidence to stdout.

Snapshots use compact JSON with schema 2 / converter 2.0.0: each rule has only action and match; the source appears only in metadata.source; the conversion report retains counts only. Absorbed .cn entries and shadowed GFWList exceptions are not distributed in the snapshot and are not restored after a broad rule is disabled. See ADR-0024. Older snapshot versions are rejected.

Domain values and file DTOs for rules evolve independently. ProxyRule represents both a normalized rule value and rule identity across sources; custom entries also retain a UUID. Custom-rule files are written as schema 3 and no longer store source per rule. Schemas 1 and 2 remain readable; reading does not rewrite the file, and the next normal save updates its format. The bundled snapshot format is unchanged. See ADR-0039.

Python is the only upstream conversion implementation. Swift loads, validates, and consumes snapshots; it does not parse upstream input independently. Run the offline regression checks for conversion scripts with PYTHONDONTWRITEBYTECODE=1 python3 Scripts/test-rule-snapshot-converters.py. The default task test also runs both Python checks; run task test:rules for just these checks. Also run PYTHONDONTWRITEBYTECODE=1 python3 Scripts/test-rule-conversion-behavior.py to verify conversion behavior and the fixed snapshot fixtures used by the unit-test bundle. After reviewing a conversion change, add --write-fixtures to the same command to rebuild the fixtures. Fixture timestamps are fixed, and normal tests compare generated output byte for byte. Check snapshot integrity with Scripts/verify-rule-snapshots.sh.

If an update fails, the previous valid snapshot is kept. geolocation-cn conversion fails on unknown syntax or corrupted input. china-ipv4 conversion also fails on abnormal formats (when too many lines are rejected), when all entries are invalid, or when the snapshot size changes abnormally compared with the previous version. gfwlist conversion fails on unknown syntax, corrupted Base64, abnormal size, or an abnormal size change compared with the previous version. Normal builds run Scripts/verify-rule-snapshots.sh offline to check that snapshots exist, their digests match, and schema/converter versions agree; missing or corrupted snapshots fail the build. Distributed artifacts must include each source's NOTICE (license and attribution).

In rule mode, “proxy when unmatched” generates a proxy_all ACL containing both Chinese-domain and Chinese IPv4-CIDR direct-routing candidates, with fixed local bypass taking priority. “Direct when unmatched” generates a bypass_all ACL containing only effective GFWList proxy candidates. The two default actions do not unconditionally union all bundled sources. Unmatched destinations and IP literals that match no available rule go direct. CIDR checks may trigger local DNS queries: when matching an unmatched domain by IP, sslocal may perform a local DNS query. The product does not promise that all DNS queries travel through the remote Shadowsocks server.