Add hysteria2 port hopping and certificate pinning#110
Merged
Conversation
Two hysteria2 features fall out of shared-link/Clash parameters that were previously dropped on import: mport / Clash "ports" (port hopping) and pinSHA256 / Clash "fingerprint" (certificate pin). - Port hopping folds into finalmask.quicParams.udpHop, following the same fold-in/lift-out pattern as the existing salamander obfs support (FinalmaskJson.Add/TakeHysteria2UdpHop). Share links round-trip the port range back out as mport=; a hand-tuned hop the writer wouldn't have produced itself is preserved verbatim in fm= instead of being silently rewritten. - Certificate pinning is a new ServerEntry.PinnedPeerCertSha256 field mapping to tlsSettings.pinnedPeerCertSha256 in the shared TLS builder (BuildTlsSettings), so it applies to every TLS outbound (trojan/vless/vmess), not just hysteria2 as first implemented - verified against the shipped xray core, which validates the pin identically regardless of protocol. Not applicable to REALITY, which has no tlsSettings. The edit dialog clears the field whenever the current config can't produce a tlsSettings block, mirroring the existing ECH cleanup rule. - Fixed a bug where hysteria2's own URI form (host:port-range in the address, e.g. "host:35000-39000") threw inside `new Uri()` and caused the whole node to silently vanish on import. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 332d75c480
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Owner
Author
|
@codex address that feedback |
|
To use Codex here, create an environment for this repo. |
Gate PinnedPeerCertSha256 cleanup on protocol AND security, not Security alone. ss shares the same Security combobox as vmess/vless/trojan for row-visibility purposes, but BuildSsOutbound never reads Security — so a leftover "tls" selection from before switching to ss went untouched by the previous check, and would silently reapply the stale pin if the entry was later switched back to a real TLS protocol pointing at a different server. Addresses Codex review comment on PR #110. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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.
Summary
mport=(share links) and Clash'sports:fold intofinalmask.quicParams.udpHop, following the same fold-in/lift-out pattern already used for salamander obfs. Share links round-trip the range back out asmport=; a hand-tuned hop the writer wouldn't have produced itself is preserved verbatim infm=instead of being silently rewritten (aCount == 2 && interval == "30"shape check, not a loose key-count guess — a looser check would have invented anintervalvalue on re-import that the original author never wrote).ServerEntry.PinnedPeerCertSha256→tlsSettings.pinnedPeerCertSha256, wired into the sharedBuildTlsSettingshelper so it applies to every TLS outbound (trojan/vless/vmess), not just hysteria2. Verified against the shipped xray core (xray.exe run -test) that the pin validates identically regardless of protocol — a short/malformed pin is rejected by the core's own length check on every protocol tested. Not applicable to REALITY (notlsSettings); the edit dialog clears the field whenever the current config can't produce one, mirroring the existing ECH cleanup rule.host:35000-39000port range in the address) threw insidenew Uri()and silently dropped the whole node on import — no error, the node just never showed up.Test plan
dotnet test XrayUI.Tests/XrayUI.Tests.csproj -c Release— 65/65 passing, including round-trip coverage for: mport + pin together, a non-canonical hand-tuned udpHop (interval != "30"), and a hand-written udpHop missingintervalentirely (regression guard for the fold/lift shape check — confirmed this test fails against a looserCount-based check before the fix).dotnet build(BuildAndRun.ps1) — clean, x64 Debug.Assets/engine/xray.exeviarun -test: hysteria2 with pin + udpHop + brutal congestion, vless+ws+tls with pin, and trojan with pin — allConfiguration OK; negative controls (truncated pin, short pin) correctly rejected withincorrect pinnedPeerCertSha256 length.xray -testconfig validation.🤖 Generated with Claude Code