Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/MHSanaei/3x-ui.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/sub
diff options
context:
space:
mode:
authorHo3ein <ho3ein.sanaei@gmail.com>2023-12-10 17:42:52 +0300
committerGitHub <noreply@github.com>2023-12-10 17:42:52 +0300
commite3f1d3c892a1af48f27fdc36f273a55f38d13b40 (patch)
treeb11d0c1ed3c15c8f6f891a5e6df8e021d5db8ab6 /sub
parent36cf7c0a8fda915b51e75958ce729fd9a61a5c90 (diff)
parent9fbe80f87f950673058f0001b3704251fa8b9243 (diff)
huge changes
Diffstat (limited to 'sub')
-rw-r--r--sub/subService.go332
1 files changed, 222 insertions, 110 deletions
diff --git a/sub/subService.go b/sub/subService.go
index 4cb14030..251ef2e8 100644
--- a/sub/subService.go
+++ b/sub/subService.go
@@ -19,8 +19,9 @@ import (
type SubService struct {
address string
showInfo bool
+ remarkModel string
inboundService service.InboundService
- settingServics service.SettingService
+ settingService service.SettingService
}
func (s *SubService) GetSubs(subId string, host string, showInfo bool) ([]string, []string, error) {
@@ -34,6 +35,10 @@ func (s *SubService) GetSubs(subId string, host string, showInfo bool) ([]string
if err != nil {
return nil, nil, err
}
+ s.remarkModel, err = s.settingService.GetRemarkModel()
+ if err != nil {
+ s.remarkModel = "-ieo"
+ }
for _, inbound := range inbounds {
clients, err := s.inboundService.GetClients(inbound)
if err != nil {
@@ -53,6 +58,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)
}
@@ -87,7 +93,7 @@ func (s *SubService) GetSubs(subId string, host string, showInfo bool) ([]string
}
}
headers = append(headers, fmt.Sprintf("upload=%d; download=%d; total=%d; expire=%d", traffic.Up, traffic.Down, traffic.Total, traffic.ExpiryTime/1000))
- updateInterval, _ := s.settingServics.GetSubUpdates()
+ updateInterval, _ := s.settingService.GetSubUpdates()
headers = append(headers, fmt.Sprintf("%d", updateInterval))
headers = append(headers, subId)
return result, headers, nil
@@ -96,7 +102,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 +209,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 +220,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 +245,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 +343,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 +354,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 +368,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 +401,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 +419,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 +432,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 +481,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 +559,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 +570,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 +583,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 +612,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 +630,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 +644,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 +693,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 +774,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,22 +856,36 @@ 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()
}
func (s *SubService) genRemark(inbound *model.Inbound, email string, extra string) string {
- var remark []string
+ separationChar := string(s.remarkModel[0])
+ orderChars := s.remarkModel[1:]
+ orders := map[byte]string{
+ 'i': "",
+ 'e': "",
+ 'o': "",
+ }
if len(email) > 0 {
- if len(inbound.Remark) > 0 {
- remark = append(remark, inbound.Remark)
- }
- remark = append(remark, email)
- if len(extra) > 0 {
- remark = append(remark, extra)
+ orders['e'] = email
+ }
+ if len(inbound.Remark) > 0 {
+ orders['i'] = inbound.Remark
+ }
+ if len(extra) > 0 {
+ orders['e'] = extra
+ }
+
+ var remark []string
+ for i := 0; i < len(orderChars); i++ {
+ char := orderChars[i]
+ order, exists := orders[char]
+ if exists && order != "" {
+ remark = append(remark, order)
}
- } else {
- return inbound.Remark
}
if s.showInfo {
@@ -790,7 +902,7 @@ func (s *SubService) genRemark(inbound *model.Inbound, email string, extra strin
// Get remained days
if statsExist {
if !stats.Enable {
- return fmt.Sprintf("⛔️N/A-%s", strings.Join(remark, "-"))
+ return fmt.Sprintf("⛔️N/A%s%s", separationChar, strings.Join(remark, separationChar))
}
if vol := stats.Total - (stats.Up + stats.Down); vol > 0 {
remark = append(remark, fmt.Sprintf("%s%s", common.FormatTraffic(vol), "📊"))
@@ -804,7 +916,7 @@ func (s *SubService) genRemark(inbound *model.Inbound, email string, extra strin
}
}
}
- return strings.Join(remark, " : ")
+ return strings.Join(remark, separationChar)
}
func searchKey(data interface{}, key string) (interface{}, bool) {