move LinkGenerator ro backend
This commit is contained in:
+1
-2
@@ -88,8 +88,7 @@ func (a *APIHandler) postHandler(c *gin.Context) {
|
||||
obj := c.Request.FormValue("object")
|
||||
act := c.Request.FormValue("action")
|
||||
data := c.Request.FormValue("data")
|
||||
userLinks := c.Request.FormValue("userLinks")
|
||||
objs, err := a.ConfigService.Save(obj, act, json.RawMessage(data), json.RawMessage(userLinks), loginUser, hostname)
|
||||
objs, err := a.ConfigService.Save(obj, act, json.RawMessage(data), loginUser, hostname)
|
||||
if err != nil {
|
||||
jsonMsg(c, "save", err)
|
||||
return
|
||||
|
||||
@@ -90,7 +90,25 @@ func moveJsonToDb(db *gorm.DB) error {
|
||||
db.Raw("select id,addrs,out_json from inbound_data where tag = ?", tag).Find(&inbData)
|
||||
if inbData.Id > 0 {
|
||||
inbObj["out_json"] = inbData.OutJson
|
||||
inbObj["addrs"] = inbData.Addrs
|
||||
var addrs []map[string]interface{}
|
||||
json.Unmarshal(inbData.Addrs, &addrs)
|
||||
for index, addr := range addrs {
|
||||
if tlsEnable, ok := addr["tls"].(bool); ok {
|
||||
newTls := map[string]interface{}{
|
||||
"enabled": tlsEnable,
|
||||
}
|
||||
if insecure, ok := addr["insecure"].(bool); ok {
|
||||
newTls["insecure"] = insecure
|
||||
delete(addrs[index], "insecure")
|
||||
}
|
||||
if sni, ok := addr["server_name"].(string); ok {
|
||||
newTls["server_name"] = sni
|
||||
delete(addrs[index], "server_name")
|
||||
}
|
||||
addrs[index]["tls"] = newTls
|
||||
}
|
||||
}
|
||||
inbObj["addrs"] = addrs
|
||||
} else {
|
||||
inbObj["out_json"] = json.RawMessage("{}")
|
||||
inbObj["addrs"] = json.RawMessage("[]")
|
||||
|
||||
@@ -90,7 +90,7 @@ func (i Inbound) MarshalFull() (*map[string]interface{}, error) {
|
||||
combined["out_json"] = i.OutJson
|
||||
|
||||
if i.Options != nil {
|
||||
var restFields map[string]json.RawMessage
|
||||
var restFields map[string]interface{}
|
||||
if err := json.Unmarshal(i.Options, &restFields); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+117
-17
@@ -5,6 +5,7 @@ import (
|
||||
"s-ui/database"
|
||||
"s-ui/database/model"
|
||||
"s-ui/logger"
|
||||
"s-ui/util"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
@@ -24,7 +25,7 @@ func (s *ClientService) GetAll() ([]model.Client, error) {
|
||||
return clients, nil
|
||||
}
|
||||
|
||||
func (s *ClientService) Save(tx *gorm.DB, act string, data json.RawMessage) ([]uint, error) {
|
||||
func (s *ClientService) Save(tx *gorm.DB, act string, data json.RawMessage, hostname string) ([]uint, error) {
|
||||
var err error
|
||||
var inboundIds []uint
|
||||
|
||||
@@ -39,6 +40,10 @@ func (s *ClientService) Save(tx *gorm.DB, act string, data json.RawMessage) ([]u
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = s.updateLinksWithFixedInbounds(tx, []*model.Client{&client}, inboundIds, hostname)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = tx.Save(&client).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -67,33 +72,128 @@ func (s *ClientService) Save(tx *gorm.DB, act string, data json.RawMessage) ([]u
|
||||
return inboundIds, nil
|
||||
}
|
||||
|
||||
func (s *ClientService) UpdateLinks(tx *gorm.DB, links json.RawMessage) error {
|
||||
var userLinks []interface{}
|
||||
err := json.Unmarshal(links, &userLinks)
|
||||
func (s *ClientService) updateLinksWithFixedInbounds(tx *gorm.DB, clients []*model.Client, inbounIds []uint, hostname string) error {
|
||||
var err error
|
||||
var inbounds []model.Inbound
|
||||
|
||||
// Zero inbounds means removing local links only
|
||||
if len(inbounIds) > 0 {
|
||||
err = tx.Model(model.Inbound{}).Preload("Tls").Where("id in ? and type in ?", inbounIds, util.InboundTypeWithLink).Find(&inbounds).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for index, client := range clients {
|
||||
var clientLinks, newClientLinks []map[string]string
|
||||
json.Unmarshal(client.Links, &clientLinks)
|
||||
|
||||
for _, inbound := range inbounds {
|
||||
newLinks := util.LinkGenerator(client.Config, &inbound, hostname)
|
||||
for _, newLink := range newLinks {
|
||||
newClientLinks = append(newClientLinks, map[string]string{
|
||||
"remark": inbound.Tag,
|
||||
"type": "local",
|
||||
"uri": newLink,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Add no local links
|
||||
for _, clientLink := range clientLinks {
|
||||
if clientLink["type"] != "local" {
|
||||
newClientLinks = append(newClientLinks, clientLink)
|
||||
}
|
||||
}
|
||||
|
||||
clients[index].Links, err = json.MarshalIndent(newClientLinks, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *ClientService) UpdateClientsOnInboundDelete(tx *gorm.DB, id uint, tag string) error {
|
||||
var clients []model.Client
|
||||
err := tx.Table("clients").
|
||||
Where("EXISTS (SELECT 1 FROM json_each(clients.inbounds) WHERE json_each.value = ?)", id).
|
||||
Find(&clients).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, userLink := range userLinks {
|
||||
userLinkData, _ := userLink.(map[string]interface{})
|
||||
userId, _ := userLinkData["id"].(float64)
|
||||
links, err := json.MarshalIndent(userLinkData["links"], "", " ")
|
||||
for _, client := range clients {
|
||||
// Delete inbounds
|
||||
var clientInbounds, newClientInbounds []uint
|
||||
json.Unmarshal(client.Inbounds, &clientInbounds)
|
||||
for _, clientInbound := range clientInbounds {
|
||||
if clientInbound != id {
|
||||
newClientInbounds = append(newClientInbounds, clientInbound)
|
||||
}
|
||||
}
|
||||
client.Inbounds, err = json.MarshalIndent(newClientInbounds, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if inbounds, ok := userLinkData["inbounds"]; ok {
|
||||
inbounds, err := json.MarshalIndent(inbounds, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = tx.Model(model.Client{}).Where("id = ?", uint(userId)).Update("inbounds", inbounds).Error
|
||||
if err != nil {
|
||||
return err
|
||||
// Delete links
|
||||
var clientLinks, newClientLinks []map[string]string
|
||||
json.Unmarshal(client.Links, &clientLinks)
|
||||
for _, clientLink := range clientLinks {
|
||||
if clientLink["remark"] != tag {
|
||||
newClientLinks = append(newClientLinks, clientLink)
|
||||
}
|
||||
}
|
||||
err = tx.Model(model.Client{}).Where("id = ?", uint(userId)).Update("links", links).Error
|
||||
client.Links, err = json.MarshalIndent(newClientLinks, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = tx.Save(&client).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *ClientService) UpdateLinksByInboundChange(tx *gorm.DB, inbounIds []uint, hostname string) error {
|
||||
var inbounds []model.Inbound
|
||||
err := tx.Model(model.Inbound{}).Preload("Tls").Where("id in ? and type in ?", inbounIds, util.InboundTypeWithLink).Find(&inbounds).Error
|
||||
if err != nil && err != gorm.ErrRecordNotFound {
|
||||
return err
|
||||
}
|
||||
for _, inbound := range inbounds {
|
||||
var clients []model.Client
|
||||
err = tx.Table("clients").
|
||||
Where("EXISTS (SELECT 1 FROM json_each(clients.inbounds) WHERE json_each.value = ?)", inbound.Id).
|
||||
Find(&clients).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, client := range clients {
|
||||
var clientLinks, newClientLinks []map[string]string
|
||||
json.Unmarshal(client.Links, &clientLinks)
|
||||
newLinks := util.LinkGenerator(client.Config, &inbound, hostname)
|
||||
for _, newLink := range newLinks {
|
||||
newClientLinks = append(newClientLinks, map[string]string{
|
||||
"remark": inbound.Tag,
|
||||
"type": "local",
|
||||
"uri": newLink,
|
||||
})
|
||||
}
|
||||
for _, clientLink := range clientLinks {
|
||||
if clientLink["remark"] != inbound.Tag {
|
||||
newClientLinks = append(newClientLinks, clientLink)
|
||||
}
|
||||
}
|
||||
|
||||
client.Links, err = json.MarshalIndent(newClientLinks, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = tx.Save(&client).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
+23
-12
@@ -123,9 +123,10 @@ func (s *ConfigService) StopCore() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *ConfigService) Save(obj string, act string, data json.RawMessage, userLinks json.RawMessage, loginUser string, hostname string) ([]string, error) {
|
||||
func (s *ConfigService) Save(obj string, act string, data json.RawMessage, loginUser string, hostname string) ([]string, error) {
|
||||
var err error
|
||||
var inboundIds []uint
|
||||
var inboundId uint
|
||||
|
||||
db := database.GetDB()
|
||||
tx := db.Begin()
|
||||
@@ -139,11 +140,11 @@ func (s *ConfigService) Save(obj string, act string, data json.RawMessage, userL
|
||||
|
||||
switch obj {
|
||||
case "clients":
|
||||
inboundIds, err = s.ClientService.Save(tx, act, data)
|
||||
inboundIds, err = s.ClientService.Save(tx, act, data, hostname)
|
||||
case "tls":
|
||||
inboundIds, err = s.TlsService.Save(tx, act, data)
|
||||
case "inbounds":
|
||||
err = s.InboundService.Save(tx, act, data, hostname)
|
||||
inboundId, err = s.InboundService.Save(tx, act, data, hostname)
|
||||
case "outbounds":
|
||||
err = s.OutboundService.Save(tx, act, data)
|
||||
case "endpoints":
|
||||
@@ -161,13 +162,6 @@ func (s *ConfigService) Save(obj string, act string, data json.RawMessage, userL
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(userLinks) > 0 {
|
||||
err = s.ClientService.UpdateLinks(tx, userLinks)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
dt := time.Now().Unix()
|
||||
err = tx.Create(&model.Changes{
|
||||
DateTime: dt,
|
||||
@@ -188,8 +182,25 @@ func (s *ConfigService) Save(obj string, act string, data json.RawMessage, userL
|
||||
// Update side changes
|
||||
|
||||
// Update client links
|
||||
if len(userLinks) > 0 {
|
||||
err = s.ClientService.UpdateLinks(tx, userLinks)
|
||||
if obj == "tls" && len(inboundIds) > 0 {
|
||||
err = s.ClientService.UpdateLinksByInboundChange(tx, inboundIds, hostname)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
objs = append(objs, "clients")
|
||||
}
|
||||
if obj == "inbounds" && act != "add" {
|
||||
switch act {
|
||||
case "edit":
|
||||
err = s.ClientService.UpdateLinksByInboundChange(tx, []uint{inboundId}, hostname)
|
||||
case "del":
|
||||
var tag string
|
||||
err = json.Unmarshal(data, &tag)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = s.ClientService.UpdateClientsOnInboundDelete(tx, inboundId, tag)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+12
-15
@@ -94,8 +94,13 @@ func (j *JsonService) getData(subId string) (*model.Client, []*model.Inbound, er
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
var clientInbounds []uint
|
||||
err = json.Unmarshal(client.Inbounds, &clientInbounds)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
var inbounds []*model.Inbound
|
||||
err = db.Model(model.Inbound{}).Where("tag in ?", client.Inbounds).Find(&inbounds).Error
|
||||
err = db.Model(model.Inbound{}).Where("id in ?", clientInbounds).Find(&inbounds).Error
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -156,22 +161,14 @@ func (j *JsonService) getOutbounds(clientConfig json.RawMessage, inbounds []*mod
|
||||
newOut["server_port"] = int(port)
|
||||
|
||||
// Override TLS
|
||||
newTls, overrideTls := addr["tls"].(bool)
|
||||
if overrideTls {
|
||||
tlsIf := map[string]interface{}{}
|
||||
if newTls {
|
||||
tlsIf["enabled"] = true
|
||||
newSNI, overrideSNI := addr["server_name"].(string)
|
||||
if overrideSNI {
|
||||
tlsIf["server_name"] = newSNI
|
||||
}
|
||||
newInsecure, overrideInsecure := addr["insecure"].(bool)
|
||||
if overrideInsecure {
|
||||
tlsIf["insecure"] = newInsecure
|
||||
}
|
||||
outTls, _ := newOut["tls"].(map[string]interface{})
|
||||
if addrTls, ok := addr["tls"].(map[string]interface{}); ok {
|
||||
for key, value := range addrTls {
|
||||
outTls[key] = value
|
||||
}
|
||||
newOut["tls"] = tlsIf
|
||||
}
|
||||
newOut["tls"] = outTls
|
||||
|
||||
remark, _ := addr["remark"].(string)
|
||||
newTag := fmt.Sprintf("%d.%s%s", index+1, tag, remark)
|
||||
newOut["tag"] = newTag
|
||||
|
||||
@@ -0,0 +1,510 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"s-ui/database/model"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var InboundTypeWithLink = []string{"shadowsocks", "naive", "hysteria", "hysteria2", "tuic", "vless", "trojan", "vmess"}
|
||||
|
||||
func LinkGenerator(clientConfig json.RawMessage, i *model.Inbound, hostname string) []string {
|
||||
inbound, err := i.MarshalFull()
|
||||
if err != nil {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
var tls map[string]interface{}
|
||||
if i.TlsId > 0 {
|
||||
json.Unmarshal(i.Tls.Client, &tls)
|
||||
}
|
||||
|
||||
var userConfig map[string]map[string]interface{}
|
||||
if err := json.Unmarshal(clientConfig, &userConfig); err != nil {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
var Addrs []map[string]interface{}
|
||||
json.Unmarshal(i.Addrs, &Addrs)
|
||||
fmt.Printf("AddrsArray: %+v\n", Addrs)
|
||||
if len(Addrs) == 0 {
|
||||
Addrs = append(Addrs, map[string]interface{}{
|
||||
"server": hostname,
|
||||
"server_port": (*inbound)["listen_port"],
|
||||
"remark": i.Tag,
|
||||
})
|
||||
if i.TlsId > 0 {
|
||||
Addrs[0]["tls"] = tls
|
||||
}
|
||||
} else {
|
||||
for index, addr := range Addrs {
|
||||
addrRemark, _ := addr["remark"].(string)
|
||||
Addrs[index]["remark"] = i.Tag + addrRemark
|
||||
if addrTls, ok := addr["tls"].(map[string]interface{}); ok {
|
||||
newTls := map[string]interface{}{}
|
||||
if oldTls, hasOldTls := tls["tls"].(map[string]interface{}); hasOldTls {
|
||||
for k, v := range oldTls {
|
||||
newTls[k] = v
|
||||
}
|
||||
}
|
||||
// Override tls
|
||||
for k, v := range addrTls {
|
||||
newTls[k] = v
|
||||
}
|
||||
Addrs[index]["tls"] = newTls
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch i.Type {
|
||||
case "shadowsocks":
|
||||
return shadowsocksLink(userConfig, *inbound, Addrs)
|
||||
case "naive":
|
||||
return naiveLink(userConfig["naive"], *inbound, Addrs)
|
||||
case "hysteria":
|
||||
return hysteriaLink(userConfig["hysteria"], *inbound, Addrs)
|
||||
case "hysteria2":
|
||||
return hysteria2Link(userConfig["hysteria2"], *inbound, Addrs)
|
||||
case "tuic":
|
||||
return tuicLink(userConfig["tuic"], *inbound, Addrs)
|
||||
case "vless":
|
||||
return vlessLink(userConfig["vless"], *inbound, Addrs)
|
||||
case "trojan":
|
||||
return trojanLink(userConfig["trojan"], *inbound, Addrs)
|
||||
case "vmess":
|
||||
return vmessLink(userConfig["vmess"], *inbound, Addrs)
|
||||
}
|
||||
|
||||
return []string{}
|
||||
}
|
||||
|
||||
func shadowsocksLink(
|
||||
userConfig map[string]map[string]interface{},
|
||||
inbound map[string]interface{},
|
||||
addrs []map[string]interface{}) []string {
|
||||
|
||||
var userPass []string
|
||||
method, _ := inbound["method"].(string)
|
||||
var pass string
|
||||
if method == "2022-blake3-aes-128-gcm" {
|
||||
pass, _ = userConfig["shadowsocks16"]["password"].(string)
|
||||
} else {
|
||||
pass, _ = userConfig["shadowsocks"]["password"].(string)
|
||||
}
|
||||
userPass = append(userPass, pass)
|
||||
|
||||
if strings.HasPrefix(method, "2022") {
|
||||
inbPass, _ := inbound["password"].(string)
|
||||
userPass = append(userPass, inbPass)
|
||||
}
|
||||
|
||||
uriBase := fmt.Sprintf("ss://%s", toBase64([]byte(fmt.Sprintf("%s:%s", method, strings.Join(userPass, ":")))))
|
||||
|
||||
var links []string
|
||||
for _, addr := range addrs {
|
||||
port, _ := addr["server_port"].(float64)
|
||||
links = append(links, fmt.Sprintf("%s@%s:%d", uriBase, addr["server"].(string), uint(port)))
|
||||
}
|
||||
return links
|
||||
}
|
||||
|
||||
func naiveLink(
|
||||
userConfig map[string]interface{},
|
||||
inbound map[string]interface{},
|
||||
addrs []map[string]interface{}) []string {
|
||||
|
||||
password, _ := userConfig["password"].(string)
|
||||
username, _ := userConfig["username"].(string)
|
||||
|
||||
baseUri := "http2://"
|
||||
var links []string
|
||||
|
||||
for _, addr := range addrs {
|
||||
params := map[string]string{}
|
||||
params["padding"] = "1"
|
||||
if tls, ok := addr["tls"].(map[string]interface{}); ok {
|
||||
if sni, ok := tls["server_name"].(string); ok {
|
||||
params["peer"] = sni
|
||||
}
|
||||
if alpn, ok := tls["alpn"].([]interface{}); ok {
|
||||
alpnList := make([]string, len(alpn))
|
||||
for i, v := range alpn {
|
||||
alpnList[i] = v.(string)
|
||||
}
|
||||
params["alpn"] = strings.Join(alpnList, ",")
|
||||
}
|
||||
if insecure, ok := tls["insecure"].(bool); ok && insecure {
|
||||
params["allowInsecure"] = "1"
|
||||
}
|
||||
}
|
||||
if tfo, ok := inbound["tcp_fast_open"].(bool); ok && tfo {
|
||||
params["tfo"] = "1"
|
||||
} else {
|
||||
params["tfo"] = "0"
|
||||
}
|
||||
|
||||
port, _ := addr["server_port"].(float64)
|
||||
uri := baseUri + toBase64([]byte(fmt.Sprintf("%s:%s@%s:%d", username, password, addr["server"].(string), uint(port))))
|
||||
links = append(links, addParams(uri, params, addr["remark"].(string)))
|
||||
}
|
||||
return links
|
||||
}
|
||||
|
||||
func hysteriaLink(
|
||||
userConfig map[string]interface{},
|
||||
inbound map[string]interface{},
|
||||
addrs []map[string]interface{}) []string {
|
||||
|
||||
baseUri := "hysteria://"
|
||||
var links []string
|
||||
|
||||
for _, addr := range addrs {
|
||||
params := map[string]string{}
|
||||
if upmbps, ok := inbound["up_mbps"].(string); ok {
|
||||
params["up_mbps"] = upmbps
|
||||
}
|
||||
if downmbps, ok := inbound["down_mbps"].(string); ok {
|
||||
params["down_mbps"] = downmbps
|
||||
}
|
||||
if auth, ok := userConfig["auth_str"].(string); ok {
|
||||
params["auth"] = auth
|
||||
}
|
||||
if tls, ok := addr["tls"].(map[string]interface{}); ok {
|
||||
if sni, ok := tls["server_name"].(string); ok {
|
||||
params["peer"] = sni
|
||||
}
|
||||
if alpn, ok := tls["alpn"].([]interface{}); ok {
|
||||
alpnList := make([]string, len(alpn))
|
||||
for i, v := range alpn {
|
||||
alpnList[i] = v.(string)
|
||||
}
|
||||
params["alpn"] = strings.Join(alpnList, ",")
|
||||
}
|
||||
if insecure, ok := tls["insecure"].(bool); ok && insecure {
|
||||
params["allowInsecure"] = "1"
|
||||
}
|
||||
}
|
||||
if obfs, ok := inbound["obfs"].(string); ok {
|
||||
params["obfs"] = obfs
|
||||
}
|
||||
if tfo, ok := inbound["tcp_fast_open"].(bool); ok && tfo {
|
||||
params["fastopen"] = "1"
|
||||
} else {
|
||||
params["fastopen"] = "0"
|
||||
}
|
||||
|
||||
port, _ := addr["server_port"].(float64)
|
||||
uri := fmt.Sprintf("%s%s:%d", baseUri, addr["server"].(string), uint(port))
|
||||
links = append(links, addParams(uri, params, addr["remark"].(string)))
|
||||
}
|
||||
|
||||
return links
|
||||
}
|
||||
|
||||
func hysteria2Link(
|
||||
userConfig map[string]interface{},
|
||||
inbound map[string]interface{},
|
||||
addrs []map[string]interface{}) []string {
|
||||
|
||||
password, _ := userConfig["password"].(string)
|
||||
baseUri := fmt.Sprintf("%s%s@", "hysteria2://", password)
|
||||
var links []string
|
||||
|
||||
for _, addr := range addrs {
|
||||
params := map[string]string{}
|
||||
if upmbps, ok := inbound["up_mbps"].(string); ok {
|
||||
params["up_mbps"] = upmbps
|
||||
}
|
||||
if downmbps, ok := inbound["down_mbps"].(string); ok {
|
||||
params["down_mbps"] = downmbps
|
||||
}
|
||||
if tls, ok := addr["tls"].(map[string]interface{}); ok {
|
||||
if sni, ok := tls["server_name"].(string); ok {
|
||||
params["sni"] = sni
|
||||
}
|
||||
if alpn, ok := tls["alpn"].([]interface{}); ok {
|
||||
alpnList := make([]string, len(alpn))
|
||||
for i, v := range alpn {
|
||||
alpnList[i] = v.(string)
|
||||
}
|
||||
params["alpn"] = strings.Join(alpnList, ",")
|
||||
}
|
||||
if insecure, ok := tls["insecure"].(bool); ok && insecure {
|
||||
params["allowInsecure"] = "1"
|
||||
}
|
||||
}
|
||||
if obfs, ok := inbound["obfs"].(map[string]interface{}); ok {
|
||||
if obfsType, ok := obfs["type"].(string); ok {
|
||||
params["obfs"] = obfsType
|
||||
}
|
||||
if obfsPassword, ok := obfs["password"].(string); ok {
|
||||
params["obfs-password"] = obfsPassword
|
||||
}
|
||||
}
|
||||
if tfo, ok := inbound["tcp_fast_open"].(bool); ok && tfo {
|
||||
params["fastopen"] = "1"
|
||||
} else {
|
||||
params["fastopen"] = "0"
|
||||
}
|
||||
|
||||
port, _ := addr["server_port"].(float64)
|
||||
uri := fmt.Sprintf("%s%s:%d", baseUri, addr["server"].(string), uint(port))
|
||||
links = append(links, addParams(uri, params, addr["remark"].(string)))
|
||||
}
|
||||
|
||||
return links
|
||||
}
|
||||
|
||||
func tuicLink(
|
||||
userConfig map[string]interface{},
|
||||
inbound map[string]interface{},
|
||||
addrs []map[string]interface{}) []string {
|
||||
|
||||
password, _ := userConfig["password"].(string)
|
||||
uuid, _ := userConfig["uuid"].(string)
|
||||
baseUri := fmt.Sprintf("%s%s:%s@", "tuic://", uuid, password)
|
||||
var links []string
|
||||
|
||||
for _, addr := range addrs {
|
||||
params := map[string]string{}
|
||||
if tls, ok := addr["tls"].(map[string]interface{}); ok {
|
||||
if sni, ok := tls["server_name"].(string); ok {
|
||||
params["sni"] = sni
|
||||
}
|
||||
if alpn, ok := tls["alpn"].([]interface{}); ok {
|
||||
alpnList := make([]string, len(alpn))
|
||||
for i, v := range alpn {
|
||||
alpnList[i] = v.(string)
|
||||
}
|
||||
params["alpn"] = strings.Join(alpnList, ",")
|
||||
}
|
||||
if insecure, ok := tls["insecure"].(bool); ok && insecure {
|
||||
params["allowInsecure"] = "1"
|
||||
}
|
||||
if disableSni, ok := tls["disable_sni"].(bool); ok && disableSni {
|
||||
params["disableSni"] = "1"
|
||||
}
|
||||
}
|
||||
if congestionControl, ok := inbound["congestion_control"].(string); ok {
|
||||
params["congestion_control"] = congestionControl
|
||||
}
|
||||
|
||||
port, _ := addr["server_port"].(float64)
|
||||
uri := fmt.Sprintf("%s%s:%d", baseUri, addr["server"].(string), uint(port))
|
||||
links = append(links, addParams(uri, params, addr["remark"].(string)))
|
||||
}
|
||||
|
||||
return links
|
||||
}
|
||||
|
||||
func vlessLink(
|
||||
userConfig map[string]interface{},
|
||||
inbound map[string]interface{},
|
||||
addrs []map[string]interface{}) []string {
|
||||
|
||||
uuid, _ := userConfig["uuid"].(string)
|
||||
baseParams := getTransportParams(inbound["transport"])
|
||||
var links []string
|
||||
|
||||
for _, addr := range addrs {
|
||||
params := baseParams
|
||||
if tls, ok := addr["tls"].(map[string]interface{}); ok && tls["enabled"].(bool) {
|
||||
if reality, ok := tls["reality"].(map[string]interface{}); ok && reality["enabled"].(bool) {
|
||||
params["security"] = "reality"
|
||||
if pbk, ok := reality["public_key"].(string); ok {
|
||||
params["pbk"] = pbk
|
||||
}
|
||||
if sid, ok := reality["short_id"].(string); ok {
|
||||
params["sid"] = sid
|
||||
}
|
||||
} else {
|
||||
params["security"] = "tls"
|
||||
if insecure, ok := tls["insecure"].(bool); ok && insecure {
|
||||
params["allowInsecure"] = "1"
|
||||
}
|
||||
if flow, ok := userConfig["flow"].(string); ok {
|
||||
params["flow"] = flow
|
||||
}
|
||||
}
|
||||
if sni, ok := tls["server_name"].(string); ok {
|
||||
params["sni"] = sni
|
||||
}
|
||||
if alpn, ok := tls["alpn"].([]interface{}); ok {
|
||||
alpnList := make([]string, len(alpn))
|
||||
for i, v := range alpn {
|
||||
alpnList[i] = v.(string)
|
||||
}
|
||||
params["alpn"] = strings.Join(alpnList, ",")
|
||||
}
|
||||
}
|
||||
port, _ := addr["server_port"].(float64)
|
||||
uri := fmt.Sprintf("vless://%s@%s:%d", uuid, addr["server"].(string), uint(port))
|
||||
uri = addParams(uri, params, addr["remark"].(string))
|
||||
links = append(links, uri)
|
||||
}
|
||||
|
||||
return links
|
||||
}
|
||||
|
||||
func trojanLink(
|
||||
userConfig map[string]interface{},
|
||||
inbound map[string]interface{},
|
||||
addrs []map[string]interface{}) []string {
|
||||
password, _ := userConfig["password"].(string)
|
||||
baseParams := getTransportParams(inbound["transport"])
|
||||
var links []string
|
||||
|
||||
for _, addr := range addrs {
|
||||
params := baseParams
|
||||
if tls, ok := addr["tls"].(map[string]interface{}); ok && tls["enabled"].(bool) {
|
||||
if reality, ok := tls["reality"].(map[string]interface{}); ok && reality["enabled"].(bool) {
|
||||
params["security"] = "reality"
|
||||
if pbk, ok := reality["public_key"].(string); ok {
|
||||
params["pbk"] = pbk
|
||||
}
|
||||
if sid, ok := reality["short_id"].(string); ok {
|
||||
params["sid"] = sid
|
||||
}
|
||||
} else {
|
||||
params["security"] = "tls"
|
||||
if insecure, ok := tls["insecure"].(bool); ok && insecure {
|
||||
params["allowInsecure"] = "1"
|
||||
}
|
||||
}
|
||||
if sni, ok := tls["server_name"].(string); ok {
|
||||
params["sni"] = sni
|
||||
}
|
||||
if alpn, ok := tls["alpn"].([]interface{}); ok {
|
||||
alpnList := make([]string, len(alpn))
|
||||
for i, v := range alpn {
|
||||
alpnList[i] = v.(string)
|
||||
}
|
||||
params["alpn"] = strings.Join(alpnList, ",")
|
||||
}
|
||||
}
|
||||
port, _ := addr["server_port"].(float64)
|
||||
uri := fmt.Sprintf("trojan://%s@%s:%d", password, addr["server"].(string), uint(port))
|
||||
uri = addParams(uri, params, addr["remark"].(string))
|
||||
links = append(links, uri)
|
||||
}
|
||||
|
||||
return links
|
||||
}
|
||||
|
||||
func vmessLink(
|
||||
userConfig map[string]interface{},
|
||||
inbound map[string]interface{},
|
||||
addrs []map[string]interface{}) []string {
|
||||
|
||||
uuid, _ := userConfig["uuid"].(string)
|
||||
trasportParams := getTransportParams(inbound["transport"])
|
||||
var links []string
|
||||
|
||||
baseParams := map[string]interface{}{
|
||||
"v": 2,
|
||||
"id": uuid,
|
||||
"aid": 0,
|
||||
}
|
||||
if trasportParams["type"] == "http" || trasportParams["type"] == "tcp" {
|
||||
baseParams["net"] = "tcp"
|
||||
if trasportParams["type"] == "http" {
|
||||
baseParams["type"] = "http"
|
||||
}
|
||||
} else {
|
||||
baseParams["net"] = trasportParams["type"]
|
||||
}
|
||||
|
||||
for _, addr := range addrs {
|
||||
obj := baseParams
|
||||
obj["addr"], _ = addr["server"].(string)
|
||||
port, _ := addr["server_port"].(float64)
|
||||
obj["port"] = uint(port)
|
||||
obj["ps"], _ = addr["remark"].(string)
|
||||
if trasportParams["host"] != "" {
|
||||
obj["host"] = trasportParams["host"]
|
||||
}
|
||||
if trasportParams["path"] != "" {
|
||||
obj["path"] = trasportParams["path"]
|
||||
}
|
||||
if tls, ok := addr["tls"].(map[string]interface{}); ok && tls["enabled"].(bool) {
|
||||
obj["tls"] = "tls"
|
||||
if insecure, ok := tls["insecure"].(bool); ok && insecure {
|
||||
obj["allowInsecure"] = 1
|
||||
}
|
||||
if sni, ok := tls["server_name"].(string); ok {
|
||||
obj["sni"] = sni
|
||||
}
|
||||
} else {
|
||||
obj["tls"] = "none"
|
||||
}
|
||||
|
||||
jsonStr, _ := json.MarshalIndent(obj, "", " ")
|
||||
|
||||
uri := fmt.Sprintf("vmess://%s", toBase64(jsonStr))
|
||||
links = append(links, uri)
|
||||
}
|
||||
return links
|
||||
}
|
||||
|
||||
func toBase64(d []byte) string {
|
||||
return base64.StdEncoding.EncodeToString([]byte(d))
|
||||
}
|
||||
|
||||
func addParams(uri string, params map[string]string, remark string) string {
|
||||
URL, _ := url.Parse(uri)
|
||||
q := URL.Query()
|
||||
for k, v := range params {
|
||||
q.Add(k, v)
|
||||
}
|
||||
URL.RawQuery = q.Encode()
|
||||
URL.Fragment = remark
|
||||
return URL.String()
|
||||
}
|
||||
|
||||
func getTransportParams(t interface{}) map[string]string {
|
||||
params := map[string]string{}
|
||||
trasport, _ := t.(map[string]interface{})
|
||||
if transportType, ok := trasport["type"].(string); ok {
|
||||
params["type"] = transportType
|
||||
} else {
|
||||
params["type"] = "tcp"
|
||||
return params
|
||||
}
|
||||
switch params["type"] {
|
||||
case "http":
|
||||
if host, ok := trasport["host"].([]interface{}); ok {
|
||||
var hosts []string
|
||||
for _, v := range host {
|
||||
hosts = append(hosts, v.(string))
|
||||
}
|
||||
params["host"] = strings.Join(hosts, ",")
|
||||
}
|
||||
if path, ok := trasport["path"].(string); ok {
|
||||
params["path"] = path
|
||||
}
|
||||
case "ws":
|
||||
if path, ok := trasport["path"].(string); ok {
|
||||
params["path"] = path
|
||||
}
|
||||
if headers, ok := trasport["headers"].(map[string]interface{}); ok {
|
||||
if host, ok := headers["Host"].(string); ok {
|
||||
params["peer"] = host
|
||||
}
|
||||
}
|
||||
case "grpc":
|
||||
if serviceName, ok := trasport["service_name"].(string); ok {
|
||||
params["serviceName"] = serviceName
|
||||
}
|
||||
case "httpupgrade":
|
||||
if host, ok := trasport["host"].(string); ok {
|
||||
params["peer"] = host
|
||||
}
|
||||
if path, ok := trasport["path"].(string); ok {
|
||||
params["path"] = path
|
||||
}
|
||||
}
|
||||
return params
|
||||
}
|
||||
Reference in New Issue
Block a user