389 Commits
Author SHA1 Message Date
Leadaxe 9dc758e43c Merge upstream/testing (L3-forwarding, snell, bridge) into lx-1.14
Merges 14 upstream commits including L3-forwarding support (which bumped
wireguard-go v0.0.3->v0.0.5, already re-grafted in the prior commit),
snell protocol, bridge outbound, flow-tracking/sniff improvements, and
DNS/dialer fixes.

lx conflict resolutions:
- protocol/wireguard/endpoint.go: took upstream's new flow API
  (PreMatchFlow/PortAddresses/PortMTU/AttachReturn/DetachReturn/JudgeFlow),
  dropped our old PrepareConnection/NewDirectRouteConnection. SPEC 020
  idle-suspend wake guard (resumeOnDial) moved to WritePackets — the single
  point every L3-forwarded packet transits, incl. established flows that
  bypass DialContext.
- adapter/outbound.go: kept lx IdleSuspendable/ReachabilityInvalidator,
  restored 'time' import dropped by auto-merge.
- go.mod/go.sum + test/: took upstream dependency bumps (tailscale, sing,
  sing-tun); wireguard-go stays v0.0.5 with local submodule replace.

Green: full sing-box CLI with LX_TAGS (Go 1.24.7), libbox, wireguard/
adapter/dns/daemon packages, transport+protocol/wireguard tests, AWG
config validation.
2026-07-08 15:10:38 +03:00
世界 9ec7cc8cbe Improve bridge 2026-07-08 16:30:06 +08:00
世界 c7fe778cae Add bridge outbound 2026-07-08 00:34:26 +08:00
世界 f2dd4bfd75 Imrpove flow tracking & sniff action 2026-07-07 18:37:18 +08:00
世界 e6419b945f Add L3 forwarding support 2026-07-06 21:13:33 +08:00
世界 5af56d2cfd Add snell protocol 2026-07-05 12:47:42 +08:00
Leadaxe b28c689cb9 docs: document observability (SPEC 014-018) + round_robin (SPEC 019) across lx docs
The lx feature docs had drifted: README (en/ru) and docs/lx-config.md still said
"currently XHTTP + AWG2" and covered only SPEC 002/003/009 — the observability
layer (SPEC 014-018) and round_robin load balancing (SPEC 019) were undocumented
in the lx overview, and urltest.md still described the pre-rc.15 domain behaviour.

- docs/lx-config.md: new "## 3. round_robin load balancing" (mode/balancer,
  pool/pool_tolerance/sticky_hash, ["none"] sentinel + badjson-[] caveat, slot-hash
  binding, example, status) and "## 4. Observability (CommandClient extensions)"
  (URLTestOutbound/GetRules/GetGroups/GetOutbounds/GetPool/SubscribeDNSQueries +
  Connection.detourList, all behind with_lx_command); Validate&build -> ## 5.
- README.md / README.ru.md: broaden the stale "XHTTP + AWG2" framing; add feature
  rows for observability and round_robin with honest status.
- docs/configuration/outbound/urltest.md: reconcile sticky_hash "domain" with the
  rc.15 fix — domain reads metadata.Domain (survives domain->IP resolve), so it
  works for normal sniffed domain traffic, not only literal-IP destinations; the
  warning is reframed (domain works; dest_ip is an alternative).

Docs-only; no code change.
2026-06-29 02:23:49 +03:00
Leadaxe a531879e02 fix(SPEC 019 v2): three sticky/pool bugs found by device verification
Device verification of round_robin on a real 51-node pool surfaced three bugs,
all fixed here. Listed by impact.

1. sticky key 'domain' was always empty -> all traffic collapsed to one node.
   The router resolves a domain destination to an IP and overwrites
   metadata.Destination before a group's DialContext runs, so destination.Fqdn
   is empty when the balancer builds the key. stickyComponent("domain") read
   that empty Fqdn, so a single process's key was process+NUL for every site
   -> one fixed slot. On device this measured 28/1/1 across a 3-node pool
   (uniformity 0.27). Fix: read metadata.Domain (survives the resolve), fall
   back to destination.Fqdn only for a direct dial. After: spread 0.95+.

2. living pool nodes could change slot index during a health-check, moving
   sticky keys. balancePoolFirstLive compacted with a filtering append (a
   transiently-dead slot shifted every later live node left); planTolerantPool
   did delete(inPool, occupant) (an evicted-but-living node re-entered a later
   slot, cascading); manual URLTest rebuild ran the tolerant planner even at
   pool_tolerance==0. All now replace-in-slot (fixed-length copy(current), only
   dead/empty slots rewritten by index; dedicated planFirstLivePool for the
   tolerance==0 rebuild).

3. stickiness could not be disabled via sticky_hash: [] -- the config decoder
   (badjson.UnmarshallExcludedContext) re-marshals the struct and collapses an
   empty array to nil, indistinguishable from omitted, so the default always
   applied. Disabling now uses the explicit sentinel sticky_hash: ["none"].

Tests: domain-from-metadata + fallback, replace-in-slot survivor/cascade/
first-live regressions (fail against pre-fix code), ["none"] disable + []
defaults + none-mixed error. All green under -race; gofmt clean.
2026-06-28 21:48:31 +03:00
Leadaxe 50efd8f335 fix(SPEC 019 v2): balancer.pool 0 = default, not error (rc.14)
Desktop smoke-test of the rc.13 binary surfaced this: a Go int with omitempty can't tell
`pool: 0` from an omitted field, so `pool: 0` hit the `< 1` validation and rejected a
config that should have defaulted. Now pool 0/omitted → default 3; only a negative pool
errors. Added TestBalancerZeroPoolIsDefault; renamed the negative-pool test. SPEC_V2,
urltest.md, changelog rc.14 updated.

Verified on the rc.13 desktop binary: round_robin pool fill (pool_tolerance:0 tests only
pool-many nodes, >0 tests all), config fail-fast (balancer+least_test, unknown sticky_hash,
unknown mode, negative pool), and live routing through the group.
2026-06-28 18:11:55 +03:00
Leadaxe 5997b1812a lx(1.14): SPEC 019 v2 — round_robin pool, lazy health-check, slot-hash sticky, GetPool
Reworks urltest round_robin to scale to large node lists. v1 rotated over ALL live nodes,
which meant URL-testing every node each interval (unworkable at 1000 nodes). v2:

- Fixed-size pool of slots (balancer.pool, default 3). Slot indices never move; a
  replacement takes the exact slot it evicts. round_robin rotates only within the pool.
- Lazy health-check: pool_tolerance=0 tests no more nodes than needed to keep the pool
  full of live nodes, then stops; pool_tolerance>0 tests all and keeps the fastest with a
  per-slot eviction threshold. Dead pool node keeps its slot until a live replacement is
  found (pool never empties). A dial error never changes the pool — only the health-check.
- sticky = slot-hash (slot[hash(key)%pool], FNV-64a). Binds to a fixed slot index, so a
  living node keeps ALL its keys when other slots churn: strict zero reconnects, zero
  per-key state. Default sticky_hash ["process","domain"]; explicit [] disables.
- Removes v1 jumphash (broke on mid-list eviction), ttl_map, and least_connection (dropped
  from the roadmap — round_robin is statistically even).
- GetPool RPC: CommandClient.GetPool(tag) -> []PoolSlot{slot,tag,delay} so clients can show
  the N nodes actually in rotation. delay clamped 0->1 for live nodes; non-round_robin
  group -> empty. Additive proto/daemon/libbox, behind with_lx_command.

Config moved under a `balancer` object (breaking for the rc.11/12 round_robin shape; no
prod configs, tests only). least_test (default) is byte-for-byte unchanged.

Tests: newBalancer validation/defaults, rotation distribution, slot-hash stable +
living-node-keeps-keys-across-other-slot-churn, empty-key fixed slot, planTolerantPool
top-N / keep-in-tolerance / evict-beyond / dead-slot-replace. go build (+with_lx_command),
go test -race ./protocol/group/, gofmt all clean. Not yet device-verified.
2026-06-28 17:50:43 +03:00
Leadaxe 061b5f4cca docs(SPEC 019): add TEST_REPORT (live-verified) + dest_ip stickiness caveat
Live run on 5 vless nodes (3 instances, one per mode): round_robin rotates strictly
across the live set and skips dead nodes; both sticky strategies pin deterministically;
bad config is rejected at start; -race clean on units and live. Feature is now
device-verified, not just isolated.

The run surfaced a config caveat (not a bug, by design): dest_ip is empty until the
destination is resolved, so a sticky key of only source_ip/dest_ip/dest_port collapses
to "" for domain traffic and pins everything to one node. Documented in urltest.md —
use `domain` in `hash` for domain-based traffic.
2026-06-28 01:23:45 +03:00
Leadaxe 5ebff914fc lx(1.14): SPEC 019 urltest mode + sticky load-balancing
Add a `mode` to the urltest group so it can distribute traffic instead of only
picking the lowest-delay node, with optional per-flow stickiness.

- mode: least_test (default, unchanged) | round_robin (rotate across live nodes)
  | least_connection (reserved, phase 2 — rejected at config time).
- round_robin selects once per connection over the tag-sorted live set (nodes with
  a fresh URL-test result supporting the network); UDP/QUIC sessions stay on one
  node; first usable outbound is the fallback when nothing is live. The legacy
  selectedOutbound* cache path is untouched — balancing is a separate branch in
  DialContext/ListenPacket.
- sticky {mode, timeout, cap, hash}: binds one flow to one node. hash components
  process|domain|source_ip|dest_ip|dest_port concatenate in order; absent -> "",
  all-empty key -> one fixed node (keyless flows never rotate). mode jumphash
  (default, stateless consistent hash — ~1/n remap on node-set change) or ttlmap
  (key->node table, lazy + ticker eviction, 2000 LRU cap, 10m TTL, dead-node re-pin).

Reuses the existing urltest health ticker/history as the single liveness source;
no new probing. Now() reports the last-picked tag in balanced modes.

Tests (go test -race, 15 cases): distribution, dead-node skip, all-dead fallback,
jumphash stability + empty-key fixed node, ttlmap stick/expire/cap/dead-repick,
key building, validation. The race detector caught a real bug in the sticky
sweeper (read t.ticker unlocked while close() nilled it) — fixed by passing the
channels into the goroutine, mirroring URLTestGroup.loopCheck.

Also folds the SPEC 016 connections-map mutex (ebf9cc07) into the rc.11 changelog
section, which had not yet shipped in a release.
2026-06-28 01:10:17 +03:00
世界 0794d645af Add iOS jailbreak release 2026-06-25 17:39:16 +08:00
世界 4d5c2a03d6 documentation: Add USB/IP server and client 2026-06-25 17:39:08 +08:00
世界 f4061770bb Fix remote control when Clash server is unavailable 2026-06-25 17:38:56 +08:00
世界 3035af688e Add dashboard support for API service 2026-06-25 17:38:56 +08:00
世界 95c37c138a Add sing-box API service 2026-06-25 17:38:53 +08:00
世界 dcbb8271f8 platform: Add tailscale device name and logout 2026-06-25 17:38:52 +08:00
世界 f18b01b7fe tailscale: Add tailssh server 2026-06-25 17:38:51 +08:00
世界 d0ef5c028d hysteria2: Add gecko obfs 2026-06-25 17:38:51 +08:00
世界 23a676ac8a tailscale: Revert dialer deprecation and remove control_http_client 2026-06-25 17:38:25 +08:00
世界 4b55717612 Fix hysteria2 realm server 2026-06-25 17:38:12 +08:00
世界 d8f461cc5a Update hysteria2 realm 2026-06-25 17:38:12 +08:00
世界 094808a4fa Add hysteria2 realm service and support 2026-06-25 17:38:11 +08:00
macronut c768f248d9 Add more spoof method
Signed-off-by: macronut <4027187+macronut@users.noreply.github.com>
2026-06-25 17:38:11 +08:00
世界 e8643485d2 Allow customizing TUN DNS mode and hijack interface DNS by default 2026-06-25 17:38:10 +08:00
世界 ce360eece8 dns: Add mDNS server 2026-06-25 17:38:10 +08:00
世界 511e72bcfb dns: Add preferred_by rule item 2026-06-25 17:38:10 +08:00
世界 9b277bd690 dns: Add neighbor-based hostname resolution to local server 2026-06-25 17:38:09 +08:00
世界 dd454bf0c6 dns: Add timeout configuration 2026-06-25 17:38:08 +08:00
世界 1541bbc91d ssh: Add cipher, MAC, and key exchange configuration 2026-06-25 17:38:08 +08:00
nekohasekai a37fcd59bb Add Windows TLS engine 2026-06-25 17:38:07 +08:00
世界 6e2c0fa249 Add ACME profile support for IP address certificates 2026-06-25 17:38:05 +08:00
世界 157eb993de Add search domain support for Tailscale DNS 2026-06-25 17:38:04 +08:00
世界 3d1d6acbe3 Add TLS spoof support 2026-06-25 17:38:01 +08:00
世界 cfe83a5dcc Refactor: HTTP clients, unified HTTP2/QUIC options, Apple engines 2026-06-25 17:37:59 +08:00
世界 ecd07e2f85 Add optimistic DNS cache 2026-06-25 17:37:59 +08:00
世界 2255e1f80b documentation: Fix missing update for ip_version and query_type 2026-06-25 17:37:58 +08:00
世界 fd7bc21175 Add cloudflared inbound 2026-06-25 17:37:08 +08:00
世界 dec919e0ca Add package_name_regex route, DNS and headless rule item 2026-06-25 17:35:30 +08:00
世界 db1e08a07f documentation: Fixes 2026-06-25 17:35:30 +08:00
世界 d8b7e92cc2 Un-deprecate ip_accept_any DNS rule item 2026-06-25 17:35:29 +08:00
nekohasekai 92118b594c Add evaluate DNS rule action and related rule items 2026-06-25 17:35:25 +08:00
世界 f96582c5d1 Add BBR profile and hop interval randomization for Hysteria2 2026-06-25 17:35:24 +08:00
nekohasekai 1d523907cb Refactor ACME support to certificate provider 2026-06-25 17:35:24 +08:00
世界 306ed3e496 documentation: Update descriptions for neighbor rules 2026-06-25 17:35:24 +08:00
世界 6dd01016da Add MAC and hostname rule items 2026-06-25 17:33:05 +08:00
世界 cb70a068c5 Add iOS jailbreak release 2026-06-21 12:16:31 +08:00
世界 5f6e5a8ed0 documentation: Add USB/IP server and client 2026-06-20 22:25:00 +08:00
世界 e4e8af4755 Fix remote control when Clash server is unavailable 2026-06-20 22:24:49 +08:00