From 5fbf8f0d535b131ad6de22a0d1dda0f2167d5ee0 Mon Sep 17 00:00:00 2001 From: Alireza Ahmadi Date: Fri, 8 Dec 2023 18:45:21 +0100 Subject: Expand multiDomain to externalProxy #1300 --- sub/subService.go | 288 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 191 insertions(+), 97 deletions(-) (limited to 'sub') diff --git a/sub/subService.go b/sub/subService.go index 23fad299..a1cbbb0f 100644 --- a/sub/subService.go +++ b/sub/subService.go @@ -53,6 +53,7 @@ func (s *SubService) GetSubs(subId string, host string, showInfo bool) ([]string json.Unmarshal([]byte(fallbackMaster.StreamSettings), &masterStream) stream["security"] = masterStream["security"] stream["tlsSettings"] = masterStream["tlsSettings"] + stream["externalProxy"] = masterStream["externalProxy"] modifiedStream, _ := json.MarshalIndent(stream, "", " ") inbound.StreamSettings = string(modifiedStream) } @@ -96,7 +97,14 @@ func (s *SubService) GetSubs(subId string, host string, showInfo bool) ([]string func (s *SubService) getInboundsBySubId(subId string) ([]*model.Inbound, error) { db := database.GetDB() var inbounds []*model.Inbound - err := db.Model(model.Inbound{}).Preload("ClientStats").Where("settings like ? and enable = ?", fmt.Sprintf(`%%"subId": "%s"%%`, subId), true).Find(&inbounds).Error + err := db.Model(model.Inbound{}).Preload("ClientStats").Where(`id in ( + SELECT DISTINCT inbounds.id + FROM inbounds, + JSON_EACH(JSON_EXTRACT(inbounds.settings, '$.clients')) AS client + WHERE + protocol in ('vmess','vless','trojan','shadowsocks') + AND JSON_EXTRACT(client.value, '$.subId') = ? AND enable = ? + )`, subId, true).Find(&inbounds).Error if err != nil { return nil, err } @@ -196,7 +204,6 @@ func (s *SubService) genVmessLink(inbound *model.Inbound, email string) string { } security, _ := stream["security"].(string) - var domains []interface{} obj["tls"] = security if security == "tls" { tlsSetting, _ := stream["tlsSettings"].(map[string]interface{}) @@ -208,24 +215,18 @@ func (s *SubService) genVmessLink(inbound *model.Inbound, email string) string { } obj["alpn"] = strings.Join(alpn, ",") } + if sniValue, ok := searchKey(tlsSetting, "serverName"); ok { + obj["sni"], _ = sniValue.(string) + } + tlsSettings, _ := searchKey(tlsSetting, "settings") if tlsSetting != nil { - if sniValue, ok := searchKey(tlsSettings, "serverName"); ok { - obj["sni"], _ = sniValue.(string) - } if fpValue, ok := searchKey(tlsSettings, "fingerprint"); ok { obj["fp"], _ = fpValue.(string) } if insecure, ok := searchKey(tlsSettings, "allowInsecure"); ok { obj["allowInsecure"], _ = insecure.(bool) } - if domainSettings, ok := searchKey(tlsSettings, "domains"); ok { - domains, _ = domainSettings.([]interface{}) - } - } - serverName, _ := tlsSetting["serverName"].(string) - if serverName != "" { - obj["add"] = serverName } } @@ -239,16 +240,30 @@ func (s *SubService) genVmessLink(inbound *model.Inbound, email string) string { } obj["id"] = clients[clientIndex].ID - if len(domains) > 0 { + externalProxies, _ := stream["externalProxy"].([]interface{}) + + if len(externalProxies) > 0 { links := "" - for index, d := range domains { - domain := d.(map[string]interface{}) - obj["ps"] = s.genRemark(inbound, email, domain["remark"].(string)) - obj["add"] = domain["domain"].(string) + for index, externalProxy := range externalProxies { + ep, _ := externalProxy.(map[string]interface{}) + newSecurity, _ := ep["forceTls"].(string) + newObj := map[string]interface{}{} + for key, value := range obj { + if !(newSecurity == "none" && (key == "alpn" || key == "sni" || key == "fp" || key == "allowInsecure")) { + newObj[key] = value + } + } + newObj["ps"] = s.genRemark(inbound, email, ep["remark"].(string)) + newObj["add"] = ep["dest"].(string) + newObj["port"] = int(ep["port"].(float64)) + + if newSecurity != "same" { + newObj["tls"] = newSecurity + } if index > 0 { links += "\n" } - jsonStr, _ := json.MarshalIndent(obj, "", " ") + jsonStr, _ := json.MarshalIndent(newObj, "", " ") links += "vmess://" + base64.StdEncoding.EncodeToString(jsonStr) } return links @@ -323,7 +338,6 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string { } security, _ := stream["security"].(string) - var domains []interface{} if security == "tls" { params["security"] = "tls" tlsSetting, _ := stream["tlsSettings"].(map[string]interface{}) @@ -335,11 +349,12 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string { if len(alpn) > 0 { params["alpn"] = strings.Join(alpn, ",") } + if sniValue, ok := searchKey(tlsSetting, "serverName"); ok { + params["sni"], _ = sniValue.(string) + } + tlsSettings, _ := searchKey(tlsSetting, "settings") if tlsSetting != nil { - if sniValue, ok := searchKey(tlsSettings, "serverName"); ok { - params["sni"], _ = sniValue.(string) - } if fpValue, ok := searchKey(tlsSettings, "fingerprint"); ok { params["fp"], _ = fpValue.(string) } @@ -348,19 +363,11 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string { params["allowInsecure"] = "1" } } - if domainSettings, ok := searchKey(tlsSettings, "domains"); ok { - domains, _ = domainSettings.([]interface{}) - } } if streamNetwork == "tcp" && len(clients[clientIndex].Flow) > 0 { params["flow"] = clients[clientIndex].Flow } - - serverName, _ := tlsSetting["serverName"].(string) - if serverName != "" { - address = serverName - } } if security == "reality" { @@ -389,11 +396,6 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string { params["spx"] = spx } } - if serverName, ok := searchKey(realitySettings, "serverName"); ok { - if sname, ok := serverName.(string); ok && len(sname) > 0 { - address = sname - } - } } if streamNetwork == "tcp" && len(clients[clientIndex].Flow) > 0 { @@ -412,7 +414,9 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string { if len(alpn) > 0 { params["alpn"] = strings.Join(alpn, ",") } - + if sniValue, ok := searchKey(xtlsSetting, "serverName"); ok { + params["sni"], _ = sniValue.(string) + } xtlsSettings, _ := searchKey(xtlsSetting, "settings") if xtlsSetting != nil { if fpValue, ok := searchKey(xtlsSettings, "fingerprint"); ok { @@ -423,42 +427,47 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string { params["allowInsecure"] = "1" } } - if sniValue, ok := searchKey(xtlsSettings, "serverName"); ok { - params["sni"], _ = sniValue.(string) - } } if streamNetwork == "tcp" && len(clients[clientIndex].Flow) > 0 { params["flow"] = clients[clientIndex].Flow } - - serverName, _ := xtlsSetting["serverName"].(string) - if serverName != "" { - address = serverName - } } if security != "tls" && security != "reality" && security != "xtls" { params["security"] = "none" } - link := fmt.Sprintf("vless://%s@%s:%d", uuid, address, port) - url, _ := url.Parse(link) - q := url.Query() + externalProxies, _ := stream["externalProxy"].([]interface{}) - for k, v := range params { - q.Add(k, v) - } + if len(externalProxies) > 0 { + links := "" + for index, externalProxy := range externalProxies { + ep, _ := externalProxy.(map[string]interface{}) + newSecurity, _ := ep["forceTls"].(string) + dest, _ := ep["dest"].(string) + port := int(ep["port"].(float64)) + link := fmt.Sprintf("vless://%s@%s:%d", uuid, dest, port) + + if newSecurity != "same" { + params["security"] = newSecurity + } else { + params["security"] = security + } + url, _ := url.Parse(link) + q := url.Query() - // Set the new query values on the URL - url.RawQuery = q.Encode() + for k, v := range params { + if !(newSecurity == "none" && (k == "alpn" || k == "sni" || k == "fp" || k == "allowInsecure")) { + q.Add(k, v) + } + } + + // Set the new query values on the URL + url.RawQuery = q.Encode() + + url.Fragment = s.genRemark(inbound, email, ep["remark"].(string)) - if len(domains) > 0 { - links := "" - for index, d := range domains { - domain := d.(map[string]interface{}) - url.Fragment = s.genRemark(inbound, email, domain["remark"].(string)) - url.Host = fmt.Sprintf("%s:%d", domain["domain"].(string), port) if index > 0 { links += "\n" } @@ -467,6 +476,17 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string { return links } + link := fmt.Sprintf("vless://%s@%s:%d", uuid, address, port) + url, _ := url.Parse(link) + q := url.Query() + + for k, v := range params { + q.Add(k, v) + } + + // Set the new query values on the URL + url.RawQuery = q.Encode() + url.Fragment = s.genRemark(inbound, email, "") return url.String() } @@ -534,7 +554,6 @@ func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string } security, _ := stream["security"].(string) - var domains []interface{} if security == "tls" { params["security"] = "tls" tlsSetting, _ := stream["tlsSettings"].(map[string]interface{}) @@ -546,11 +565,11 @@ func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string if len(alpn) > 0 { params["alpn"] = strings.Join(alpn, ",") } + if sniValue, ok := searchKey(tlsSetting, "serverName"); ok { + params["sni"], _ = sniValue.(string) + } tlsSettings, _ := searchKey(tlsSetting, "settings") if tlsSetting != nil { - if sniValue, ok := searchKey(tlsSettings, "serverName"); ok { - params["sni"], _ = sniValue.(string) - } if fpValue, ok := searchKey(tlsSettings, "fingerprint"); ok { params["fp"], _ = fpValue.(string) } @@ -559,14 +578,6 @@ func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string params["allowInsecure"] = "1" } } - if domainSettings, ok := searchKey(tlsSettings, "domains"); ok { - domains, _ = domainSettings.([]interface{}) - } - } - - serverName, _ := tlsSetting["serverName"].(string) - if serverName != "" { - address = serverName } } @@ -596,11 +607,6 @@ func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string params["spx"] = spx } } - if serverName, ok := searchKey(realitySettings, "serverName"); ok { - if sname, ok := serverName.(string); ok && len(sname) > 0 { - address = sname - } - } } if streamNetwork == "tcp" && len(clients[clientIndex].Flow) > 0 { @@ -619,6 +625,9 @@ func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string if len(alpn) > 0 { params["alpn"] = strings.Join(alpn, ",") } + if sniValue, ok := searchKey(xtlsSetting, "serverName"); ok { + params["sni"], _ = sniValue.(string) + } xtlsSettings, _ := searchKey(xtlsSetting, "settings") if xtlsSetting != nil { @@ -630,43 +639,47 @@ func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string params["allowInsecure"] = "1" } } - if sniValue, ok := searchKey(xtlsSettings, "serverName"); ok { - params["sni"], _ = sniValue.(string) - } } if streamNetwork == "tcp" && len(clients[clientIndex].Flow) > 0 { params["flow"] = clients[clientIndex].Flow } - - serverName, _ := xtlsSetting["serverName"].(string) - if serverName != "" { - address = serverName - } } if security != "tls" && security != "reality" && security != "xtls" { params["security"] = "none" } - link := fmt.Sprintf("trojan://%s@%s:%d", password, address, port) + externalProxies, _ := stream["externalProxy"].([]interface{}) - url, _ := url.Parse(link) - q := url.Query() + if len(externalProxies) > 0 { + links := "" + for index, externalProxy := range externalProxies { + ep, _ := externalProxy.(map[string]interface{}) + newSecurity, _ := ep["forceTls"].(string) + dest, _ := ep["dest"].(string) + port := int(ep["port"].(float64)) + link := fmt.Sprintf("trojan://%s@%s:%d", password, dest, port) + + if newSecurity != "same" { + params["security"] = newSecurity + } else { + params["security"] = security + } + url, _ := url.Parse(link) + q := url.Query() - for k, v := range params { - q.Add(k, v) - } + for k, v := range params { + if !(newSecurity == "none" && (k == "alpn" || k == "sni" || k == "fp" || k == "allowInsecure")) { + q.Add(k, v) + } + } - // Set the new query values on the URL - url.RawQuery = q.Encode() + // Set the new query values on the URL + url.RawQuery = q.Encode() + + url.Fragment = s.genRemark(inbound, email, ep["remark"].(string)) - if len(domains) > 0 { - links := "" - for index, d := range domains { - domain := d.(map[string]interface{}) - url.Fragment = s.genRemark(inbound, email, domain["remark"].(string)) - url.Host = fmt.Sprintf("%s:%d", domain["domain"].(string), port) if index > 0 { links += "\n" } @@ -675,6 +688,18 @@ func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string return links } + link := fmt.Sprintf("trojan://%s@%s:%d", password, address, port) + + url, _ := url.Parse(link) + q := url.Query() + + for k, v := range params { + q.Add(k, v) + } + + // Set the new query values on the URL + url.RawQuery = q.Encode() + url.Fragment = s.genRemark(inbound, email, "") return url.String() } @@ -744,10 +769,78 @@ func (s *SubService) genShadowsocksLink(inbound *model.Inbound, email string) st } } + security, _ := stream["security"].(string) + if security == "tls" { + params["security"] = "tls" + tlsSetting, _ := stream["tlsSettings"].(map[string]interface{}) + alpns, _ := tlsSetting["alpn"].([]interface{}) + var alpn []string + for _, a := range alpns { + alpn = append(alpn, a.(string)) + } + if len(alpn) > 0 { + params["alpn"] = strings.Join(alpn, ",") + } + if sniValue, ok := searchKey(tlsSetting, "serverName"); ok { + params["sni"], _ = sniValue.(string) + } + + tlsSettings, _ := searchKey(tlsSetting, "settings") + if tlsSetting != nil { + if fpValue, ok := searchKey(tlsSettings, "fingerprint"); ok { + params["fp"], _ = fpValue.(string) + } + if insecure, ok := searchKey(tlsSettings, "allowInsecure"); ok { + if insecure.(bool) { + params["allowInsecure"] = "1" + } + } + } + } + encPart := fmt.Sprintf("%s:%s", method, clients[clientIndex].Password) if method[0] == '2' { encPart = fmt.Sprintf("%s:%s:%s", method, inboundPassword, clients[clientIndex].Password) } + + externalProxies, _ := stream["externalProxy"].([]interface{}) + + if len(externalProxies) > 0 { + links := "" + for index, externalProxy := range externalProxies { + ep, _ := externalProxy.(map[string]interface{}) + newSecurity, _ := ep["forceTls"].(string) + dest, _ := ep["dest"].(string) + port := int(ep["port"].(float64)) + link := fmt.Sprintf("ss://%s@%s:%d", base64.StdEncoding.EncodeToString([]byte(encPart)), dest, port) + + if newSecurity != "same" { + params["security"] = newSecurity + } else { + params["security"] = security + } + url, _ := url.Parse(link) + q := url.Query() + + for k, v := range params { + if !(newSecurity == "none" && (k == "alpn" || k == "sni" || k == "fp" || k == "allowInsecure")) { + q.Add(k, v) + } + } + + // Set the new query values on the URL + url.RawQuery = q.Encode() + + url.Fragment = s.genRemark(inbound, email, ep["remark"].(string)) + + if index > 0 { + links += "\n" + } + links += url.String() + } + return links + } + link := fmt.Sprintf("ss://%s@%s:%d", base64.StdEncoding.EncodeToString([]byte(encPart)), address, inbound.Port) url, _ := url.Parse(link) q := url.Query() @@ -758,6 +851,7 @@ func (s *SubService) genShadowsocksLink(inbound *model.Inbound, email string) st // Set the new query values on the URL url.RawQuery = q.Encode() + url.Fragment = s.genRemark(inbound, email, "") return url.String() } -- cgit v1.2.3