github lilendian0x00/xray-knife v9.12.0
Xray-knife v9.12.0

latest release: v9.12.1
3 hours ago

What's New

Correctness pass on the rotating proxy: rotation, chain mode, and health checks.

🎛️ New Proxy Flags

  • --health-fail-threshold <n> — consecutive health-check failures before the active config takes a strike (default 3).
  • --chain-attempts <n> — random chain combinations to try per rotation cycle (default 5).

🩺 Better Health Checks

  • Health probe now runs through the live local listener (SOCKS5 / HTTP), so it tests both the inbound and the outbound — not just the outbound.
  • A single failure no longer counts; it takes --health-fail-threshold failures in a row.
  • Single-config mode (--config <link>) also runs health checks now and rebuilds the instance on repeated failure.

🐛 Bug Fixes

  • --drain > 0 broke rotation: the new and old instances tried to bind the same port at the same time, so Start failed. Old listener is now closed before the new one binds; --drain becomes the wait before the switch.
  • Chain rotation had the same port conflict — fixed the same way.
  • Timer deadlock on Go 1.23+: the legacy if !timer.Stop() { <-timer.C } drain blocked forever because Stop already empties the channel. Removed in all six rotation loops.
  • Chain mode ignored in app mode: --chain was silently dropped, fell through to rotation. App mode now picks the right runner.
  • Short chains: selectChainFromPool returned fewer hops than requested when some pool entries failed to parse. Now walks the whole pool until it has enough valid hops.
  • Configs that failed instance Start were left untracked and kept getting picked again. Now striked like any other failure.
  • --rotate 0 tight loop: zero or very small rotation values are clamped to a minimum.
  • Bad listen port was silently ignored, leaving the namespace tunnel on port 0. Now validated up front.
  • Stdin EOF spam: closing stdin (< /dev/null, daemonized) turned EOF into an endless force-rotate stream. Watcher exits cleanly on EOF.
  • System mode + non-HTTP/SOCKS inbound is rejected up front instead of pointing the OS proxy at something browsers can't speak.
  • --bind not honored at test time: examiner now inherits --bind so test results match runtime.
  • Current outbound wasted a test slot per rotation. It's now removed from the candidate set before the batch is picked.

⚡ Improvements

  • Rotation state collapsed to a single rotating value so the web UI no longer flickers between testing and switching mid-cycle.
  • Auto-generated SOCKS username/password bumped from 4 to 16 chars (app mode binds on 0.0.0.0).
  • Pool shuffles use a per-call rand source instead of the global one, reducing contention from the web service.

Migration note: --drain is no longer asynchronous. With a non-zero value, rotation now waits that many seconds on the current outbound, closes it, then brings the next one up. There is a brief gap on the inbound port during the handover. Set --drain 0 (the default) for an immediate switch.

Don't miss a new xray-knife release

NewReleases is sending notifications on new releases.