mirror of
https://hubproxy.babadafafafafa.cn/https://github.com/mihomo-party-org/clash-party.git
synced 2026-09-20 08:03:39 +08:00
Client-side hardening of the CPX airport plugin, squashed from 46 commits
forked at 89c2bb0e. Behaviour changes:
- Unified operation model (§0.4/0.5): one deadline + one AbortSignal + one
persistence commit per operation; per-plugin lock → vault lock hierarchy;
tombstone on delete; every wait (lock, DNS preflight, proxy resolution,
vault decrypt) is bounded by the same budget.
- Routing: direct/proxy auto-fallback with a pre-send guard; proxied https
builds its own CONNECT tunnel (an aborted hung CONNECT closes its socket);
invalid local-proxy ports are refused instead of falling back to :80; the
core's inbound credentials are carried to the local proxy; NAT64 and
site-local IPv6 ranges are non-public.
- Gateways: multi-gateway recovery with one rediscovery per operation,
normalized endpoint paths, signed discovery documents (Ed25519, seq/digest
accept/align/rollback/equivocation), commit order vault → plugin.yaml.
- Subscriptions: a fetched subscription is validated by the core (mihomo -t)
against the current override set before it replaces the profile, inside
the profile write critical section (profile.yaml and override.yaml share
one write queue); schedule fields are read at write time; the first
subscription is activated through the real switch flow; profile deletion
removes the record last so any failure stays retryable.
- Devices: a re-login that replaces a still-valid device records it in the
vault (staleDevices) and retires it after the login, after later
successful fetches and on removal; enroll compensation restores the old
vault and keeps an un-revoked new device for retirement.
- Vault: on Linux the vault is persisted only behind a system secret store
(backend name + ciphertext-prefix canary); otherwise it stays in memory.
A cache-miss read releases the caller at the budget while the lock is held
until the decrypt ends.
- Config caches (plugin.yaml, profile.yaml, override.yaml) can no longer be
rolled back by a late cold read.
- Reference gateway and provider guides updated (deploy contract, discoveryUrls
same-origin rule, /revoke after re-login); https-proxy-agent dropped.
Reviewed in a Codex loop (gpt-6, 38 calls): 74 findings, 68 fixed and
verified, 6 invalid, no backlog. Tests: vitest 501, gateway 106.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
47 lines
2.3 KiB
Plaintext
47 lines
2.3 KiB
Plaintext
# Public domain. An A/AAAA DNS record MUST point at this VPS before deploying —
|
|
# Caddy uses it to obtain a Let's Encrypt certificate. Required.
|
|
DOMAIN=gw.example.com
|
|
|
|
# Optional: serve several domains from this ONE gateway process. Separate them with a comma
|
|
# AND a space ("a, b"): Caddy takes the value verbatim as site addresses and rejects a bare
|
|
# "a,b" (deploy.sh normalizes it, docker compose alone does not). Caddy obtains a certificate
|
|
# for each. Use together with GATEWAY_ORIGINS.
|
|
# DOMAINS=gw.example.com, gw2-cdn.example.net
|
|
|
|
# Optional: 1..3 https origins advertised in /.well-known/cpx-gateway as `gateways`
|
|
# (`gateway` is always gateways[0]). Every origin MUST reach this same process — codes,
|
|
# nonces and rate limits live in memory, so multiple replicas are not supported.
|
|
# Defaults to PUBLIC_ORIGIN (https://$DOMAIN).
|
|
# GATEWAY_ORIGINS=https://gw.example.com,https://gw2-cdn.example.net
|
|
|
|
# Default per-user device limit for `cpx-admin add-user` (override per user with --limit).
|
|
DEVICE_LIMIT_DEFAULT=3
|
|
|
|
# ---- Advanced (sensible defaults; uncomment only to override) ----
|
|
# gateway origin written into /.well-known/cpx-gateway (defaults to https://$DOMAIN)
|
|
# PUBLIC_ORIGIN=https://gw.example.com
|
|
# Allowed client/server clock skew for signed requests (ms)
|
|
# CLOCK_SKEW_MS=300000
|
|
# Upstream subscription fetch timeout (ms) and max size (bytes)
|
|
# SUB_TIMEOUT_MS=30000
|
|
# SUB_MAX_BYTES=10485760
|
|
# Pending nonces kept per device
|
|
# NONCE_POOL_MAX=8
|
|
# Login attempts allowed per IP per window
|
|
# LOGIN_MAX=10
|
|
# LOGIN_WINDOW_MS=60000
|
|
# Set to "true" to retire this gateway: /challenge and /config return 410 gateway_retired
|
|
# RETIRED=false
|
|
# Path (inside the container) to a private CA cert for the subscription origin
|
|
# ORIGIN_CA_FILE=
|
|
|
|
# Optional: JSON file (inside the container) with human-readable messages the client shows
|
|
# next to the matching error. Keys: device_revoked, device_limit, gateway_retired.
|
|
# MESSAGES_FILE=/data/messages.json
|
|
|
|
# Optional: pre-signed discovery envelope ("<payloadB64>.<sigB64>") produced OFFLINE with
|
|
# `cpx-admin sign-discovery`. Served as well-known `signed` and as the X-CPX-Discovery header.
|
|
# The private key must never be on this host. Publish this BEFORE distributing a .cpx that
|
|
# contains providerPubKey.
|
|
# DISCOVERY_SIGNED_FILE=/data/discovery.signed
|