mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-08-25 12:27:13 +00:00
fix(sub): keep Hysteria2 mport on external-proxy links
genHysteriaLink only looked up the UDP hop range on the no-endpoint path, after the externalProxy fan-out had already returned. An inbound with Hosts therefore emitted per-host links without mport, so clients pinned themselves to the single listening port and silently lost port hopping. Set the param before the fan-out so every endpoint inherits it, matching the frontend link builder and the Clash emitter. Closes #6264
This commit is contained in:
@@ -1209,6 +1209,12 @@ func (s *SubService) genHysteriaLink(inbound *model.Inbound, email string) strin
|
||||
protocol = "hysteria"
|
||||
}
|
||||
|
||||
// Set before the externalProxy fan-out: a Host overrides only the
|
||||
// address, so every endpoint inherits the inbound's UDP hop range.
|
||||
if hopPorts := hysteriaHopPorts(stream); hopPorts != "" {
|
||||
params["mport"] = hopPorts
|
||||
}
|
||||
|
||||
// Fan out one link per External Proxy entry if any. Previously this
|
||||
// generator ignored `externalProxy` entirely, so the link kept the
|
||||
// server's own IP/port even when the admin configured an alternate
|
||||
@@ -1238,9 +1244,6 @@ func (s *SubService) genHysteriaLink(inbound *model.Inbound, email string) strin
|
||||
|
||||
// No external proxy configured — use the inbound's resolved address so
|
||||
// node-managed inbounds get the node's host instead of the central panel's.
|
||||
if hopPorts := hysteriaHopPorts(stream); hopPorts != "" {
|
||||
params["mport"] = hopPorts
|
||||
}
|
||||
link := fmt.Sprintf("%s://%s@%s", protocol, auth, joinHostPort(s.resolveInboundAddress(inbound), inbound.Port))
|
||||
return buildLinkWithParams(link, params, s.genRemark(inbound, email, "", "quic"))
|
||||
}
|
||||
|
||||
@@ -1189,3 +1189,33 @@ func TestGenHysteriaLinkOmitsFinalMaskQueryParam(t *testing.T) {
|
||||
t.Fatalf("missing standard obfs-password: %s", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenHysteriaLinkKeepsHopPortsWithExternalProxy(t *testing.T) {
|
||||
stream := `{
|
||||
"security":"tls",
|
||||
"tlsSettings":{"serverName":"hy.sni"},
|
||||
"finalmask":{"quicParams":{"udpHop":{"ports":"20000-50000","interval":"5-10"}}},
|
||||
"externalProxy":[
|
||||
{"dest":"cdn.example.com","port":8443},
|
||||
{"dest":"2001:db8::10","port":9443}
|
||||
]
|
||||
}`
|
||||
in := &model.Inbound{
|
||||
Listen: "203.0.113.1",
|
||||
Port: 443,
|
||||
Protocol: model.Hysteria,
|
||||
Remark: "hy2",
|
||||
Settings: `{"version":2,"clients":[{"auth":"hyauth","email":"user"}]}`,
|
||||
StreamSettings: stream,
|
||||
}
|
||||
got := (&SubService{}).genHysteriaLink(in, "user")
|
||||
links := strings.Split(got, "\n")
|
||||
if len(links) != 2 {
|
||||
t.Fatalf("expected one link per external proxy, got %d: %q", len(links), got)
|
||||
}
|
||||
for _, link := range links {
|
||||
if !strings.Contains(link, "mport=20000-50000") {
|
||||
t.Fatalf("external-proxy link lost the UDP hop range: %s", link)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user