| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | package sub | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	_ "embed" | 
					
						
							|  |  |  | 	"encoding/json" | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2024-03-10 21:31:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 	"x-ui/database/model" | 
					
						
							|  |  |  | 	"x-ui/logger" | 
					
						
							|  |  |  | 	"x-ui/util/json_util" | 
					
						
							|  |  |  | 	"x-ui/util/random" | 
					
						
							|  |  |  | 	"x-ui/web/service" | 
					
						
							|  |  |  | 	"x-ui/xray" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //go:embed default.json
 | 
					
						
							|  |  |  | var defaultJson string | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type SubJsonService struct { | 
					
						
							| 
									
										
										
										
											2025-03-12 19:13:51 +00:00
										 |  |  | 	configJson       map[string]any | 
					
						
							| 
									
										
										
										
											2024-03-11 12:44:24 +00:00
										 |  |  | 	defaultOutbounds []json_util.RawMessage | 
					
						
							|  |  |  | 	fragment         string | 
					
						
							| 
									
										
										
										
											2025-01-01 17:42:50 +00:00
										 |  |  | 	noises           string | 
					
						
							| 
									
										
										
										
											2024-03-12 16:14:51 +00:00
										 |  |  | 	mux              string | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	inboundService service.InboundService | 
					
						
							| 
									
										
										
										
											2024-03-11 12:44:24 +00:00
										 |  |  | 	SubService     *SubService | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-17 07:33:44 +00:00
										 |  |  | func NewSubJsonService(fragment string, noises string, mux string, rules string, subService *SubService) *SubJsonService { | 
					
						
							| 
									
										
										
										
											2025-03-12 19:13:51 +00:00
										 |  |  | 	var configJson map[string]any | 
					
						
							| 
									
										
										
										
											2024-03-11 12:44:24 +00:00
										 |  |  | 	var defaultOutbounds []json_util.RawMessage | 
					
						
							|  |  |  | 	json.Unmarshal([]byte(defaultJson), &configJson) | 
					
						
							| 
									
										
										
										
											2025-03-12 19:13:51 +00:00
										 |  |  | 	if outboundSlices, ok := configJson["outbounds"].([]any); ok { | 
					
						
							| 
									
										
										
										
											2024-03-11 12:44:24 +00:00
										 |  |  | 		for _, defaultOutbound := range outboundSlices { | 
					
						
							|  |  |  | 			jsonBytes, _ := json.Marshal(defaultOutbound) | 
					
						
							|  |  |  | 			defaultOutbounds = append(defaultOutbounds, jsonBytes) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-12 16:14:51 +00:00
										 |  |  | 	if rules != "" { | 
					
						
							| 
									
										
										
										
											2025-03-12 19:13:51 +00:00
										 |  |  | 		var newRules []any | 
					
						
							|  |  |  | 		routing, _ := configJson["routing"].(map[string]any) | 
					
						
							|  |  |  | 		defaultRules, _ := routing["rules"].([]any) | 
					
						
							| 
									
										
										
										
											2024-03-12 16:14:51 +00:00
										 |  |  | 		json.Unmarshal([]byte(rules), &newRules) | 
					
						
							|  |  |  | 		defaultRules = append(newRules, defaultRules...) | 
					
						
							|  |  |  | 		routing["rules"] = defaultRules | 
					
						
							|  |  |  | 		configJson["routing"] = routing | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-11 12:44:24 +00:00
										 |  |  | 	if fragment != "" { | 
					
						
							|  |  |  | 		defaultOutbounds = append(defaultOutbounds, json_util.RawMessage(fragment)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-17 07:33:44 +00:00
										 |  |  | 	if noises != "" { | 
					
						
							|  |  |  | 		defaultOutbounds = append(defaultOutbounds, json_util.RawMessage(noises)) | 
					
						
							| 
									
										
										
										
											2024-08-29 09:27:43 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 	return &SubJsonService{ | 
					
						
							| 
									
										
										
										
											2024-03-11 12:44:24 +00:00
										 |  |  | 		configJson:       configJson, | 
					
						
							|  |  |  | 		defaultOutbounds: defaultOutbounds, | 
					
						
							|  |  |  | 		fragment:         fragment, | 
					
						
							| 
									
										
										
										
											2025-01-01 17:42:50 +00:00
										 |  |  | 		noises:           noises, | 
					
						
							| 
									
										
										
										
											2024-03-12 16:14:51 +00:00
										 |  |  | 		mux:              mux, | 
					
						
							| 
									
										
										
										
											2024-03-11 12:44:24 +00:00
										 |  |  | 		SubService:       subService, | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (s *SubJsonService) GetJson(subId string, host string) (string, string, error) { | 
					
						
							|  |  |  | 	inbounds, err := s.SubService.getInboundsBySubId(subId) | 
					
						
							|  |  |  | 	if err != nil || len(inbounds) == 0 { | 
					
						
							|  |  |  | 		return "", "", err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var header string | 
					
						
							|  |  |  | 	var traffic xray.ClientTraffic | 
					
						
							|  |  |  | 	var clientTraffics []xray.ClientTraffic | 
					
						
							| 
									
										
										
										
											2024-03-11 12:44:24 +00:00
										 |  |  | 	var configArray []json_util.RawMessage | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Prepare Inbounds
 | 
					
						
							|  |  |  | 	for _, inbound := range inbounds { | 
					
						
							|  |  |  | 		clients, err := s.inboundService.GetClients(inbound) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			logger.Error("SubJsonService - GetClients: Unable to get clients from inbound") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if clients == nil { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if len(inbound.Listen) > 0 && inbound.Listen[0] == '@' { | 
					
						
							| 
									
										
										
										
											2024-03-11 12:44:24 +00:00
										 |  |  | 			listen, port, streamSettings, err := s.SubService.getFallbackMaster(inbound.Listen, inbound.StreamSettings) | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 			if err == nil { | 
					
						
							|  |  |  | 				inbound.Listen = listen | 
					
						
							|  |  |  | 				inbound.Port = port | 
					
						
							|  |  |  | 				inbound.StreamSettings = streamSettings | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for _, client := range clients { | 
					
						
							|  |  |  | 			if client.Enable && client.SubID == subId { | 
					
						
							|  |  |  | 				clientTraffics = append(clientTraffics, s.SubService.getClientTraffics(inbound.ClientStats, client.Email)) | 
					
						
							| 
									
										
										
										
											2024-03-11 12:44:24 +00:00
										 |  |  | 				newConfigs := s.getConfig(inbound, client, host) | 
					
						
							|  |  |  | 				configArray = append(configArray, newConfigs...) | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-11 12:44:24 +00:00
										 |  |  | 	if len(configArray) == 0 { | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 		return "", "", nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Prepare statistics
 | 
					
						
							|  |  |  | 	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 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Combile outbounds
 | 
					
						
							| 
									
										
										
										
											2024-04-01 07:52:10 +00:00
										 |  |  | 	var finalJson []byte | 
					
						
							|  |  |  | 	if len(configArray) == 1 { | 
					
						
							|  |  |  | 		finalJson, _ = json.MarshalIndent(configArray[0], "", "  ") | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		finalJson, _ = json.MarshalIndent(configArray, "", "  ") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	header = fmt.Sprintf("upload=%d; download=%d; total=%d; expire=%d", traffic.Up, traffic.Down, traffic.Total, traffic.ExpiryTime/1000) | 
					
						
							|  |  |  | 	return string(finalJson), header, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-11 12:44:24 +00:00
										 |  |  | func (s *SubJsonService) getConfig(inbound *model.Inbound, client model.Client, host string) []json_util.RawMessage { | 
					
						
							|  |  |  | 	var newJsonArray []json_util.RawMessage | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 	stream := s.streamData(inbound.StreamSettings) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-12 19:13:51 +00:00
										 |  |  | 	externalProxies, ok := stream["externalProxy"].([]any) | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 	if !ok || len(externalProxies) == 0 { | 
					
						
							| 
									
										
										
										
											2025-03-12 19:13:51 +00:00
										 |  |  | 		externalProxies = []any{ | 
					
						
							|  |  |  | 			map[string]any{ | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 				"forceTls": "same", | 
					
						
							|  |  |  | 				"dest":     host, | 
					
						
							|  |  |  | 				"port":     float64(inbound.Port), | 
					
						
							| 
									
										
										
										
											2024-03-11 12:44:24 +00:00
										 |  |  | 				"remark":   "", | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 			}, | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	delete(stream, "externalProxy") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, ep := range externalProxies { | 
					
						
							| 
									
										
										
										
											2025-03-12 19:13:51 +00:00
										 |  |  | 		extPrxy := ep.(map[string]any) | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 		inbound.Listen = extPrxy["dest"].(string) | 
					
						
							|  |  |  | 		inbound.Port = int(extPrxy["port"].(float64)) | 
					
						
							|  |  |  | 		newStream := stream | 
					
						
							|  |  |  | 		switch extPrxy["forceTls"].(string) { | 
					
						
							|  |  |  | 		case "tls": | 
					
						
							|  |  |  | 			if newStream["security"] != "tls" { | 
					
						
							|  |  |  | 				newStream["security"] = "tls" | 
					
						
							| 
									
										
										
										
											2025-03-12 19:13:51 +00:00
										 |  |  | 				newStream["tslSettings"] = map[string]any{} | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		case "none": | 
					
						
							|  |  |  | 			if newStream["security"] != "none" { | 
					
						
							|  |  |  | 				newStream["security"] = "none" | 
					
						
							|  |  |  | 				delete(newStream, "tslSettings") | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		streamSettings, _ := json.MarshalIndent(newStream, "", "  ") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-11 12:44:24 +00:00
										 |  |  | 		var newOutbounds []json_util.RawMessage | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		switch inbound.Protocol { | 
					
						
							|  |  |  | 		case "vmess", "vless": | 
					
						
							|  |  |  | 			newOutbounds = append(newOutbounds, s.genVnext(inbound, streamSettings, client)) | 
					
						
							|  |  |  | 		case "trojan", "shadowsocks": | 
					
						
							|  |  |  | 			newOutbounds = append(newOutbounds, s.genServer(inbound, streamSettings, client)) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		newOutbounds = append(newOutbounds, s.defaultOutbounds...) | 
					
						
							| 
									
										
										
										
											2025-03-12 19:13:51 +00:00
										 |  |  | 		newConfigJson := make(map[string]any) | 
					
						
							| 
									
										
										
										
											2024-03-11 12:44:24 +00:00
										 |  |  | 		for key, value := range s.configJson { | 
					
						
							|  |  |  | 			newConfigJson[key] = value | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-03-11 12:44:24 +00:00
										 |  |  | 		newConfigJson["outbounds"] = newOutbounds | 
					
						
							|  |  |  | 		newConfigJson["remarks"] = s.SubService.genRemark(inbound, client.Email, extPrxy["remark"].(string)) | 
					
						
							| 
									
										
										
										
											2024-04-01 07:52:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-11 12:44:24 +00:00
										 |  |  | 		newConfig, _ := json.MarshalIndent(newConfigJson, "", "  ") | 
					
						
							|  |  |  | 		newJsonArray = append(newJsonArray, newConfig) | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-11 12:44:24 +00:00
										 |  |  | 	return newJsonArray | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-12 19:13:51 +00:00
										 |  |  | func (s *SubJsonService) streamData(stream string) map[string]any { | 
					
						
							|  |  |  | 	var streamSettings map[string]any | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 	json.Unmarshal([]byte(stream), &streamSettings) | 
					
						
							|  |  |  | 	security, _ := streamSettings["security"].(string) | 
					
						
							|  |  |  | 	if security == "tls" { | 
					
						
							| 
									
										
										
										
											2025-03-12 19:13:51 +00:00
										 |  |  | 		streamSettings["tlsSettings"] = s.tlsData(streamSettings["tlsSettings"].(map[string]any)) | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 	} else if security == "reality" { | 
					
						
							| 
									
										
										
										
											2025-03-12 19:13:51 +00:00
										 |  |  | 		streamSettings["realitySettings"] = s.realityData(streamSettings["realitySettings"].(map[string]any)) | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	delete(streamSettings, "sockopt") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-11 12:44:24 +00:00
										 |  |  | 	if s.fragment != "" { | 
					
						
							| 
									
										
										
										
											2025-01-01 17:42:50 +00:00
										 |  |  | 		streamSettings["sockopt"] = json_util.RawMessage(`{"dialerProxy": "fragment", "tcpKeepAliveIdle": 100, "tcpMptcp": true, "penetrate": true}`) | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// remove proxy protocol
 | 
					
						
							|  |  |  | 	network, _ := streamSettings["network"].(string) | 
					
						
							|  |  |  | 	switch network { | 
					
						
							|  |  |  | 	case "tcp": | 
					
						
							|  |  |  | 		streamSettings["tcpSettings"] = s.removeAcceptProxy(streamSettings["tcpSettings"]) | 
					
						
							|  |  |  | 	case "ws": | 
					
						
							|  |  |  | 		streamSettings["wsSettings"] = s.removeAcceptProxy(streamSettings["wsSettings"]) | 
					
						
							| 
									
										
										
										
											2024-04-01 07:52:10 +00:00
										 |  |  | 	case "httpupgrade": | 
					
						
							|  |  |  | 		streamSettings["httpupgradeSettings"] = s.removeAcceptProxy(streamSettings["httpupgradeSettings"]) | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return streamSettings | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-12 19:13:51 +00:00
										 |  |  | func (s *SubJsonService) removeAcceptProxy(setting any) map[string]any { | 
					
						
							|  |  |  | 	netSettings, ok := setting.(map[string]any) | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 	if ok { | 
					
						
							|  |  |  | 		delete(netSettings, "acceptProxyProtocol") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return netSettings | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-12 19:13:51 +00:00
										 |  |  | func (s *SubJsonService) tlsData(tData map[string]any) map[string]any { | 
					
						
							|  |  |  | 	tlsData := make(map[string]any, 1) | 
					
						
							|  |  |  | 	tlsClientSettings, _ := tData["settings"].(map[string]any) | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	tlsData["serverName"] = tData["serverName"] | 
					
						
							|  |  |  | 	tlsData["alpn"] = tData["alpn"] | 
					
						
							| 
									
										
										
										
											2024-02-23 23:49:28 +00:00
										 |  |  | 	if allowInsecure, ok := tlsClientSettings["allowInsecure"].(bool); ok { | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 		tlsData["allowInsecure"] = allowInsecure | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if fingerprint, ok := tlsClientSettings["fingerprint"].(string); ok { | 
					
						
							|  |  |  | 		tlsData["fingerprint"] = fingerprint | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return tlsData | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-12 19:13:51 +00:00
										 |  |  | func (s *SubJsonService) realityData(rData map[string]any) map[string]any { | 
					
						
							|  |  |  | 	rltyData := make(map[string]any, 1) | 
					
						
							|  |  |  | 	rltyClientSettings, _ := rData["settings"].(map[string]any) | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	rltyData["show"] = false | 
					
						
							|  |  |  | 	rltyData["publicKey"] = rltyClientSettings["publicKey"] | 
					
						
							|  |  |  | 	rltyData["fingerprint"] = rltyClientSettings["fingerprint"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Set random data
 | 
					
						
							|  |  |  | 	rltyData["spiderX"] = "/" + random.Seq(15) | 
					
						
							| 
									
										
										
										
											2025-03-12 19:13:51 +00:00
										 |  |  | 	shortIds, ok := rData["shortIds"].([]any) | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 	if ok && len(shortIds) > 0 { | 
					
						
							| 
									
										
										
										
											2024-09-09 07:46:39 +00:00
										 |  |  | 		rltyData["shortId"] = shortIds[random.Num(len(shortIds))].(string) | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		rltyData["shortId"] = "" | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-03-12 19:13:51 +00:00
										 |  |  | 	serverNames, ok := rData["serverNames"].([]any) | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 	if ok && len(serverNames) > 0 { | 
					
						
							| 
									
										
										
										
											2024-09-09 07:46:39 +00:00
										 |  |  | 		rltyData["serverName"] = serverNames[random.Num(len(serverNames))].(string) | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		rltyData["serverName"] = "" | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return rltyData | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-11 12:44:24 +00:00
										 |  |  | func (s *SubJsonService) genVnext(inbound *model.Inbound, streamSettings json_util.RawMessage, client model.Client) json_util.RawMessage { | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 	outbound := Outbound{} | 
					
						
							|  |  |  | 	usersData := make([]UserVnext, 1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	usersData[0].ID = client.ID | 
					
						
							|  |  |  | 	usersData[0].Level = 8 | 
					
						
							| 
									
										
										
										
											2024-08-10 22:47:44 +00:00
										 |  |  | 	if inbound.Protocol == model.VMESS { | 
					
						
							|  |  |  | 		usersData[0].Security = client.Security | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 	if inbound.Protocol == model.VLESS { | 
					
						
							|  |  |  | 		usersData[0].Flow = client.Flow | 
					
						
							|  |  |  | 		usersData[0].Encryption = "none" | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	vnextData := make([]VnextSetting, 1) | 
					
						
							|  |  |  | 	vnextData[0] = VnextSetting{ | 
					
						
							|  |  |  | 		Address: inbound.Listen, | 
					
						
							|  |  |  | 		Port:    inbound.Port, | 
					
						
							|  |  |  | 		Users:   usersData, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	outbound.Protocol = string(inbound.Protocol) | 
					
						
							| 
									
										
										
										
											2024-03-11 12:44:24 +00:00
										 |  |  | 	outbound.Tag = "proxy" | 
					
						
							| 
									
										
										
										
											2024-03-12 16:14:51 +00:00
										 |  |  | 	if s.mux != "" { | 
					
						
							|  |  |  | 		outbound.Mux = json_util.RawMessage(s.mux) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-03-11 12:44:24 +00:00
										 |  |  | 	outbound.StreamSettings = streamSettings | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 	outbound.Settings = OutboundSettings{ | 
					
						
							|  |  |  | 		Vnext: vnextData, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	result, _ := json.MarshalIndent(outbound, "", "  ") | 
					
						
							|  |  |  | 	return result | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-11 12:44:24 +00:00
										 |  |  | func (s *SubJsonService) genServer(inbound *model.Inbound, streamSettings json_util.RawMessage, client model.Client) json_util.RawMessage { | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 	outbound := Outbound{} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	serverData := make([]ServerSetting, 1) | 
					
						
							|  |  |  | 	serverData[0] = ServerSetting{ | 
					
						
							|  |  |  | 		Address:  inbound.Listen, | 
					
						
							|  |  |  | 		Port:     inbound.Port, | 
					
						
							|  |  |  | 		Level:    8, | 
					
						
							|  |  |  | 		Password: client.Password, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if inbound.Protocol == model.Shadowsocks { | 
					
						
							| 
									
										
										
										
											2025-03-12 19:13:51 +00:00
										 |  |  | 		var inboundSettings map[string]any | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 		json.Unmarshal([]byte(inbound.Settings), &inboundSettings) | 
					
						
							|  |  |  | 		method, _ := inboundSettings["method"].(string) | 
					
						
							|  |  |  | 		serverData[0].Method = method | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// server password in multi-user 2022 protocols
 | 
					
						
							|  |  |  | 		if strings.HasPrefix(method, "2022") { | 
					
						
							|  |  |  | 			if serverPassword, ok := inboundSettings["password"].(string); ok { | 
					
						
							|  |  |  | 				serverData[0].Password = fmt.Sprintf("%s:%s", serverPassword, client.Password) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	outbound.Protocol = string(inbound.Protocol) | 
					
						
							| 
									
										
										
										
											2024-03-11 12:44:24 +00:00
										 |  |  | 	outbound.Tag = "proxy" | 
					
						
							| 
									
										
										
										
											2024-03-12 16:14:51 +00:00
										 |  |  | 	if s.mux != "" { | 
					
						
							|  |  |  | 		outbound.Mux = json_util.RawMessage(s.mux) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-03-11 12:44:24 +00:00
										 |  |  | 	outbound.StreamSettings = streamSettings | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 	outbound.Settings = OutboundSettings{ | 
					
						
							|  |  |  | 		Servers: serverData, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	result, _ := json.MarshalIndent(outbound, "", "  ") | 
					
						
							|  |  |  | 	return result | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type Outbound struct { | 
					
						
							| 
									
										
										
										
											2025-03-12 19:13:51 +00:00
										 |  |  | 	Protocol       string               `json:"protocol"` | 
					
						
							|  |  |  | 	Tag            string               `json:"tag"` | 
					
						
							|  |  |  | 	StreamSettings json_util.RawMessage `json:"streamSettings"` | 
					
						
							|  |  |  | 	Mux            json_util.RawMessage `json:"mux,omitempty"` | 
					
						
							|  |  |  | 	ProxySettings  map[string]any       `json:"proxySettings,omitempty"` | 
					
						
							|  |  |  | 	Settings       OutboundSettings     `json:"settings,omitempty"` | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type OutboundSettings struct { | 
					
						
							|  |  |  | 	Vnext   []VnextSetting  `json:"vnext,omitempty"` | 
					
						
							|  |  |  | 	Servers []ServerSetting `json:"servers,omitempty"` | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type VnextSetting struct { | 
					
						
							|  |  |  | 	Address string      `json:"address"` | 
					
						
							|  |  |  | 	Port    int         `json:"port"` | 
					
						
							|  |  |  | 	Users   []UserVnext `json:"users"` | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type UserVnext struct { | 
					
						
							|  |  |  | 	Encryption string `json:"encryption,omitempty"` | 
					
						
							|  |  |  | 	Flow       string `json:"flow,omitempty"` | 
					
						
							|  |  |  | 	ID         string `json:"id"` | 
					
						
							| 
									
										
										
										
											2024-08-10 22:47:44 +00:00
										 |  |  | 	Security   string `json:"security,omitempty"` | 
					
						
							| 
									
										
										
										
											2024-02-21 10:47:52 +00:00
										 |  |  | 	Level      int    `json:"level"` | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type ServerSetting struct { | 
					
						
							|  |  |  | 	Password string `json:"password"` | 
					
						
							|  |  |  | 	Level    int    `json:"level"` | 
					
						
							|  |  |  | 	Address  string `json:"address"` | 
					
						
							|  |  |  | 	Port     int    `json:"port"` | 
					
						
							|  |  |  | 	Flow     string `json:"flow,omitempty"` | 
					
						
							|  |  |  | 	Method   string `json:"method,omitempty"` | 
					
						
							|  |  |  | } |