2023-05-22 17:36:34 +03:00
package sub
2023-04-09 22:43:18 +03:00
import (
"encoding/base64"
"fmt"
"net/url"
"strings"
"x-ui/database"
"x-ui/database/model"
"x-ui/logger"
2023-05-22 17:36:34 +03:00
"x-ui/web/service"
2023-04-18 21:04:06 +03:00
"x-ui/xray"
2023-04-09 22:43:18 +03:00
"github.com/goccy/go-json"
)
type SubService struct {
address string
2023-05-22 17:36:34 +03:00
inboundService service . InboundService
settingServics service . SettingService
2023-04-09 22:43:18 +03:00
}
2023-05-17 00:37:35 +03:00
func ( s * SubService ) GetSubs ( subId string , host string ) ( [ ] string , [ ] string , error ) {
2023-04-09 22:43:18 +03:00
s . address = host
var result [ ] string
2023-05-17 00:37:35 +03:00
var headers [ ] string
2023-04-18 21:04:06 +03:00
var traffic xray . ClientTraffic
var clientTraffics [ ] xray . ClientTraffic
2023-04-09 22:43:18 +03:00
inbounds , err := s . getInboundsBySubId ( subId )
if err != nil {
2023-05-17 00:37:35 +03:00
return nil , nil , err
2023-04-09 22:43:18 +03:00
}
for _ , inbound := range inbounds {
2023-05-22 17:36:34 +03:00
clients , err := s . inboundService . GetClients ( inbound )
2023-04-09 22:43:18 +03:00
if err != nil {
logger . Error ( "SubService - GetSub: Unable to get clients from inbound" )
}
if clients == nil {
continue
}
for _ , client := range clients {
2023-05-12 17:59:02 +03:00
if client . Enable && client . SubID == subId {
2023-04-09 22:43:18 +03:00
link := s . getLink ( inbound , client . Email )
result = append ( result , link )
2023-04-18 21:04:06 +03:00
clientTraffics = append ( clientTraffics , s . getClientTraffics ( inbound . ClientStats , client . Email ) )
}
}
}
for index , clientTraffic := range clientTraffics {
if index == 0 {
traffic . Up = clientTraffic . Up
traffic . Down = clientTraffic . Down
traffic . Total = clientTraffic . Total
if clientTraffic . ExpiryTime > 0 {
traffic . ExpiryTime = clientTraffic . ExpiryTime
}
} else {
traffic . Up += clientTraffic . Up
traffic . Down += clientTraffic . Down
if traffic . Total == 0 || clientTraffic . Total == 0 {
traffic . Total = 0
} else {
traffic . Total += clientTraffic . Total
}
if clientTraffic . ExpiryTime != traffic . ExpiryTime {
traffic . ExpiryTime = 0
2023-04-09 22:43:18 +03:00
}
}
}
2023-05-17 00:37:35 +03:00
headers = append ( headers , fmt . Sprintf ( "upload=%d; download=%d; total=%d; expire=%d" , traffic . Up , traffic . Down , traffic . Total , traffic . ExpiryTime / 1000 ) )
2023-05-22 17:36:34 +03:00
updateInterval , _ := s . settingServics . GetSubUpdates ( )
headers = append ( headers , fmt . Sprintf ( "%d" , updateInterval ) )
2023-05-17 00:37:35 +03:00
headers = append ( headers , subId )
return result , headers , nil
2023-04-09 22:43:18 +03:00
}
func ( s * SubService ) getInboundsBySubId ( subId string ) ( [ ] * model . Inbound , error ) {
db := database . GetDB ( )
var inbounds [ ] * model . Inbound
2023-05-12 17:59:02 +03:00
err := db . Model ( model . Inbound { } ) . Preload ( "ClientStats" ) . Where ( "settings like ? and enable = ?" , fmt . Sprintf ( ` %%"subId": "%s"%% ` , subId ) , true ) . Find ( & inbounds ) . Error
2023-05-17 00:37:35 +03:00
if err != nil {
2023-04-09 22:43:18 +03:00
return nil , err
}
return inbounds , nil
}
2023-04-18 21:04:06 +03:00
func ( s * SubService ) getClientTraffics ( traffics [ ] xray . ClientTraffic , email string ) xray . ClientTraffic {
for _ , traffic := range traffics {
if traffic . Email == email {
return traffic
}
}
return xray . ClientTraffic { }
}
2023-04-09 22:43:18 +03:00
func ( s * SubService ) getLink ( inbound * model . Inbound , email string ) string {
switch inbound . Protocol {
case "vmess" :
return s . genVmessLink ( inbound , email )
case "vless" :
return s . genVlessLink ( inbound , email )
case "trojan" :
return s . genTrojanLink ( inbound , email )
2023-05-06 19:51:14 +03:00
case "shadowsocks" :
return s . genShadowsocksLink ( inbound , email )
2023-04-09 22:43:18 +03:00
}
return ""
}
func ( s * SubService ) genVmessLink ( inbound * model . Inbound , email string ) string {
if inbound . Protocol != model . VMess {
return ""
}
2023-05-04 19:28:16 +03:00
remark := fmt . Sprintf ( "%s-%s" , inbound . Remark , email )
2023-04-27 23:45:06 +03:00
obj := map [ string ] interface { } {
"v" : "2" ,
2023-05-04 19:28:16 +03:00
"ps" : remark ,
2023-04-27 23:45:06 +03:00
"add" : s . address ,
"port" : inbound . Port ,
"type" : "none" ,
}
2023-04-09 22:43:18 +03:00
var stream map [ string ] interface { }
json . Unmarshal ( [ ] byte ( inbound . StreamSettings ) , & stream )
network , _ := stream [ "network" ] . ( string )
2023-04-27 23:45:06 +03:00
obj [ "net" ] = network
2023-04-09 22:43:18 +03:00
switch network {
case "tcp" :
tcp , _ := stream [ "tcpSettings" ] . ( map [ string ] interface { } )
header , _ := tcp [ "header" ] . ( map [ string ] interface { } )
2023-04-27 23:45:06 +03:00
typeStr , _ := header [ "type" ] . ( string )
obj [ "type" ] = typeStr
2023-04-09 22:43:18 +03:00
if typeStr == "http" {
request := header [ "request" ] . ( map [ string ] interface { } )
requestPath , _ := request [ "path" ] . ( [ ] interface { } )
2023-04-27 23:45:06 +03:00
obj [ "path" ] = requestPath [ 0 ] . ( string )
2023-04-09 22:43:18 +03:00
headers , _ := request [ "headers" ] . ( map [ string ] interface { } )
2023-04-27 23:45:06 +03:00
obj [ "host" ] = searchHost ( headers )
2023-04-09 22:43:18 +03:00
}
case "kcp" :
kcp , _ := stream [ "kcpSettings" ] . ( map [ string ] interface { } )
header , _ := kcp [ "header" ] . ( map [ string ] interface { } )
2023-04-27 23:45:06 +03:00
obj [ "type" ] , _ = header [ "type" ] . ( string )
obj [ "path" ] , _ = kcp [ "seed" ] . ( string )
2023-04-09 22:43:18 +03:00
case "ws" :
ws , _ := stream [ "wsSettings" ] . ( map [ string ] interface { } )
2023-04-27 23:45:06 +03:00
obj [ "path" ] = ws [ "path" ] . ( string )
2023-04-09 22:43:18 +03:00
headers , _ := ws [ "headers" ] . ( map [ string ] interface { } )
2023-04-27 23:45:06 +03:00
obj [ "host" ] = searchHost ( headers )
2023-04-09 22:43:18 +03:00
case "http" :
2023-04-27 23:45:06 +03:00
obj [ "net" ] = "h2"
2023-04-09 22:43:18 +03:00
http , _ := stream [ "httpSettings" ] . ( map [ string ] interface { } )
2023-04-27 23:45:06 +03:00
obj [ "path" ] , _ = http [ "path" ] . ( string )
obj [ "host" ] = searchHost ( http )
2023-04-09 22:43:18 +03:00
case "quic" :
quic , _ := stream [ "quicSettings" ] . ( map [ string ] interface { } )
header := quic [ "header" ] . ( map [ string ] interface { } )
2023-04-27 23:45:06 +03:00
obj [ "type" ] , _ = header [ "type" ] . ( string )
obj [ "host" ] , _ = quic [ "security" ] . ( string )
obj [ "path" ] , _ = quic [ "key" ] . ( string )
2023-04-09 22:43:18 +03:00
case "grpc" :
grpc , _ := stream [ "grpcSettings" ] . ( map [ string ] interface { } )
2023-04-27 23:45:06 +03:00
obj [ "path" ] = grpc [ "serviceName" ] . ( string )
if grpc [ "multiMode" ] . ( bool ) {
obj [ "type" ] = "multi"
}
2023-04-09 22:43:18 +03:00
}
security , _ := stream [ "security" ] . ( string )
2023-05-22 17:36:34 +03:00
var domains [ ] interface { }
2023-04-27 23:45:06 +03:00
obj [ "tls" ] = security
2023-04-09 22:43:18 +03:00
if security == "tls" {
tlsSetting , _ := stream [ "tlsSettings" ] . ( map [ string ] interface { } )
alpns , _ := tlsSetting [ "alpn" ] . ( [ ] interface { } )
2023-04-27 23:45:06 +03:00
if len ( alpns ) > 0 {
var alpn [ ] string
for _ , a := range alpns {
alpn = append ( alpn , a . ( string ) )
}
obj [ "alpn" ] = strings . Join ( alpn , "," )
2023-04-09 22:43:18 +03:00
}
tlsSettings , _ := searchKey ( tlsSetting , "settings" )
if tlsSetting != nil {
if sniValue , ok := searchKey ( tlsSettings , "serverName" ) ; ok {
2023-04-27 23:45:06 +03:00
obj [ "sni" ] , _ = sniValue . ( string )
2023-04-09 22:43:18 +03:00
}
if fpValue , ok := searchKey ( tlsSettings , "fingerprint" ) ; ok {
2023-04-27 23:45:06 +03:00
obj [ "fp" ] , _ = fpValue . ( string )
2023-04-09 22:43:18 +03:00
}
if insecure , ok := searchKey ( tlsSettings , "allowInsecure" ) ; ok {
2023-04-27 23:45:06 +03:00
obj [ "allowInsecure" ] , _ = insecure . ( bool )
2023-04-09 22:43:18 +03:00
}
2023-05-22 17:36:34 +03:00
if domainSettings , ok := searchKey ( tlsSettings , "domains" ) ; ok {
domains , _ = domainSettings . ( [ ] interface { } )
}
2023-04-09 22:43:18 +03:00
}
serverName , _ := tlsSetting [ "serverName" ] . ( string )
if serverName != "" {
2023-04-27 23:45:06 +03:00
obj [ "add" ] = serverName
2023-04-09 22:43:18 +03:00
}
}
2023-05-22 17:36:34 +03:00
clients , _ := s . inboundService . GetClients ( inbound )
2023-04-09 22:43:18 +03:00
clientIndex := - 1
for i , client := range clients {
if client . Email == email {
clientIndex = i
break
}
}
2023-04-27 23:45:06 +03:00
obj [ "id" ] = clients [ clientIndex ] . ID
obj [ "aid" ] = clients [ clientIndex ] . AlterIds
2023-04-09 22:43:18 +03:00
2023-05-22 17:36:34 +03:00
if len ( domains ) > 0 {
links := ""
for index , d := range domains {
domain := d . ( map [ string ] interface { } )
obj [ "ps" ] = remark + "-" + domain [ "remark" ] . ( string )
obj [ "add" ] = domain [ "domain" ] . ( string )
if index > 0 {
links += "\n"
}
jsonStr , _ := json . MarshalIndent ( obj , "" , " " )
links += "vmess://" + base64 . StdEncoding . EncodeToString ( jsonStr )
}
return links
}
2023-04-09 22:43:18 +03:00
jsonStr , _ := json . MarshalIndent ( obj , "" , " " )
return "vmess://" + base64 . StdEncoding . EncodeToString ( jsonStr )
}
func ( s * SubService ) genVlessLink ( inbound * model . Inbound , email string ) string {
address := s . address
if inbound . Protocol != model . VLESS {
return ""
}
var stream map [ string ] interface { }
json . Unmarshal ( [ ] byte ( inbound . StreamSettings ) , & stream )
2023-05-22 17:36:34 +03:00
clients , _ := s . inboundService . GetClients ( inbound )
2023-04-09 22:43:18 +03:00
clientIndex := - 1
for i , client := range clients {
if client . Email == email {
clientIndex = i
break
}
}
uuid := clients [ clientIndex ] . ID
port := inbound . Port
streamNetwork := stream [ "network" ] . ( string )
params := make ( map [ string ] string )
params [ "type" ] = streamNetwork
switch streamNetwork {
case "tcp" :
tcp , _ := stream [ "tcpSettings" ] . ( map [ string ] interface { } )
header , _ := tcp [ "header" ] . ( map [ string ] interface { } )
typeStr , _ := header [ "type" ] . ( string )
if typeStr == "http" {
request := header [ "request" ] . ( map [ string ] interface { } )
requestPath , _ := request [ "path" ] . ( [ ] interface { } )
params [ "path" ] = requestPath [ 0 ] . ( string )
headers , _ := request [ "headers" ] . ( map [ string ] interface { } )
params [ "host" ] = searchHost ( headers )
params [ "headerType" ] = "http"
}
case "kcp" :
kcp , _ := stream [ "kcpSettings" ] . ( map [ string ] interface { } )
header , _ := kcp [ "header" ] . ( map [ string ] interface { } )
params [ "headerType" ] = header [ "type" ] . ( string )
params [ "seed" ] = kcp [ "seed" ] . ( string )
case "ws" :
ws , _ := stream [ "wsSettings" ] . ( map [ string ] interface { } )
params [ "path" ] = ws [ "path" ] . ( string )
headers , _ := ws [ "headers" ] . ( map [ string ] interface { } )
params [ "host" ] = searchHost ( headers )
case "http" :
http , _ := stream [ "httpSettings" ] . ( map [ string ] interface { } )
params [ "path" ] = http [ "path" ] . ( string )
params [ "host" ] = searchHost ( http )
case "quic" :
quic , _ := stream [ "quicSettings" ] . ( map [ string ] interface { } )
params [ "quicSecurity" ] = quic [ "security" ] . ( string )
params [ "key" ] = quic [ "key" ] . ( string )
header := quic [ "header" ] . ( map [ string ] interface { } )
params [ "headerType" ] = header [ "type" ] . ( string )
case "grpc" :
grpc , _ := stream [ "grpcSettings" ] . ( map [ string ] interface { } )
params [ "serviceName" ] = grpc [ "serviceName" ] . ( string )
2023-04-27 23:45:06 +03:00
if grpc [ "multiMode" ] . ( bool ) {
params [ "mode" ] = "multi"
}
2023-04-09 22:43:18 +03:00
}
security , _ := stream [ "security" ] . ( string )
2023-05-22 17:36:34 +03:00
var domains [ ] interface { }
2023-04-09 22:43:18 +03:00
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 , "," )
}
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 )
}
if insecure , ok := searchKey ( tlsSettings , "allowInsecure" ) ; ok {
if insecure . ( bool ) {
params [ "allowInsecure" ] = "1"
}
}
2023-05-22 17:36:34 +03:00
if domainSettings , ok := searchKey ( tlsSettings , "domains" ) ; ok {
domains , _ = domainSettings . ( [ ] interface { } )
}
2023-04-09 22:43:18 +03:00
}
if streamNetwork == "tcp" && len ( clients [ clientIndex ] . Flow ) > 0 {
params [ "flow" ] = clients [ clientIndex ] . Flow
}
serverName , _ := tlsSetting [ "serverName" ] . ( string )
if serverName != "" {
address = serverName
}
}
2023-04-11 15:10:45 +03:00
if security == "reality" {
params [ "security" ] = "reality"
2023-04-19 11:25:31 +03:00
realitySetting , _ := stream [ "realitySettings" ] . ( map [ string ] interface { } )
realitySettings , _ := searchKey ( realitySetting , "settings" )
if realitySetting != nil {
if sniValue , ok := searchKey ( realitySetting , "serverNames" ) ; ok {
2023-04-12 11:44:07 +03:00
sNames , _ := sniValue . ( [ ] interface { } )
params [ "sni" ] , _ = sNames [ 0 ] . ( string )
2023-04-11 15:10:45 +03:00
}
if pbkValue , ok := searchKey ( realitySettings , "publicKey" ) ; ok {
params [ "pbk" ] , _ = pbkValue . ( string )
}
2023-04-19 11:25:31 +03:00
if sidValue , ok := searchKey ( realitySetting , "shortIds" ) ; ok {
2023-04-12 11:44:07 +03:00
shortIds , _ := sidValue . ( [ ] interface { } )
params [ "sid" ] , _ = shortIds [ 0 ] . ( string )
2023-04-11 15:10:45 +03:00
}
if fpValue , ok := searchKey ( realitySettings , "fingerprint" ) ; ok {
2023-04-19 11:25:31 +03:00
if fp , ok := fpValue . ( string ) ; ok && len ( fp ) > 0 {
params [ "fp" ] = fp
}
}
2023-05-17 15:40:11 +03:00
if spxValue , ok := searchKey ( realitySettings , "spiderX" ) ; ok {
if spx , ok := spxValue . ( string ) ; ok && len ( spx ) > 0 {
params [ "spx" ] = spx
}
}
2023-04-19 11:25:31 +03:00
if serverName , ok := searchKey ( realitySettings , "serverName" ) ; ok {
if sname , ok := serverName . ( string ) ; ok && len ( sname ) > 0 {
address = sname
}
2023-04-11 15:10:45 +03:00
}
}
if streamNetwork == "tcp" && len ( clients [ clientIndex ] . Flow ) > 0 {
params [ "flow" ] = clients [ clientIndex ] . Flow
}
}
2023-04-09 22:43:18 +03:00
if security == "xtls" {
params [ "security" ] = "xtls"
2023-04-18 21:04:06 +03:00
xtlsSetting , _ := stream [ "xtlsSettings" ] . ( map [ string ] interface { } )
2023-04-09 22:43:18 +03:00
alpns , _ := xtlsSetting [ "alpn" ] . ( [ ] interface { } )
var alpn [ ] string
for _ , a := range alpns {
alpn = append ( alpn , a . ( string ) )
}
if len ( alpn ) > 0 {
params [ "alpn" ] = strings . Join ( alpn , "," )
}
2023-04-18 21:04:06 +03:00
xtlsSettings , _ := searchKey ( xtlsSetting , "settings" )
2023-04-09 22:43:18 +03:00
if xtlsSetting != nil {
2023-04-18 21:04:06 +03:00
if fpValue , ok := searchKey ( xtlsSettings , "fingerprint" ) ; ok {
2023-04-09 22:43:18 +03:00
params [ "fp" ] , _ = fpValue . ( string )
}
2023-04-18 21:04:06 +03:00
if insecure , ok := searchKey ( xtlsSettings , "allowInsecure" ) ; ok {
2023-04-09 22:43:18 +03:00
if insecure . ( bool ) {
params [ "allowInsecure" ] = "1"
}
}
2023-05-07 19:29:06 +03:00
if sniValue , ok := searchKey ( xtlsSettings , "serverName" ) ; ok {
params [ "sni" ] , _ = sniValue . ( string )
}
2023-04-09 22:43:18 +03:00
}
if streamNetwork == "tcp" && len ( clients [ clientIndex ] . Flow ) > 0 {
params [ "flow" ] = clients [ clientIndex ] . Flow
}
serverName , _ := xtlsSetting [ "serverName" ] . ( string )
if serverName != "" {
address = serverName
}
}
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 ( )
2023-05-04 19:28:16 +03:00
remark := fmt . Sprintf ( "%s-%s" , inbound . Remark , email )
2023-05-22 17:36:34 +03:00
if len ( domains ) > 0 {
links := ""
for index , d := range domains {
domain := d . ( map [ string ] interface { } )
url . Fragment = remark + "-" + domain [ "remark" ] . ( string )
url . Host = fmt . Sprintf ( "%s:%d" , domain [ "domain" ] . ( string ) , port )
if index > 0 {
links += "\n"
}
links += url . String ( )
}
return links
}
2023-05-04 19:28:16 +03:00
url . Fragment = remark
2023-04-09 22:43:18 +03:00
return url . String ( )
}
func ( s * SubService ) genTrojanLink ( inbound * model . Inbound , email string ) string {
address := s . address
if inbound . Protocol != model . Trojan {
return ""
}
var stream map [ string ] interface { }
json . Unmarshal ( [ ] byte ( inbound . StreamSettings ) , & stream )
2023-05-22 17:36:34 +03:00
clients , _ := s . inboundService . GetClients ( inbound )
2023-04-09 22:43:18 +03:00
clientIndex := - 1
for i , client := range clients {
if client . Email == email {
clientIndex = i
break
}
}
password := clients [ clientIndex ] . Password
port := inbound . Port
streamNetwork := stream [ "network" ] . ( string )
params := make ( map [ string ] string )
params [ "type" ] = streamNetwork
switch streamNetwork {
case "tcp" :
tcp , _ := stream [ "tcpSettings" ] . ( map [ string ] interface { } )
header , _ := tcp [ "header" ] . ( map [ string ] interface { } )
typeStr , _ := header [ "type" ] . ( string )
if typeStr == "http" {
request := header [ "request" ] . ( map [ string ] interface { } )
requestPath , _ := request [ "path" ] . ( [ ] interface { } )
params [ "path" ] = requestPath [ 0 ] . ( string )
headers , _ := request [ "headers" ] . ( map [ string ] interface { } )
params [ "host" ] = searchHost ( headers )
params [ "headerType" ] = "http"
}
case "kcp" :
kcp , _ := stream [ "kcpSettings" ] . ( map [ string ] interface { } )
header , _ := kcp [ "header" ] . ( map [ string ] interface { } )
params [ "headerType" ] = header [ "type" ] . ( string )
params [ "seed" ] = kcp [ "seed" ] . ( string )
case "ws" :
ws , _ := stream [ "wsSettings" ] . ( map [ string ] interface { } )
params [ "path" ] = ws [ "path" ] . ( string )
headers , _ := ws [ "headers" ] . ( map [ string ] interface { } )
params [ "host" ] = searchHost ( headers )
case "http" :
http , _ := stream [ "httpSettings" ] . ( map [ string ] interface { } )
params [ "path" ] = http [ "path" ] . ( string )
params [ "host" ] = searchHost ( http )
case "quic" :
quic , _ := stream [ "quicSettings" ] . ( map [ string ] interface { } )
params [ "quicSecurity" ] = quic [ "security" ] . ( string )
params [ "key" ] = quic [ "key" ] . ( string )
header := quic [ "header" ] . ( map [ string ] interface { } )
params [ "headerType" ] = header [ "type" ] . ( string )
case "grpc" :
grpc , _ := stream [ "grpcSettings" ] . ( map [ string ] interface { } )
params [ "serviceName" ] = grpc [ "serviceName" ] . ( string )
2023-04-27 23:45:06 +03:00
if grpc [ "multiMode" ] . ( bool ) {
params [ "mode" ] = "multi"
}
2023-04-09 22:43:18 +03:00
}
security , _ := stream [ "security" ] . ( string )
2023-05-22 17:36:34 +03:00
var domains [ ] interface { }
2023-04-09 22:43:18 +03:00
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 , "," )
}
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 )
}
if insecure , ok := searchKey ( tlsSettings , "allowInsecure" ) ; ok {
if insecure . ( bool ) {
params [ "allowInsecure" ] = "1"
}
}
2023-05-22 17:36:34 +03:00
if domainSettings , ok := searchKey ( tlsSettings , "domains" ) ; ok {
domains , _ = domainSettings . ( [ ] interface { } )
}
2023-04-09 22:43:18 +03:00
}
serverName , _ := tlsSetting [ "serverName" ] . ( string )
if serverName != "" {
address = serverName
2023-04-11 22:00:24 +03:00
}
}
if security == "reality" {
params [ "security" ] = "reality"
2023-04-19 11:25:31 +03:00
realitySetting , _ := stream [ "realitySettings" ] . ( map [ string ] interface { } )
realitySettings , _ := searchKey ( realitySetting , "settings" )
if realitySetting != nil {
if sniValue , ok := searchKey ( realitySetting , "serverNames" ) ; ok {
2023-04-12 11:44:07 +03:00
sNames , _ := sniValue . ( [ ] interface { } )
params [ "sni" ] , _ = sNames [ 0 ] . ( string )
2023-04-11 22:00:24 +03:00
}
if pbkValue , ok := searchKey ( realitySettings , "publicKey" ) ; ok {
params [ "pbk" ] , _ = pbkValue . ( string )
}
if sidValue , ok := searchKey ( realitySettings , "shortIds" ) ; ok {
2023-04-12 11:44:07 +03:00
shortIds , _ := sidValue . ( [ ] interface { } )
params [ "sid" ] , _ = shortIds [ 0 ] . ( string )
2023-04-11 22:00:24 +03:00
}
if fpValue , ok := searchKey ( realitySettings , "fingerprint" ) ; ok {
2023-04-19 11:25:31 +03:00
if fp , ok := fpValue . ( string ) ; ok && len ( fp ) > 0 {
params [ "fp" ] = fp
}
}
2023-05-17 15:40:11 +03:00
if spxValue , ok := searchKey ( realitySettings , "spiderX" ) ; ok {
if spx , ok := spxValue . ( string ) ; ok && len ( spx ) > 0 {
params [ "spx" ] = spx
}
}
2023-04-19 11:25:31 +03:00
if serverName , ok := searchKey ( realitySettings , "serverName" ) ; ok {
if sname , ok := serverName . ( string ) ; ok && len ( sname ) > 0 {
address = sname
}
2023-04-11 22:00:24 +03:00
}
}
2023-04-12 11:44:07 +03:00
if streamNetwork == "tcp" && len ( clients [ clientIndex ] . Flow ) > 0 {
params [ "flow" ] = clients [ clientIndex ] . Flow
2023-04-09 22:43:18 +03:00
}
}
if security == "xtls" {
params [ "security" ] = "xtls"
2023-04-18 21:04:06 +03:00
xtlsSetting , _ := stream [ "xtlsSettings" ] . ( map [ string ] interface { } )
2023-04-09 22:43:18 +03:00
alpns , _ := xtlsSetting [ "alpn" ] . ( [ ] interface { } )
var alpn [ ] string
for _ , a := range alpns {
alpn = append ( alpn , a . ( string ) )
}
if len ( alpn ) > 0 {
params [ "alpn" ] = strings . Join ( alpn , "," )
}
2023-04-18 21:04:06 +03:00
xtlsSettings , _ := searchKey ( xtlsSetting , "settings" )
2023-04-09 22:43:18 +03:00
if xtlsSetting != nil {
2023-04-18 21:04:06 +03:00
if fpValue , ok := searchKey ( xtlsSettings , "fingerprint" ) ; ok {
2023-04-09 22:43:18 +03:00
params [ "fp" ] , _ = fpValue . ( string )
}
2023-04-18 21:04:06 +03:00
if insecure , ok := searchKey ( xtlsSettings , "allowInsecure" ) ; ok {
2023-04-09 22:43:18 +03:00
if insecure . ( bool ) {
params [ "allowInsecure" ] = "1"
}
}
2023-05-07 19:29:06 +03:00
if sniValue , ok := searchKey ( xtlsSettings , "serverName" ) ; ok {
params [ "sni" ] , _ = sniValue . ( string )
}
2023-04-09 22:43:18 +03:00
}
if streamNetwork == "tcp" && len ( clients [ clientIndex ] . Flow ) > 0 {
params [ "flow" ] = clients [ clientIndex ] . Flow
}
serverName , _ := xtlsSetting [ "serverName" ] . ( string )
if serverName != "" {
address = serverName
}
}
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 ( )
2023-05-04 19:28:16 +03:00
remark := fmt . Sprintf ( "%s-%s" , inbound . Remark , email )
2023-05-22 17:36:34 +03:00
if len ( domains ) > 0 {
links := ""
for index , d := range domains {
domain := d . ( map [ string ] interface { } )
url . Fragment = remark + "-" + domain [ "remark" ] . ( string )
url . Host = fmt . Sprintf ( "%s:%d" , domain [ "domain" ] . ( string ) , port )
if index > 0 {
links += "\n"
}
links += url . String ( )
}
return links
}
2023-05-04 19:28:16 +03:00
url . Fragment = remark
2023-04-09 22:43:18 +03:00
return url . String ( )
}
2023-05-06 19:51:14 +03:00
func ( s * SubService ) genShadowsocksLink ( inbound * model . Inbound , email string ) string {
address := s . address
if inbound . Protocol != model . Shadowsocks {
return ""
}
2023-05-22 17:36:34 +03:00
clients , _ := s . inboundService . GetClients ( inbound )
2023-05-06 19:51:14 +03:00
var settings map [ string ] interface { }
json . Unmarshal ( [ ] byte ( inbound . Settings ) , & settings )
inboundPassword := settings [ "password" ] . ( string )
method := settings [ "method" ] . ( string )
clientIndex := - 1
for i , client := range clients {
if client . Email == email {
clientIndex = i
break
}
}
encPart := fmt . Sprintf ( "%s:%s:%s" , method , inboundPassword , clients [ clientIndex ] . Password )
2023-05-20 17:14:18 +03:00
remark := fmt . Sprintf ( "%s-%s" , inbound . Remark , clients [ clientIndex ] . Email )
return fmt . Sprintf ( "ss://%s@%s:%d#%s" , base64 . StdEncoding . EncodeToString ( [ ] byte ( encPart ) ) , address , inbound . Port , remark )
2023-05-06 19:51:14 +03:00
}
2023-04-09 22:43:18 +03:00
func searchKey ( data interface { } , key string ) ( interface { } , bool ) {
switch val := data . ( type ) {
case map [ string ] interface { } :
for k , v := range val {
if k == key {
return v , true
}
if result , ok := searchKey ( v , key ) ; ok {
return result , true
}
}
case [ ] interface { } :
for _ , v := range val {
if result , ok := searchKey ( v , key ) ; ok {
return result , true
}
}
}
return nil , false
}
func searchHost ( headers interface { } ) string {
data , _ := headers . ( map [ string ] interface { } )
for k , v := range data {
if strings . EqualFold ( k , "host" ) {
switch v . ( type ) {
case [ ] interface { } :
hosts , _ := v . ( [ ] interface { } )
2023-04-25 14:09:09 +03:00
if len ( hosts ) > 0 {
return hosts [ 0 ] . ( string )
} else {
return ""
}
2023-04-09 22:43:18 +03:00
case interface { } :
return v . ( string )
}
}
}
return ""
}