github Jolymmiles/Xray-core v26.10.28-1202
Xray-core v26.10.28-1202

3 hours ago

Highlights

  • Upstream v26.10.21 and main up to 229799a7. This brings XDRIVE (h2 by default, h3, XMUX), XDNS DoH resolvers, WireGuard and MASQUE on Xray's own TCP/IP stack, the Lua sandbox by default, and Vision reading the REALITY raw input through a pointer (XTLS#7176, the SIGSEGV of XTLS#7162) (#59, #65, #69).
  • The VLESS header now shares a TLS record with the first payload. A VLESS client and server no longer send the request header, or the [version, 0] response, in a TLS/REALITY record of its own. Record lengths after the REALITY handshake now match upstream's (#61, #63).
  • XHTTP downloads hold their rate beside other traffic. A governed (h2Flow) XHTTP server no longer drives a download down to about 1 Mbit/s when other traffic keeps the path's queue full (#64).
  • XMUX maxConcurrency holds under concurrent dials. XHTTP and XDRIVE now count a dial in the XMUX client it picks before another dial can pick it (#66, #67, #68).

Fork fixes

  • VLESS header and first payload (#61, #63).
    • Without sniffing. The VLESS outbound flushed its header before the first payload when the inbound gave it a plain link reader (SOCKS, HTTP, dokodemo with sniffing off). It now waits for the first payload whatever the reader, as upstream does.
    • Silent client. Vision now sends its padding block when the client stays silent.
    • One record. In flush-next mode the VLESS writers handed the header to the TLS conn as a separate slice, so each became its own record. After the REALITY handshake, a no-flow client sent 53 43 534 and now sends 53 560, as upstream does. The server sent 19 534 and now sends 536.
    • Gate. TestVLESSTCPHeaderSharesTLSRecordWithFirstPayload checks all four TLS/REALITY × no-flow/Vision modes between Xray processes.
  • XHTTP flow governor beside a standing queue (#64). A governed server cut download caps against a queue that other traffic kept full, so cut after cut took a download to its floor. Each connection now measures what its cuts do to the queue and scales them by that gain. Measured with burst.py (one download at 60 Mbit/s, RTT 144 ms, beside four plain TCP flows for 20 s): over the burst's second half the download went from 0.8 Mbit/s to 16.5 Mbit/s on a pre-final revision, against 31.0 Mbit/s with no governor. "h2Flow": {"queueCuts": false} turns the cuts off for an inbound.
  • XMUX reservation (#66, #67, #68).
    • XHTTP and XDRIVE. Both counted a dial in its XMUX client only after releasing the pool lock. Simultaneous dials could therefore stack on one connection past xmux.maxConcurrency.
    • Failed dials. An XHTTP dial whose streams failed to open kept its reservation and left its download stream open. It now releases both.
    • XDRIVE templates. A data race on the template storage's retry delay is gone.
  • REALITY config validation (#59). A malformed REALITY private key, ML-DSA-65 seed, or short ID of the wrong length, in a protobuf config or a HandlerService AddInbound, panicked the whole process when the listener started. That inbound is now refused with an error.
  • TUN segments (#59). With segments on, a TCP segment reassembled from IP fragments, or joined to verify its checksum, was queued as the buffer its last piece was read into. The connection then read the wrong bytes or stalled. Such a segment is now copied.
  • XDNS DoH resolver (#59, #60).
    • SNI. Over h1/h2 the resolver sent no SNI and failed handshakes without serverName. Its ClientHello now carries the URL's host, as h3 already did.
    • Leaks and crashes. A failed h3 dial no longer leaks its UDP socket, and "congestion": "brutal" no longer crashes the client.
    • Redirects. HTTP redirects are refused: Go's default policy turned the POST into a GET and read the redirect target's page as the DNS answer.
  • TLS dialers (#62). An outbound whose tlsSettings holds a certificate read from files started a certificate refresh goroutine on every dial. Dialers now build their TLS config without it. The ClientHello is byte-identical for every fingerprint.
  • QUIC sniffing (#27). The QUIC sniffer read a UDP flow's cached datagrams as one stream. A client could thus route a flow by one server name while the server read another. It now reads the datagrams one by one, as a server receives them, and names no server where servers would disagree.

Upstream changes

  • v26.10.17 and v26.10.21 (#59), plus main to 229799a7 (#65, #69):
  • Freedom blockDelay now also applies to DispatchLink() inbounds such as VLESS and Hysteria (XTLS#7238). Before, a blocked target over VLESS stayed open until the client closed it.
  • Windows: when an interface cannot bind both families, the UDP system dialer and the TUN inbound's autoOutboundsInterface retry with a single-family socket (XTLS#7214). On every platform the local DNS client now dials the IP family of the server, so on Linux a socket to an IPv6 DNS server is IPV6_V6ONLY.

Compatibility notes

  • VLESS, Trojan, REALITY, Vision and SMUX wire formats are unchanged. The VLESS change is in TLS record framing only: the header and the first payload now go in one record, as upstream sends them.
  • REALITY inbounds with a malformed key, seed or short ID are now refused at load or AddInbound instead of crashing the process.
  • The XDNS DoH resolver now refuses HTTP redirects (a fork policy; RFC 8484 allows them) and sends SNI on h1/h2.
  • h2Flow remains opt-in. queueCuts defaults to on when the governor is enabled.
  • Fork deviations from upstream and the tests that guard them are listed in docs/FORK.md. Builds use Go 1.27.3 with -tags http2legacy.

Validation

  • Local release gate testing/release/structural_presence.sh standard on the candidate c99d0258: pass (unit, race, vet, checkptr, the Xray/sing-box/Mihomo VLESS TCP and SMUX process matrices, the VLESS header record gate, scenarios).
  • Tests and Checkings on the release commit: pass.
  • Pre-release Validation (pinned Linux gate, structural_presence.sh linux): pass, https://github.com/Jolymmiles/Xray-core/actions/runs/40684625524

Don't miss a new Xray-core release

NewReleases is sending notifications on new releases.