mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-07-21 03:56:07 +00:00
feat(inbound): Advanced XHTTP and external TLS proxy settings (#4491)
* ✨ Introduce extended XHTTP and external proxy settings * ✨ Add custom SNI for proxy * ✨ Add previous changes into React version of app * fix(sub): isolate per-proxy tlsSettings during external-proxy iteration cloneMap (Clash) is shallow and `newStream := stream` (JSON) is an alias, so tlsSettings was shared across iterations. The new applyExternalProxyTLSToStream mutates it, leaking one proxy's serverName/fingerprint/alpn into the next (only overwritten when the next proxy explicitly sets the same field). Add cloneStreamForExternalProxy: shallow clones the top-level stream plus deep clones tlsSettings and tlsSettings.settings. Regression test locks in that proxy B does not inherit proxy A's fingerprint/alpn when B leaves them unset.
This commit is contained in:
+18
-2
@@ -122,7 +122,8 @@ func (s *SubClashService) getProxies(inbound *model.Inbound, client model.Client
|
||||
defaultDest = host
|
||||
}
|
||||
externalProxies, ok := stream["externalProxy"].([]any)
|
||||
if !ok || len(externalProxies) == 0 {
|
||||
hasExternalProxy := ok && len(externalProxies) > 0
|
||||
if !hasExternalProxy {
|
||||
externalProxies = []any{map[string]any{
|
||||
"forceTls": "same",
|
||||
"dest": defaultDest,
|
||||
@@ -138,7 +139,7 @@ func (s *SubClashService) getProxies(inbound *model.Inbound, client model.Client
|
||||
workingInbound := *inbound
|
||||
workingInbound.Listen = extPrxy["dest"].(string)
|
||||
workingInbound.Port = int(extPrxy["port"].(float64))
|
||||
workingStream := cloneMap(stream)
|
||||
workingStream := cloneStreamForExternalProxy(stream)
|
||||
|
||||
switch extPrxy["forceTls"].(string) {
|
||||
case "tls":
|
||||
@@ -153,6 +154,10 @@ func (s *SubClashService) getProxies(inbound *model.Inbound, client model.Client
|
||||
delete(workingStream, "realitySettings")
|
||||
}
|
||||
}
|
||||
security, _ := workingStream["security"].(string)
|
||||
if hasExternalProxy {
|
||||
applyExternalProxyTLSToStream(extPrxy, workingStream, security)
|
||||
}
|
||||
|
||||
proxy := s.buildProxy(&workingInbound, client, workingStream, extPrxy["remark"].(string))
|
||||
if len(proxy) > 0 {
|
||||
@@ -383,6 +388,17 @@ func (s *SubClashService) applySecurity(proxy map[string]any, security string, s
|
||||
if fingerprint, ok := tlsSettings["fingerprint"].(string); ok && fingerprint != "" {
|
||||
proxy["client-fingerprint"] = fingerprint
|
||||
}
|
||||
if alpn, ok := externalProxyALPNList(tlsSettings["alpn"]); ok {
|
||||
out := make([]string, 0, len(alpn))
|
||||
for _, item := range alpn {
|
||||
if s, ok := item.(string); ok && s != "" {
|
||||
out = append(out, s)
|
||||
}
|
||||
}
|
||||
if len(out) > 0 {
|
||||
proxy["alpn"] = out
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
case "reality":
|
||||
|
||||
Reference in New Issue
Block a user