This commit is contained in:
Nikita Nemirovsky 2026-04-02 04:07:17 +00:00 committed by GitHub
commit 3aa4ac1684
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 84 additions and 54 deletions

View file

@ -435,34 +435,37 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string {
} }
} }
// Extract Reality params unconditionally so they're available when
// externalProxy overrides security to "reality" via forceTls.
realitySetting, _ := stream["realitySettings"].(map[string]any)
realitySettings, _ := searchKey(realitySetting, "settings")
if realitySetting != nil {
if sniValue, ok := searchKey(realitySetting, "serverNames"); ok {
sNames, _ := sniValue.([]any)
params["sni"] = sNames[random.Num(len(sNames))].(string)
}
if pbkValue, ok := searchKey(realitySettings, "publicKey"); ok {
params["pbk"], _ = pbkValue.(string)
}
if sidValue, ok := searchKey(realitySetting, "shortIds"); ok {
shortIds, _ := sidValue.([]any)
params["sid"] = shortIds[random.Num(len(shortIds))].(string)
}
if fpValue, ok := searchKey(realitySettings, "fingerprint"); ok {
if fp, ok := fpValue.(string); ok && len(fp) > 0 {
params["fp"] = fp
}
}
if pqvValue, ok := searchKey(realitySettings, "mldsa65Verify"); ok {
if pqv, ok := pqvValue.(string); ok && len(pqv) > 0 {
params["pqv"] = pqv
}
}
params["spx"] = "/" + random.Seq(15)
}
if security == "reality" { if security == "reality" {
params["security"] = "reality" params["security"] = "reality"
realitySetting, _ := stream["realitySettings"].(map[string]any)
realitySettings, _ := searchKey(realitySetting, "settings")
if realitySetting != nil {
if sniValue, ok := searchKey(realitySetting, "serverNames"); ok {
sNames, _ := sniValue.([]any)
params["sni"] = sNames[random.Num(len(sNames))].(string)
}
if pbkValue, ok := searchKey(realitySettings, "publicKey"); ok {
params["pbk"], _ = pbkValue.(string)
}
if sidValue, ok := searchKey(realitySetting, "shortIds"); ok {
shortIds, _ := sidValue.([]any)
params["sid"] = shortIds[random.Num(len(shortIds))].(string)
}
if fpValue, ok := searchKey(realitySettings, "fingerprint"); ok {
if fp, ok := fpValue.(string); ok && len(fp) > 0 {
params["fp"] = fp
}
}
if pqvValue, ok := searchKey(realitySettings, "mldsa65Verify"); ok {
if pqv, ok := pqvValue.(string); ok && len(pqv) > 0 {
params["pqv"] = pqv
}
}
params["spx"] = "/" + random.Seq(15)
}
if streamNetwork == "tcp" && len(clients[clientIndex].Flow) > 0 { if streamNetwork == "tcp" && len(clients[clientIndex].Flow) > 0 {
params["flow"] = clients[clientIndex].Flow params["flow"] = clients[clientIndex].Flow
@ -489,6 +492,14 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string {
} else { } else {
params["security"] = security params["security"] = security
} }
// Allow externalProxy to override SNI (useful when the
// inbound has extra serverNames for fallback routing that
// should not appear in subscription links).
if sni, ok := ep["sni"].(string); ok && len(sni) > 0 {
params["sni"] = sni
}
url, _ := url.Parse(link) url, _ := url.Parse(link)
q := url.Query() q := url.Query()
@ -627,34 +638,37 @@ func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string
} }
} }
// Extract Reality params unconditionally so they're available when
// externalProxy overrides security to "reality" via forceTls.
realitySetting, _ := stream["realitySettings"].(map[string]any)
realitySettings, _ := searchKey(realitySetting, "settings")
if realitySetting != nil {
if sniValue, ok := searchKey(realitySetting, "serverNames"); ok {
sNames, _ := sniValue.([]any)
params["sni"] = sNames[random.Num(len(sNames))].(string)
}
if pbkValue, ok := searchKey(realitySettings, "publicKey"); ok {
params["pbk"], _ = pbkValue.(string)
}
if sidValue, ok := searchKey(realitySetting, "shortIds"); ok {
shortIds, _ := sidValue.([]any)
params["sid"] = shortIds[random.Num(len(shortIds))].(string)
}
if fpValue, ok := searchKey(realitySettings, "fingerprint"); ok {
if fp, ok := fpValue.(string); ok && len(fp) > 0 {
params["fp"] = fp
}
}
if pqvValue, ok := searchKey(realitySettings, "mldsa65Verify"); ok {
if pqv, ok := pqvValue.(string); ok && len(pqv) > 0 {
params["pqv"] = pqv
}
}
params["spx"] = "/" + random.Seq(15)
}
if security == "reality" { if security == "reality" {
params["security"] = "reality" params["security"] = "reality"
realitySetting, _ := stream["realitySettings"].(map[string]any)
realitySettings, _ := searchKey(realitySetting, "settings")
if realitySetting != nil {
if sniValue, ok := searchKey(realitySetting, "serverNames"); ok {
sNames, _ := sniValue.([]any)
params["sni"] = sNames[random.Num(len(sNames))].(string)
}
if pbkValue, ok := searchKey(realitySettings, "publicKey"); ok {
params["pbk"], _ = pbkValue.(string)
}
if sidValue, ok := searchKey(realitySetting, "shortIds"); ok {
shortIds, _ := sidValue.([]any)
params["sid"] = shortIds[random.Num(len(shortIds))].(string)
}
if fpValue, ok := searchKey(realitySettings, "fingerprint"); ok {
if fp, ok := fpValue.(string); ok && len(fp) > 0 {
params["fp"] = fp
}
}
if pqvValue, ok := searchKey(realitySettings, "mldsa65Verify"); ok {
if pqv, ok := pqvValue.(string); ok && len(pqv) > 0 {
params["pqv"] = pqv
}
}
params["spx"] = "/" + random.Seq(15)
}
if streamNetwork == "tcp" && len(clients[clientIndex].Flow) > 0 { if streamNetwork == "tcp" && len(clients[clientIndex].Flow) > 0 {
params["flow"] = clients[clientIndex].Flow params["flow"] = clients[clientIndex].Flow
@ -681,6 +695,14 @@ func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string
} else { } else {
params["security"] = security params["security"] = security
} }
// Allow externalProxy to override SNI (useful when the
// inbound has extra serverNames for fallback routing that
// should not appear in subscription links).
if sni, ok := ep["sni"].(string); ok && len(sni) > 0 {
params["sni"] = sni
}
url, _ := url.Parse(link) url, _ := url.Parse(link)
q := url.Query() q := url.Query()
@ -848,6 +870,14 @@ func (s *SubService) genShadowsocksLink(inbound *model.Inbound, email string) st
} else { } else {
params["security"] = security params["security"] = security
} }
// Allow externalProxy to override SNI (useful when the
// inbound has extra serverNames for fallback routing that
// should not appear in subscription links).
if sni, ok := ep["sni"].(string); ok && len(sni) > 0 {
params["sni"] = sni
}
url, _ := url.Parse(link) url, _ := url.Parse(link)
q := url.Query() q := url.Query()

View file

@ -1738,7 +1738,7 @@ class Inbound extends XrayCommonClass {
'o': '', 'o': '',
}; };
if (ObjectUtil.isArrEmpty(this.stream.externalProxy)) { if (ObjectUtil.isArrEmpty(this.stream.externalProxy)) {
let r = orderChars.split('').map(char => orders[char]).filter(x => x.length > 0).join(separationChar); let r = orderChars.split('').map(char => orders[char]).filter(x => x && x.length > 0).join(separationChar);
result.push({ result.push({
remark: r, remark: r,
link: this.genLink(addr, port, 'same', r, client) link: this.genLink(addr, port, 'same', r, client)
@ -1746,7 +1746,7 @@ class Inbound extends XrayCommonClass {
} else { } else {
this.stream.externalProxy.forEach((ep) => { this.stream.externalProxy.forEach((ep) => {
orders['o'] = ep.remark; orders['o'] = ep.remark;
let r = orderChars.split('').map(char => orders[char]).filter(x => x.length > 0).join(separationChar); let r = orderChars.split('').map(char => orders[char]).filter(x => x && x.length > 0).join(separationChar);
result.push({ result.push({
remark: r, remark: r,
link: this.genLink(ep.dest, ep.port, ep.forceTls, r, client) link: this.genLink(ep.dest, ep.port, ep.forceTls, r, client)