Highlights
- Upstream v26.10.21 and
mainup to229799a7. 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
maxConcurrencyholds 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 534and now sends53 560, as upstream does. The server sent19 534and now sends536. - Gate.
TestVLESSTCPHeaderSharesTLSRecordWithFirstPayloadchecks 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.
- 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
- 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.
- SNI. Over h1/h2 the resolver sent no SNI and failed handshakes without
- TLS dialers (#62). An outbound whose
tlsSettingsholds 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
mainto229799a7(#65, #69):- WireGuard and MASQUE on Xray's own TCP/IP stack (XTLS#7156);
- XDNS DoH resolvers (XTLS#7140);
- Finalmask inbound
filter(XTLS#7206), and Luascriptfor Noise (XTLS#7124); - the Lua sandbox by default, with inline scripts refused for now (XTLS#7136);
- XDRIVE: h2 by default, h3 and XMUX (XTLS#7181, XTLS#7182, XTLS#7187, XTLS#7188);
- the Hysteria client resets stalled writes on close (XTLS#7172);
- TUN large TCP segments on Linux (XTLS#7179);
- refreshed TLS built-in roots (XTLS#7212);
go-proxyproto0.16.0 (XTLS#7237).
- Freedom
blockDelaynow also applies toDispatchLink()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
autoOutboundsInterfaceretry 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 isIPV6_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
AddInboundinstead 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.
h2Flowremains opt-in.queueCutsdefaults 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 standardon the candidatec99d0258: pass (unit, race, vet, checkptr, the Xray/sing-box/Mihomo VLESS TCP and SMUX process matrices, the VLESS header record gate, scenarios). Tests and Checkingson the release commit: pass.Pre-release Validation(pinned Linux gate,structural_presence.sh linux): pass, https://github.com/Jolymmiles/Xray-core/actions/runs/40684625524