fix(sub): stop the subscription from 500ing on valid-but-unusual stream settings

The raw share-link generators used unchecked type assertions and unguarded
array indexing: an empty Reality shortIds/serverNames array (random.Num(0)
panics), a tcp-http header with no request block or an empty request.path, a
grpc block missing its keys, empty stream settings, and a non-string Host
header all panicked mid-generation. Because getSubs loops every client's link
with no recover, one such client 500s the entire subscription for everyone. The
sibling JSON, Clash and frontend generators already guard these; make the raw
generators match with comma-ok assertions and length checks.
This commit is contained in:
MHSanaei
2026-07-15 02:36:15 +02:00
parent e4d4ab3a63
commit abab7cd000
2 changed files with 72 additions and 22 deletions
+29 -22
View File
@@ -781,7 +781,7 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string {
}
uuid := client.ID
port := inbound.Port
streamNetwork := stream["network"].(string)
streamNetwork, _ := stream["network"].(string)
params := make(map[string]string)
params["type"] = streamNetwork
@@ -840,7 +840,7 @@ func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string
}
password := encodeUserinfo(client.Password)
port := inbound.Port
streamNetwork := stream["network"].(string)
streamNetwork, _ := stream["network"].(string)
params := make(map[string]string)
params["type"] = streamNetwork
@@ -913,9 +913,9 @@ func (s *SubService) genShadowsocksLink(inbound *model.Inbound, email string) st
}
settings := s.linkSettings(inbound)
inboundPassword := settings["password"].(string)
method := settings["method"].(string)
streamNetwork := stream["network"].(string)
inboundPassword, _ := settings["password"].(string)
method, _ := settings["method"].(string)
streamNetwork, _ := stream["network"].(string)
params := make(map[string]string)
params["type"] = streamNetwork
@@ -1206,9 +1206,11 @@ func applyShareNetworkParams(stream map[string]any, streamNetwork string, params
header, _ := tcp["header"].(map[string]any)
typeStr, _ := header["type"].(string)
if typeStr == "http" {
request := header["request"].(map[string]any)
request, _ := header["request"].(map[string]any)
requestPath, _ := request["path"].([]any)
params["path"] = requestPath[0].(string)
if len(requestPath) > 0 {
params["path"], _ = requestPath[0].(string)
}
host := ""
if response, ok := header["response"].(map[string]any); ok {
if respHeaders, ok := response["headers"].(map[string]any); ok {
@@ -1229,9 +1231,9 @@ func applyShareNetworkParams(stream map[string]any, streamNetwork string, params
applyPathAndHostParams(ws, params)
case "grpc":
grpc, _ := stream["grpcSettings"].(map[string]any)
params["serviceName"] = grpc["serviceName"].(string)
params["serviceName"], _ = grpc["serviceName"].(string)
params["authority"], _ = grpc["authority"].(string)
if grpc["multiMode"].(bool) {
if mm, _ := grpc["multiMode"].(bool); mm {
params["mode"] = "multi"
}
case "httpupgrade":
@@ -1262,9 +1264,11 @@ func applyVmessNetworkParams(stream map[string]any, network string, obj map[stri
typeStr, _ := header["type"].(string)
obj["type"] = typeStr
if typeStr == "http" {
request := header["request"].(map[string]any)
request, _ := header["request"].(map[string]any)
requestPath, _ := request["path"].([]any)
obj["path"] = requestPath[0].(string)
if len(requestPath) > 0 {
obj["path"], _ = requestPath[0].(string)
}
host := ""
if response, ok := header["response"].(map[string]any); ok {
if respHeaders, ok := response["headers"].(map[string]any); ok {
@@ -1284,9 +1288,9 @@ func applyVmessNetworkParams(stream map[string]any, network string, obj map[stri
applyPathAndHostObj(ws, obj)
case "grpc":
grpc, _ := stream["grpcSettings"].(map[string]any)
obj["path"] = grpc["serviceName"].(string)
obj["authority"] = grpc["authority"].(string)
if grpc["multiMode"].(bool) {
obj["path"], _ = grpc["serviceName"].(string)
obj["authority"], _ = grpc["authority"].(string)
if mm, _ := grpc["multiMode"].(bool); mm {
obj["type"] = "multi"
}
case "httpupgrade":
@@ -1451,15 +1455,17 @@ func applyShareRealityParams(stream map[string]any, params map[string]string, cl
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 sNames, _ := sniValue.([]any); len(sNames) > 0 {
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 shortIds, _ := sidValue.([]any); len(shortIds) > 0 {
params["sid"], _ = shortIds[random.Num(len(shortIds))].(string)
}
}
if fpValue, ok := searchKey(realitySettings, "fingerprint"); ok {
if fp, ok := fpValue.(string); ok && len(fp) > 0 {
@@ -2422,12 +2428,13 @@ func searchHost(headers any) string {
case []any:
hosts, _ := v.([]any)
if len(hosts) > 0 {
return hosts[0].(string)
} else {
return ""
h, _ := hosts[0].(string)
return h
}
return ""
case any:
return v.(string)
h, _ := v.(string)
return h
}
}
}