268 lines
6.3 KiB
Go
268 lines
6.3 KiB
Go
package sub
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"s-ui/database"
|
|
"s-ui/database/model"
|
|
"s-ui/service"
|
|
"s-ui/util"
|
|
)
|
|
|
|
const defaultJson = `
|
|
{
|
|
"inbounds": [
|
|
{
|
|
"type": "tun",
|
|
"address": [
|
|
"172.19.0.1/30",
|
|
"fdfe:dcba:9876::1/126"
|
|
],
|
|
"mtu": 9000,
|
|
"auto_route": true,
|
|
"strict_route": false,
|
|
"sniff": true,
|
|
"endpoint_independent_nat": false,
|
|
"stack": "system",
|
|
"platform": {
|
|
"http_proxy": {
|
|
"enabled": true,
|
|
"server": "127.0.0.1",
|
|
"server_port": 2080
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"type": "mixed",
|
|
"listen": "127.0.0.1",
|
|
"listen_port": 2080,
|
|
"sniff": true,
|
|
"users": []
|
|
}
|
|
]
|
|
}
|
|
`
|
|
|
|
type JsonService struct {
|
|
service.SettingService
|
|
LinkService
|
|
}
|
|
|
|
func (j *JsonService) GetJson(subId string, format string) (*string, error) {
|
|
var jsonConfig map[string]interface{}
|
|
|
|
client, inDatas, err := j.getData(subId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
outbounds, outTags, err := j.getOutbounds(client.Config, inDatas)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
links := j.LinkService.GetLinks(&client.Links, "external", "")
|
|
for index, link := range links {
|
|
json, tag, err := util.GetOutbound(link, index)
|
|
if err == nil && len(tag) > 0 {
|
|
*outbounds = append(*outbounds, *json)
|
|
*outTags = append(*outTags, tag)
|
|
}
|
|
}
|
|
|
|
j.addDefaultOutbounds(outbounds, outTags)
|
|
|
|
err = json.Unmarshal([]byte(defaultJson), &jsonConfig)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
jsonConfig["outbounds"] = outbounds
|
|
|
|
// Add other objects from settings
|
|
j.addOthers(&jsonConfig)
|
|
|
|
result, _ := json.MarshalIndent(jsonConfig, "", " ")
|
|
resultStr := string(result)
|
|
return &resultStr, nil
|
|
}
|
|
|
|
func (j *JsonService) getData(subId string) (*model.Client, *[]model.InboundData, error) {
|
|
db := database.GetDB()
|
|
client := &model.Client{}
|
|
err := db.Model(model.Client{}).Where("enable = true and name = ?", subId).First(client).Error
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
var inbounds []string
|
|
err = json.Unmarshal(client.Inbounds, &inbounds)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
inDatas := &[]model.InboundData{}
|
|
err = db.Model(model.InboundData{}).Where("tag in ?", inbounds).Find(&inDatas).Error
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
return client, inDatas, nil
|
|
}
|
|
|
|
func (j *JsonService) getOutbounds(clientConfig json.RawMessage, inDatas *[]model.InboundData) (*[]map[string]interface{}, *[]string, error) {
|
|
var outbounds []map[string]interface{}
|
|
var configs map[string]interface{}
|
|
var outTags []string
|
|
|
|
err := json.Unmarshal(clientConfig, &configs)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
for _, inData := range *inDatas {
|
|
if len(inData.OutJson) < 5 {
|
|
continue
|
|
}
|
|
var outbound map[string]interface{}
|
|
err = json.Unmarshal(inData.OutJson, &outbound)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
protocol, _ := outbound["type"].(string)
|
|
config, _ := configs[protocol].(map[string]interface{})
|
|
for key, value := range config {
|
|
if key != "alterId" && key != "name" && key != "username" {
|
|
outbound[key] = value
|
|
}
|
|
}
|
|
|
|
var addrs []map[string]interface{}
|
|
err = json.Unmarshal(inData.Addrs, &addrs)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
tag := outbound["tag"].(string)
|
|
if len(addrs) == 0 {
|
|
outTags = append(outTags, tag)
|
|
outbounds = append(outbounds, outbound)
|
|
} else {
|
|
for index, addr := range addrs {
|
|
// Copy original config
|
|
newOut := make(map[string]interface{}, len(outbound))
|
|
for key, value := range outbound {
|
|
newOut[key] = value
|
|
}
|
|
// Change and push copied config
|
|
newOut["server"], _ = addr["server"].(string)
|
|
port, _ := addr["server_port"].(float64)
|
|
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
|
|
}
|
|
}
|
|
newOut["tls"] = tlsIf
|
|
}
|
|
remark, _ := addr["remark"].(string)
|
|
newTag := fmt.Sprintf("%d.%s%s", index+1, tag, remark)
|
|
outTags = append(outTags, newTag)
|
|
newOut["tag"] = newTag
|
|
outbounds = append(outbounds, newOut)
|
|
}
|
|
}
|
|
}
|
|
return &outbounds, &outTags, nil
|
|
}
|
|
|
|
func (j *JsonService) addDefaultOutbounds(outbounds *[]map[string]interface{}, outTags *[]string) {
|
|
outbound := []map[string]interface{}{
|
|
{
|
|
"outbounds": append([]string{"auto", "direct"}, *outTags...),
|
|
"tag": "proxy",
|
|
"type": "selector",
|
|
},
|
|
{
|
|
"tag": "auto",
|
|
"type": "urltest",
|
|
"outbounds": outTags,
|
|
"url": "http://www.gstatic.com/generate_204",
|
|
"interval": "10m",
|
|
"tolerance": 50,
|
|
},
|
|
{
|
|
"type": "direct",
|
|
"tag": "direct",
|
|
},
|
|
{
|
|
"type": "dns",
|
|
"tag": "dns-out",
|
|
},
|
|
{
|
|
"type": "block",
|
|
"tag": "block",
|
|
},
|
|
}
|
|
*outbounds = append(outbound, *outbounds...)
|
|
}
|
|
|
|
func (j *JsonService) addOthers(jsonConfig *map[string]interface{}) error {
|
|
rules := []interface{}{
|
|
map[string]interface{}{
|
|
"clash_mode": "Direct",
|
|
"outbound": "direct",
|
|
},
|
|
map[string]interface{}{
|
|
"clash_mode": "Global",
|
|
"outbound": "proxy",
|
|
},
|
|
}
|
|
route := map[string]interface{}{
|
|
"auto_detect_interface": true,
|
|
"final": "proxy",
|
|
"rules": rules,
|
|
}
|
|
|
|
othersStr, err := j.SettingService.GetSubJsonExt()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if len(othersStr) == 0 {
|
|
(*jsonConfig)["route"] = route
|
|
return nil
|
|
}
|
|
var othersJson map[string]interface{}
|
|
err = json.Unmarshal([]byte(othersStr), &othersJson)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if _, ok := othersJson["log"]; ok {
|
|
(*jsonConfig)["log"] = othersJson["log"]
|
|
}
|
|
if _, ok := othersJson["dns"]; ok {
|
|
(*jsonConfig)["dns"] = othersJson["dns"]
|
|
}
|
|
if _, ok := othersJson["inbounds"]; ok {
|
|
(*jsonConfig)["inbounds"] = othersJson["inbounds"]
|
|
}
|
|
if _, ok := othersJson["experimental"]; ok {
|
|
(*jsonConfig)["experimental"] = othersJson["experimental"]
|
|
}
|
|
if _, ok := othersJson["rule_set"]; ok {
|
|
route["rule_set"] = othersJson["rule_set"]
|
|
}
|
|
if settingRules, ok := othersJson["rules"].([]interface{}); ok {
|
|
route["rules"] = append(rules, settingRules...)
|
|
}
|
|
(*jsonConfig)["route"] = route
|
|
|
|
return nil
|
|
}
|