github Jolymmiles/Xray-core v26.10.5-1858
Xray-core v26.10.5-1858

5 hours ago

Highlights

  • Fixes a Hysteria server crash: a late write on a released UDP link panicked in a detached goroutine and took the whole process down.
  • Mux.Cool over a Hysteria server no longer corrupts streams. Concurrent sessions used to interleave frame headers and payloads.
  • The REALITY server again authenticates clients whose Client Hello does not offer X25519MLKEM768, such as sing-box with a Chrome fingerprint. Before this release they fell back to the cover target.
  • XHTTP inbounds accept Mux.Cool TCP sessions; upstream accepts only pure XUDP there. In packet-up and stream-up, the server can optionally poke an idle downlink with a padded Mux.Cool KeepAlive, so CDNs and reverse proxies do not cut it as idle (#16, contributed by Medium1992).
  • Merges upstream Xray-core v26.9.8, v26.9.9, v26.9.30, and later upstream/main fixes through 7da5dae6. This adds the MASQUE inbound/outbound/transport, the XDRIVE transport, the rewritten XDNS finalmask, and the FinalMask-based transport dialer/listener.
  • Builds with Go 1.27.1 and -tags http2legacy. While a TLS handshake hangs, XHTTP over HTTP/2 shares one pending dial again instead of opening a connection per request (XTLS#6797).

Fork fixes

  • Hysteria server link ownership. Server.Process took UDP readers, writers and links from a sync.Pool and released them when DispatchLink returned. Outbound tasks and mux/XUDP workers keep using the link after that point, so a late write hit a nil writer and panicked. A reused pooled object could also deliver data to another session. Links are now allocated per session and the pools are removed; per-packet zero-copy parsing is unchanged. The unused pooled-writer API in common/buf is removed with them.
  • Hysteria TCP and Mux.Cool framing. The TCP link writer now serializes whole frames. Before, an Xray client with mux enabled could receive another session's frame headers inside its TCP data.
  • Mux.Cool carrier check. Mux.Cool workers start only for TCP destinations. A UDP packet addressed to v1.mux.cool, for example over a Hysteria UDP session, is dispatched like any other packet.
  • REALITY key shares. Upstream xtls/reality 20260908062103 rejects every Client Hello without an X25519MLKEM768 key share. The server now runs from an in-tree copy of that module version, third_party/reality, with one change: a hello that offers the hybrid group in neither supported_groups nor key_share authenticates through its X25519 key share. Hellos that offer the hybrid group keep upstream's rules. Unauthenticated connections still reach the cover target unchanged.
  • XDNS finalmask hardening (on top of the upstream rewrite):
    • A fragmented query shorter than its fragment header no longer panics the server before authentication.
    • DNS-over-TCP resolvers send the RFC 1035 two-byte length prefix.
    • Per-client fragment counters no longer accumulate.
    • A full send queue returns an error instead of blocking.
    • TCP and UDP resolvers can be closed during a stalled write.
    • Resolver redials publish their address atomically.
  • FinalMask settings. An unknown, corrupt or misplaced mask now returns an error instead of panicking. This applies both when loading a configuration and when adding inbounds/outbounds through the HandlerService API.
  • MASQUE resource lifetime:
    • The server releases every queued packet when a tunnel closes, including when it closes before its writer starts.
    • The client sends Packet Too Big ICMP replies through one bounded writer instead of starting a goroutine per oversized packet.
  • XHTTP Mux.Cool KeepAlive shutdown. The idle-downlink KeepAlive loop could write a frame after a Mux.Cool worker reported closed. It now checks for shutdown after building each frame and right before writing it. Shutdown itself never waits for the loop, so a write stuck on a stalled connection cannot hold Close. The idle timer uses the monotonic clock, so a wall-clock step cannot stretch or skip a KeepAlive.
  • Build tooling. vformat skips vendored third_party modules so they stay byte-identical to upstream. The codename now reads (Jolymmiles).

Upstream changes

Previous fork releases were based on upstream v26.7.28. This release merges upstream v26.9.8, v26.9.9 and v26.9.30, plus upstream/main through 7da5dae6. Notable changes:

  • New protocols and transports:
    • MASQUE (IETF CONNECT-IP, RFC 9484) inbound, outbound and transport, including HTTP/2 Extended CONNECT.
    • XDRIVE remote-storage transport with Google Drive and template backends.
  • Transport and FinalMask:
    • Transports are built on FinalMask's dialer and listener.
    • udpHop is a FinalMask UDP mask; noise masks support exp.
    • XDNS finalmask is rewritten and gains new parameters, and its resolver-close deadlock and socket leaks are fixed.
  • Proxies:
    • Shadowsocks 2022 is refactored without sing* dependencies.
    • XTLS Vision suppresses the outer CloseNotify after switching to direct copy.
    • Blackhole supports a custom response.
    • Freedom compatibility and dialerProxy handling are improved.
    • HTTPUpgrade sends Sec-WebSocket-* headers.
    • The Hysteria outbound no longer truncates UDP datagrams with ChromeParrot.
  • WireGuard:
    • Startup, close and packet-view release are fixed.
    • The outbound endpoint IP is fixed.
    • Idle UDP flows hold less memory.
    • The inbound answers ICMP ping.
    • kernelTun IPv6 table allocation is fixed.
  • TUN and system:
    • Linux gains autoSystemDNS; Windows gains autoSystemWfpBlockLeak, adapter reuse, and startup when IPv6 is disabled.
    • UDP packet destinations are preserved with traffic stats.
  • Clients and runtime:
    • The mux client Dispatch/SessionManager.Close race is fixed.
    • The gRPC client no longer redials with a canceled first-request context.
    • The XHTTP WaitReadCloser data race is fixed.
    • The buffered writer handles payloads larger than its remaining capacity.
    • The QUIC sniffer handles zero-filled datagram tails.
    • Geodata matchers use less memory.
  • Dependencies: Go 1.27.x, golang.org/x/net 0.59.0, google.golang.org/grpc 1.84.0.

Compatibility notes

  • Build tag. Release assets are built with Go 1.27.1 and -tags http2legacy. Builds from source should use the same tag. Without it, Go 1.27's x/net HTTP/2 client opens one connection per waiting request while a TLS handshake hangs, so xmux.maxConnections no longer bounds XHTTP connections. The tag also keeps the H2MUX and MASQUE servers on x/net's own HTTP/2 server, as in Go 1.26 builds. Moving the XHTTP client to net/http.Transport so the tag can be dropped is planned separately.
  • REALITY. The client-version check stays outside the key-share change. minClientVer and maxClientVer remain optional operator settings with no implicit minimum. The HHMM stamp is display-only: REALITY still sends the three version bytes, now 26.10.5.
  • XDNS configuration changed upstream. domains entries take names, types and limits; resolvers entries take addrs. Update XDNS configurations, and run clients and servers from compatible versions.
  • udpHop is configured as a FinalMask UDP mask (udphop) instead of under quicParams. QuicParams protobuf field 5 is reserved.
  • WireGuard outbound. The remoteDNS "local" mode and domainStrategy were removed upstream.
  • FakeDNS. The default IPv6 pool changed upstream to 2001:2::/48.
  • Mux.Cool. Only TCP carriers start Mux.Cool, which matches every client implementation.
  • Mux.Cool over XHTTP. This is intentional fork behavior; upstream (XTLS#4128) discourages stacking it on XHTTP's own multiplexing. Server-side KeepAlive options:
    • xhttpSettings.muxKeepAliveSecs: a seconds range, e.g. "20-25".
    • xhttpSettings.muxKeepAliveBytes: a padding range, capped at 1024 bytes.
    • Both are off by default. stream-one is never poked, and only Xray clients use Mux.Cool.
    • When enabled, the server sends a small frame after each randomized idle gap. That pattern is visible as record timing outside TLS and to a TLS-terminating CDN.
    • Fields 30 and 31 of the splithttp Config protobuf are fork-owned.
  • Wire format. VLESS, Trojan, REALITY, Vision and SMUX wire bytes are unchanged.

Validation

All local gates ran on Linux/amd64 with Go 1.27.1 and GOFLAGS=-tags=http2legacy.

  • Release commit 57e9ec41, local gates:
    • vformat, protobuf-header check, go vet ./... and go test ./...;
    • race for REALITY, VLESS, SMUX, mux, Hysteria, MASQUE, XHTTP, XDNS and FinalMask;
    • checkptr for REALITY and VLESS;
    • version test (26.10.5-1858).
  • Process interoperability. An Xray server on the release commit was tested with Xray, sing-box and Mihomo clients:
    • VLESS TCP TLS/REALITY × no-flow/Vision 36/36 (three runs);
    • SMUX 24/24;
    • H2MUX 24/24;
    • Hysteria 3/3, plus Mux.Cool over Hysteria with carrier teardown;
    • Mux.Cool over XHTTP 6/6 (Xray clients only). A counting relay saw KeepAlive frames during a 3.5 s silence only with the option on and outside stream-one: 717 bytes versus 0.
  • Regression tests. Each fix has one, and each was observed failing before its fix:
    • Hysteria link lifetime and Mux.Cool framing;
    • Mux.Cool UDP carriers;
    • REALITY hellos without the hybrid group;
    • the XDNS bounds, prefix and resolver-close cases;
    • FinalMask invalid masks;
    • the MASQUE queue drain and ICMP bound;
    • the XHTTP single-dial check (16 waiting requests → 1 TCP connection);
    • the XHTTP Mux.Cool KeepAlive shutdown.
  • Pre-release Validation passed on 57e9ec41, with 529 tests passing and none failing:
    • repository-wide unit, race and checkptr;
    • SMUX and H2MUX matrices three times;
    • stress and reconnect profiles, and the hardening cycles;
    • the direct, legacy-mux, XUDP, reverse and WireGuard version-skew gates;
    • the candidate-versus-v26.8.25-1457 performance and resource budgets (three runs);
    • the RemnaNode configuration contract;
    • a 30-minute mixed-path soak (65 cycles).
  • Tests and Checkings passed on the same commit.
  • Release-flag Linux/amd64 build: static, -tags=http2legacy, GOAMD64=v1, CGO_ENABLED=0, -trimpath.
  • Code review. The upstream sync and fork fixes went through eight review rounds. The XHTTP Mux.Cool changes (#16 and its follow-up #18) went through two independent rounds plus review bots. Every finding was fixed, or answered with a written reason in the pull request.
  • These results are correctness and compatibility evidence. No performance improvement or traffic-camouflage gain is claimed.

Release assets

GitHub Actions had a major outage when this release was published, and release.yml could not get a hosted runner in two attempts. The six assets were therefore built on Linux/amd64 from the tag, with the same commands and inputs as release.yml:

  • Go 1.27.1, CGO_ENABLED=0, default GOAMD64=v1 / GOARM64=v8.0.
  • go build -tags http2legacy -trimpath -buildvcs=false -gcflags="all=-l=4" -ldflags="-X github.com/xtls/xray-core/core.build=v26.10.5-1858 -s -w -buildid=" ./main
  • Geodata from Loyalsoldier/v2ray-rules-dat, checked against its published SHA-256.
  • The same ZIP layout and .dgst format as earlier releases.

Binary SHA-256:

  • Xray-linux-64: f1f08963a7be97f0d37efb7df5f3af1f762ce3d1c63a5eb5b779aed8f9227a11
  • Xray-linux-arm64-v8a: 03eb450e50a46859cda1c5b5591d68acc34052f2a07d0b52bba3cf5fee07a9b1

The released amd64 binary also passed the VLESS 12/12, SMUX and XHTTP Mux.Cool process gates as both server and Xray client.

Verified against CI. After Actions recovered, release.yml ran on the tag without uploading. Its xray binaries for linux/amd64 and linux/arm64 are byte-identical to the released ones (same SHA-256 as above), and so are the geodata, README and LICENSE in the packages.

Don't miss a new Xray-core release

NewReleases is sending notifications on new releases.