Conversation
…ession to clients
…server listeners The obfuscator wrappers (salamander/gecko for hysteria2, xplus for hysteria) hide the file descriptor from quic-go, and since sagernet/quic-go a7bffd4a quic-go no longer configures sockets it cannot reach through syscall.Conn. The listening socket therefore keeps the kernel default buffers (net.core.rmem_default, 208 KiB on Debian) and drops packets under bursty load. The client side already compensates by calling qtls.SetDesiredBufferSizes on the raw conn before wrapping it; do the same for the hysteria2 (plain and realm) and hysteria xplus server listeners, so they end up with the same 8 MiB buffers as a non-obfuscated listener.
realyxl
force-pushed
the
hysteria2-server-obfs-socket-buffer
branch
from
September 13, 2026 14:40
99ce6aa to
4fd0de4
Compare
nekohasekai
force-pushed
the
dev
branch
2 times, most recently
from
September 24, 2026 09:22
0c33e6f to
4f371c8
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When an obfuscator is enabled on the server side (Hysteria2
salamander/gecko, Hysteria v1xplus), the listening UDP socket keeps the kernel default buffers (net.core.rmem_default/wmem_default, 208 KiB on Debian) instead of the 8 MiB that quic-go is meant to configure. Under bursty traffic the receive buffer overflows in the kernel and packets are dropped before quic-go ever sees them.Measured on sing-box 1.14.0 (Debian 13,
net.core.rmem_max = 16777216), hysteria2 inbound with salamander:ss -ulnmshowsrb212992 tb212992for the listener, and the socket drop counter (dinss -m, matchingUdpRcvbufErrors) grew by 1 500–7 000 during each 10 s, ~450 Mbit/s download test.Root cause
Service.Startwraps the raw*net.UDPConnwith the obfuscator before passing it to quic-go. The wrappers only exposeReadFrom/WriteTo/Upstream, so quic-go cannot reach the file descriptor. Since sagernet/quic-go a7bffd4a (v0.61.0-sing-box-mod.2),wrapConnprobessyscall.Connonly and otherwise returnsbasicConnwithout touching any socket option — by design: "the socket behind a non-syscall conn is expected to have been configured by its owner".The owner is sing-quic. The client side already handles this:
hysteria2/client.goandhysteria/client.gocallqtls.SetDesiredBufferSizes(rawConn)whenever obfs is enabled, before wrapping. The server side never did.Fix
Call
qtls.SetDesiredBufferSizeson the raw listener conn before wrapping it, under the same condition as the client:hysteria2.Service.StartandstartWithRealm(PunchPacketConnalready forwardsSetReadBuffer/SetWriteBuffer)hysteria.Service.Start(xplus)Listeners without obfs are unchanged: quic-go keeps configuring them itself through the file descriptor. GSO/ECN/batch I/O remain unavailable with obfs as before; this only restores the buffer sizing.
Verification
Same host, three temporary hysteria2 listeners,
ss -ulnm:With the patch an obfuscated listener ends up with exactly the same socket buffers as a non-obfuscated one.
Supersedes #17, which added
SetReadBuffer/SetWriteBufferto the wrapper types; that stopped having any effect once quic-go stopped probing those methods.