feat: native Hysteria2 Gecko obfs (drop the sidecar)#26
Conversation
Hysteria2 Gecko obfuscation now runs through the native sing-box core (via the hawkff/sing-quic gecko backport) instead of the bundled apernet/hysteria binary sidecar. - HysteriaFmt: emit obfs.type=gecko + min/max packet size for Gecko profiles; canUseSingBox() no longer forces Gecko onto the external sidecar path. - SingBoxOptions.Hysteria2Obfs: add min_packet_size / max_packet_size (flattened into the obfs object by the core's serializer). - buildScript: point COMMIT_SING_BOX at the gecko-enabled sing-box (d003dcc). - libcore go.mod: pin sing-quic to the hawkff fork gecko backport. Verified end-to-end on Android: native Gecko Hysteria2 outbound (no sidecar) connects, egress confirmed.
📝 WalkthroughWalkthroughThis PR removes the Hysteria2 Gecko sidecar dependency by enabling native sing-box support. ChangesNative Gecko Obfs for Hysteria2
Dependency and Build Updates
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
Comment |
|
@coderabbitai review |
✅ Action performedReview finished.
|
The native sing-box Gecko path passed user-supplied min/max packet sizes directly; an inverted or out-of-range pair (e.g. min=1500, max=800) would be rejected by the core at connect time. Clamp to 1..2048 and enforce min <= max, matching the sidecar config builder's existing bounds. (Greptile P1)
Since Gecko now runs natively (canUseSingBox() == true for all UDP Hysteria2), the OBFS_GECKO sidecar branches in BoxInstance init/launch are unreachable. Remove them (the external path is Hysteria v1 only) and drop the now-unused buildHysteria2SidecarConfig import. Correct the buildHysteria2SidecarConfig KDoc which still claimed Gecko needs the sidecar. (Greptile)
|
Addressed both items from the latest review in a9e4943:
|
# Conflicts: # app/src/main/java/io/nekohasekai/sagernet/bg/proto/BoxInstance.kt
Summary
Hysteria2 Gecko obfuscation now runs through the native sing-box core instead of the bundled
apernet/hysteriabinary sidecar — fewer moving parts, no subprocess/SOCKS hop, and direct sing-box routing.Changes
HysteriaFmt.kt: emitobfs.type=geckowithmin_packet_size/max_packet_sizefor Gecko profiles;canUseSingBox()no longer forces Gecko onto the external sidecar path.SingBoxOptions.Hysteria2Obfs: addmin_packet_size/max_packet_size(flattened into theobfsobject by the core's serializer).buildScript/lib/core/get_source_env.sh: pointCOMMIT_SING_BOXat the gecko-enabled sing-box (d003dcc).libcore/go.mod: pin sing-quic to the hawkff fork gecko backport.Native dependency chain
Verification
Salamander and no-obfs Hysteria2 behavior is unchanged.
Greptile Summary
This PR migrates Hysteria2 Gecko obfuscation from an external sidecar binary (apernet/hysteria + SOCKS5 hop) to the native sing-box core, by wiring in the hawkff/sing-quic gecko backport. The result is one fewer subprocess, no loopback SOCKS hop, and direct sing-box routing for Gecko profiles.
HysteriaFmt.kt:canUseSingBox()no longer short-circuits on Gecko;buildSingBoxOutboundHysteriaBeannow emits atype = \"gecko\"obfs block with clampedmin_packet_size/max_packet_size(1–2048, min ≤ max).BoxInstance.kt: The Gecko sidecar launch path and itsbuildHysteria2SidecarConfigcall are removed; the external-path HysteriaBean handler is now Hysteria v1–only, which is correct since v2 no longer requires the sidecar.go.mod/go.sum:sagernet/sing-quicreplaced with thehawkff/sing-quicgecko fork;COMMIT_SING_BOXupdated to the matching gecko-enabled core.Confidence Score: 5/5
Safe to merge — the sidecar removal is clean, the native gecko path is correctly wired, and bounds clamping is in place.
The change is well-scoped: canUseSingBox() loses one guard, the sing-box outbound builder gains a gecko branch with correct min/max clamping (1–2048, min ≤ max), and the sidecar launch code is deleted entirely. Salamander and no-obfs Hysteria2 paths are untouched. The go.mod replace directive and updated COMMIT_SING_BOX are consistent with the claimed dependency chain. No logic errors found in the changed paths.
No files require special attention.
Important Files Changed
Sequence Diagram
%%{init: {'theme': 'neutral'}}%% sequenceDiagram participant App as Android App participant SB as sing-box core participant SQ as sing-quic (hawkff fork) participant Srv as Hysteria2 Server Note over App,Srv: Before PR - Gecko via sidecar App->>App: canUseSingBox() returns false (Gecko) App->>App: launch hysteria2-plugin binary App->>App: sing-box socks outbound to 127.0.0.1:port App-->>Srv: SOCKS5 hop Gecko QUIC Note over App,Srv: After PR - Gecko native App->>App: canUseSingBox() returns true (Gecko) App->>SB: "buildSingBoxOutboundHysteriaBean() obfs type=gecko" SB->>SQ: Gecko obfuscator (backport) SQ-->>Srv: Direct Gecko QUIC (no subprocess)%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%% sequenceDiagram participant App as Android App participant SB as sing-box core participant SQ as sing-quic (hawkff fork) participant Srv as Hysteria2 Server Note over App,Srv: Before PR - Gecko via sidecar App->>App: canUseSingBox() returns false (Gecko) App->>App: launch hysteria2-plugin binary App->>App: sing-box socks outbound to 127.0.0.1:port App-->>Srv: SOCKS5 hop Gecko QUIC Note over App,Srv: After PR - Gecko native App->>App: canUseSingBox() returns true (Gecko) App->>SB: "buildSingBoxOutboundHysteriaBean() obfs type=gecko" SB->>SQ: Gecko obfuscator (backport) SQ-->>Srv: Direct Gecko QUIC (no subprocess)Comments Outside Diff (1)
app/src/main/java/io/nekohasekai/sagernet/fmt/hysteria/HysteriaFmt.kt, line 413-414 (link)buildHysteria2SidecarConfigstill states that Gecko obfs is a reason the function is called — "used for Hysteria2 profiles with Gecko obfs (which the native sing-box core can't do)" — which is now the opposite of the truth. This dead-code comment will mislead anyone tracing the sidecar code path later.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Reviews (5): Last reviewed commit: "Merge remote-tracking branch 'origin/mai..." | Re-trigger Greptile