subService.go 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148
  1. package sub
  2. import (
  3. "encoding/base64"
  4. "fmt"
  5. "net"
  6. "net/url"
  7. "strconv"
  8. "strings"
  9. "time"
  10. "github.com/gin-gonic/gin"
  11. "github.com/goccy/go-json"
  12. "x-ui/database"
  13. "x-ui/database/model"
  14. "x-ui/logger"
  15. "x-ui/util/common"
  16. "x-ui/util/random"
  17. "x-ui/web/service"
  18. "x-ui/xray"
  19. )
  20. type SubService struct {
  21. address string
  22. showInfo bool
  23. remarkModel string
  24. datepicker string
  25. inboundService service.InboundService
  26. settingService service.SettingService
  27. }
  28. func NewSubService(showInfo bool, remarkModel string) *SubService {
  29. return &SubService{
  30. showInfo: showInfo,
  31. remarkModel: remarkModel,
  32. }
  33. }
  34. func (s *SubService) GetSubs(subId string, host string) ([]string, int64, xray.ClientTraffic, error) {
  35. s.address = host
  36. var result []string
  37. var traffic xray.ClientTraffic
  38. var lastOnline int64
  39. var clientTraffics []xray.ClientTraffic
  40. inbounds, err := s.getInboundsBySubId(subId)
  41. if err != nil {
  42. return nil, 0, traffic, err
  43. }
  44. if len(inbounds) == 0 {
  45. return nil, 0, traffic, common.NewError("No inbounds found with ", subId)
  46. }
  47. s.datepicker, err = s.settingService.GetDatepicker()
  48. if err != nil {
  49. s.datepicker = "gregorian"
  50. }
  51. for _, inbound := range inbounds {
  52. clients, err := s.inboundService.GetClients(inbound)
  53. if err != nil {
  54. logger.Error("SubService - GetClients: Unable to get clients from inbound")
  55. }
  56. if clients == nil {
  57. continue
  58. }
  59. if len(inbound.Listen) > 0 && inbound.Listen[0] == '@' {
  60. listen, port, streamSettings, err := s.getFallbackMaster(inbound.Listen, inbound.StreamSettings)
  61. if err == nil {
  62. inbound.Listen = listen
  63. inbound.Port = port
  64. inbound.StreamSettings = streamSettings
  65. }
  66. }
  67. for _, client := range clients {
  68. if client.Enable && client.SubID == subId {
  69. link := s.getLink(inbound, client.Email)
  70. result = append(result, link)
  71. ct := s.getClientTraffics(inbound.ClientStats, client.Email)
  72. clientTraffics = append(clientTraffics, ct)
  73. if ct.LastOnline > lastOnline {
  74. lastOnline = ct.LastOnline
  75. }
  76. }
  77. }
  78. }
  79. // Prepare statistics
  80. for index, clientTraffic := range clientTraffics {
  81. if index == 0 {
  82. traffic.Up = clientTraffic.Up
  83. traffic.Down = clientTraffic.Down
  84. traffic.Total = clientTraffic.Total
  85. if clientTraffic.ExpiryTime > 0 {
  86. traffic.ExpiryTime = clientTraffic.ExpiryTime
  87. }
  88. } else {
  89. traffic.Up += clientTraffic.Up
  90. traffic.Down += clientTraffic.Down
  91. if traffic.Total == 0 || clientTraffic.Total == 0 {
  92. traffic.Total = 0
  93. } else {
  94. traffic.Total += clientTraffic.Total
  95. }
  96. if clientTraffic.ExpiryTime != traffic.ExpiryTime {
  97. traffic.ExpiryTime = 0
  98. }
  99. }
  100. }
  101. return result, lastOnline, traffic, nil
  102. }
  103. func (s *SubService) getInboundsBySubId(subId string) ([]*model.Inbound, error) {
  104. db := database.GetDB()
  105. var inbounds []*model.Inbound
  106. err := db.Model(model.Inbound{}).Preload("ClientStats").Where(`id in (
  107. SELECT DISTINCT inbounds.id
  108. FROM inbounds,
  109. JSON_EACH(JSON_EXTRACT(inbounds.settings, '$.clients')) AS client
  110. WHERE
  111. protocol in ('vmess','vless','trojan','shadowsocks')
  112. AND JSON_EXTRACT(client.value, '$.subId') = ? AND enable = ?
  113. )`, subId, true).Find(&inbounds).Error
  114. if err != nil {
  115. return nil, err
  116. }
  117. return inbounds, nil
  118. }
  119. func (s *SubService) getClientTraffics(traffics []xray.ClientTraffic, email string) xray.ClientTraffic {
  120. for _, traffic := range traffics {
  121. if traffic.Email == email {
  122. return traffic
  123. }
  124. }
  125. return xray.ClientTraffic{}
  126. }
  127. func (s *SubService) getFallbackMaster(dest string, streamSettings string) (string, int, string, error) {
  128. db := database.GetDB()
  129. var inbound *model.Inbound
  130. err := db.Model(model.Inbound{}).
  131. Where("JSON_TYPE(settings, '$.fallbacks') = 'array'").
  132. Where("EXISTS (SELECT * FROM json_each(settings, '$.fallbacks') WHERE json_extract(value, '$.dest') = ?)", dest).
  133. Find(&inbound).Error
  134. if err != nil {
  135. return "", 0, "", err
  136. }
  137. var stream map[string]any
  138. json.Unmarshal([]byte(streamSettings), &stream)
  139. var masterStream map[string]any
  140. json.Unmarshal([]byte(inbound.StreamSettings), &masterStream)
  141. stream["security"] = masterStream["security"]
  142. stream["tlsSettings"] = masterStream["tlsSettings"]
  143. stream["externalProxy"] = masterStream["externalProxy"]
  144. modifiedStream, _ := json.MarshalIndent(stream, "", " ")
  145. return inbound.Listen, inbound.Port, string(modifiedStream), nil
  146. }
  147. func (s *SubService) getLink(inbound *model.Inbound, email string) string {
  148. switch inbound.Protocol {
  149. case "vmess":
  150. return s.genVmessLink(inbound, email)
  151. case "vless":
  152. return s.genVlessLink(inbound, email)
  153. case "trojan":
  154. return s.genTrojanLink(inbound, email)
  155. case "shadowsocks":
  156. return s.genShadowsocksLink(inbound, email)
  157. }
  158. return ""
  159. }
  160. func (s *SubService) genVmessLink(inbound *model.Inbound, email string) string {
  161. if inbound.Protocol != model.VMESS {
  162. return ""
  163. }
  164. obj := map[string]any{
  165. "v": "2",
  166. "add": s.address,
  167. "port": inbound.Port,
  168. "type": "none",
  169. }
  170. var stream map[string]any
  171. json.Unmarshal([]byte(inbound.StreamSettings), &stream)
  172. network, _ := stream["network"].(string)
  173. obj["net"] = network
  174. switch network {
  175. case "tcp":
  176. tcp, _ := stream["tcpSettings"].(map[string]any)
  177. header, _ := tcp["header"].(map[string]any)
  178. typeStr, _ := header["type"].(string)
  179. obj["type"] = typeStr
  180. if typeStr == "http" {
  181. request := header["request"].(map[string]any)
  182. requestPath, _ := request["path"].([]any)
  183. obj["path"] = requestPath[0].(string)
  184. headers, _ := request["headers"].(map[string]any)
  185. obj["host"] = searchHost(headers)
  186. }
  187. case "kcp":
  188. kcp, _ := stream["kcpSettings"].(map[string]any)
  189. header, _ := kcp["header"].(map[string]any)
  190. obj["type"], _ = header["type"].(string)
  191. obj["path"], _ = kcp["seed"].(string)
  192. case "ws":
  193. ws, _ := stream["wsSettings"].(map[string]any)
  194. obj["path"] = ws["path"].(string)
  195. if host, ok := ws["host"].(string); ok && len(host) > 0 {
  196. obj["host"] = host
  197. } else {
  198. headers, _ := ws["headers"].(map[string]any)
  199. obj["host"] = searchHost(headers)
  200. }
  201. case "grpc":
  202. grpc, _ := stream["grpcSettings"].(map[string]any)
  203. obj["path"] = grpc["serviceName"].(string)
  204. obj["authority"] = grpc["authority"].(string)
  205. if grpc["multiMode"].(bool) {
  206. obj["type"] = "multi"
  207. }
  208. case "httpupgrade":
  209. httpupgrade, _ := stream["httpupgradeSettings"].(map[string]any)
  210. obj["path"] = httpupgrade["path"].(string)
  211. if host, ok := httpupgrade["host"].(string); ok && len(host) > 0 {
  212. obj["host"] = host
  213. } else {
  214. headers, _ := httpupgrade["headers"].(map[string]any)
  215. obj["host"] = searchHost(headers)
  216. }
  217. case "xhttp":
  218. xhttp, _ := stream["xhttpSettings"].(map[string]any)
  219. obj["path"] = xhttp["path"].(string)
  220. if host, ok := xhttp["host"].(string); ok && len(host) > 0 {
  221. obj["host"] = host
  222. } else {
  223. headers, _ := xhttp["headers"].(map[string]any)
  224. obj["host"] = searchHost(headers)
  225. }
  226. obj["mode"] = xhttp["mode"].(string)
  227. }
  228. security, _ := stream["security"].(string)
  229. obj["tls"] = security
  230. if security == "tls" {
  231. tlsSetting, _ := stream["tlsSettings"].(map[string]any)
  232. alpns, _ := tlsSetting["alpn"].([]any)
  233. if len(alpns) > 0 {
  234. var alpn []string
  235. for _, a := range alpns {
  236. alpn = append(alpn, a.(string))
  237. }
  238. obj["alpn"] = strings.Join(alpn, ",")
  239. }
  240. if sniValue, ok := searchKey(tlsSetting, "serverName"); ok {
  241. obj["sni"], _ = sniValue.(string)
  242. }
  243. tlsSettings, _ := searchKey(tlsSetting, "settings")
  244. if tlsSetting != nil {
  245. if fpValue, ok := searchKey(tlsSettings, "fingerprint"); ok {
  246. obj["fp"], _ = fpValue.(string)
  247. }
  248. if insecure, ok := searchKey(tlsSettings, "allowInsecure"); ok {
  249. obj["allowInsecure"], _ = insecure.(bool)
  250. }
  251. }
  252. }
  253. clients, _ := s.inboundService.GetClients(inbound)
  254. clientIndex := -1
  255. for i, client := range clients {
  256. if client.Email == email {
  257. clientIndex = i
  258. break
  259. }
  260. }
  261. obj["id"] = clients[clientIndex].ID
  262. obj["scy"] = clients[clientIndex].Security
  263. externalProxies, _ := stream["externalProxy"].([]any)
  264. if len(externalProxies) > 0 {
  265. links := ""
  266. for index, externalProxy := range externalProxies {
  267. ep, _ := externalProxy.(map[string]any)
  268. newSecurity, _ := ep["forceTls"].(string)
  269. newObj := map[string]any{}
  270. for key, value := range obj {
  271. if !(newSecurity == "none" && (key == "alpn" || key == "sni" || key == "fp" || key == "allowInsecure")) {
  272. newObj[key] = value
  273. }
  274. }
  275. newObj["ps"] = s.genRemark(inbound, email, ep["remark"].(string))
  276. newObj["add"] = ep["dest"].(string)
  277. newObj["port"] = int(ep["port"].(float64))
  278. if newSecurity != "same" {
  279. newObj["tls"] = newSecurity
  280. }
  281. if index > 0 {
  282. links += "\n"
  283. }
  284. jsonStr, _ := json.MarshalIndent(newObj, "", " ")
  285. links += "vmess://" + base64.StdEncoding.EncodeToString(jsonStr)
  286. }
  287. return links
  288. }
  289. obj["ps"] = s.genRemark(inbound, email, "")
  290. jsonStr, _ := json.MarshalIndent(obj, "", " ")
  291. return "vmess://" + base64.StdEncoding.EncodeToString(jsonStr)
  292. }
  293. func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string {
  294. address := s.address
  295. if inbound.Protocol != model.VLESS {
  296. return ""
  297. }
  298. var vlessSettings model.VLESSSettings
  299. _ = json.Unmarshal([]byte(inbound.Settings), &vlessSettings)
  300. var stream map[string]any
  301. json.Unmarshal([]byte(inbound.StreamSettings), &stream)
  302. clients, _ := s.inboundService.GetClients(inbound)
  303. clientIndex := -1
  304. for i, client := range clients {
  305. if client.Email == email {
  306. clientIndex = i
  307. break
  308. }
  309. }
  310. uuid := clients[clientIndex].ID
  311. port := inbound.Port
  312. streamNetwork := stream["network"].(string)
  313. params := make(map[string]string)
  314. if vlessSettings.Encryption != "" {
  315. params["encryption"] = vlessSettings.Encryption
  316. }
  317. params["type"] = streamNetwork
  318. switch streamNetwork {
  319. case "tcp":
  320. tcp, _ := stream["tcpSettings"].(map[string]any)
  321. header, _ := tcp["header"].(map[string]any)
  322. typeStr, _ := header["type"].(string)
  323. if typeStr == "http" {
  324. request := header["request"].(map[string]any)
  325. requestPath, _ := request["path"].([]any)
  326. params["path"] = requestPath[0].(string)
  327. headers, _ := request["headers"].(map[string]any)
  328. params["host"] = searchHost(headers)
  329. params["headerType"] = "http"
  330. }
  331. case "kcp":
  332. kcp, _ := stream["kcpSettings"].(map[string]any)
  333. header, _ := kcp["header"].(map[string]any)
  334. params["headerType"] = header["type"].(string)
  335. params["seed"] = kcp["seed"].(string)
  336. case "ws":
  337. ws, _ := stream["wsSettings"].(map[string]any)
  338. params["path"] = ws["path"].(string)
  339. if host, ok := ws["host"].(string); ok && len(host) > 0 {
  340. params["host"] = host
  341. } else {
  342. headers, _ := ws["headers"].(map[string]any)
  343. params["host"] = searchHost(headers)
  344. }
  345. case "grpc":
  346. grpc, _ := stream["grpcSettings"].(map[string]any)
  347. params["serviceName"] = grpc["serviceName"].(string)
  348. params["authority"], _ = grpc["authority"].(string)
  349. if grpc["multiMode"].(bool) {
  350. params["mode"] = "multi"
  351. }
  352. case "httpupgrade":
  353. httpupgrade, _ := stream["httpupgradeSettings"].(map[string]any)
  354. params["path"] = httpupgrade["path"].(string)
  355. if host, ok := httpupgrade["host"].(string); ok && len(host) > 0 {
  356. params["host"] = host
  357. } else {
  358. headers, _ := httpupgrade["headers"].(map[string]any)
  359. params["host"] = searchHost(headers)
  360. }
  361. case "xhttp":
  362. xhttp, _ := stream["xhttpSettings"].(map[string]any)
  363. params["path"] = xhttp["path"].(string)
  364. if host, ok := xhttp["host"].(string); ok && len(host) > 0 {
  365. params["host"] = host
  366. } else {
  367. headers, _ := xhttp["headers"].(map[string]any)
  368. params["host"] = searchHost(headers)
  369. }
  370. params["mode"] = xhttp["mode"].(string)
  371. }
  372. security, _ := stream["security"].(string)
  373. if security == "tls" {
  374. params["security"] = "tls"
  375. tlsSetting, _ := stream["tlsSettings"].(map[string]any)
  376. alpns, _ := tlsSetting["alpn"].([]any)
  377. var alpn []string
  378. for _, a := range alpns {
  379. alpn = append(alpn, a.(string))
  380. }
  381. if len(alpn) > 0 {
  382. params["alpn"] = strings.Join(alpn, ",")
  383. }
  384. if sniValue, ok := searchKey(tlsSetting, "serverName"); ok {
  385. params["sni"], _ = sniValue.(string)
  386. }
  387. tlsSettings, _ := searchKey(tlsSetting, "settings")
  388. if tlsSetting != nil {
  389. if fpValue, ok := searchKey(tlsSettings, "fingerprint"); ok {
  390. params["fp"], _ = fpValue.(string)
  391. }
  392. if insecure, ok := searchKey(tlsSettings, "allowInsecure"); ok {
  393. if insecure.(bool) {
  394. params["allowInsecure"] = "1"
  395. }
  396. }
  397. }
  398. if streamNetwork == "tcp" && len(clients[clientIndex].Flow) > 0 {
  399. params["flow"] = clients[clientIndex].Flow
  400. }
  401. }
  402. if security == "reality" {
  403. params["security"] = "reality"
  404. realitySetting, _ := stream["realitySettings"].(map[string]any)
  405. realitySettings, _ := searchKey(realitySetting, "settings")
  406. if realitySetting != nil {
  407. if sniValue, ok := searchKey(realitySetting, "serverNames"); ok {
  408. sNames, _ := sniValue.([]any)
  409. params["sni"] = sNames[random.Num(len(sNames))].(string)
  410. }
  411. if pbkValue, ok := searchKey(realitySettings, "publicKey"); ok {
  412. params["pbk"], _ = pbkValue.(string)
  413. }
  414. if sidValue, ok := searchKey(realitySetting, "shortIds"); ok {
  415. shortIds, _ := sidValue.([]any)
  416. params["sid"] = shortIds[random.Num(len(shortIds))].(string)
  417. }
  418. if fpValue, ok := searchKey(realitySettings, "fingerprint"); ok {
  419. if fp, ok := fpValue.(string); ok && len(fp) > 0 {
  420. params["fp"] = fp
  421. }
  422. }
  423. if pqvValue, ok := searchKey(realitySettings, "mldsa65Verify"); ok {
  424. if pqv, ok := pqvValue.(string); ok && len(pqv) > 0 {
  425. params["pqv"] = pqv
  426. }
  427. }
  428. params["spx"] = "/" + random.Seq(15)
  429. }
  430. if streamNetwork == "tcp" && len(clients[clientIndex].Flow) > 0 {
  431. params["flow"] = clients[clientIndex].Flow
  432. }
  433. }
  434. if security != "tls" && security != "reality" {
  435. params["security"] = "none"
  436. }
  437. externalProxies, _ := stream["externalProxy"].([]any)
  438. if len(externalProxies) > 0 {
  439. links := ""
  440. for index, externalProxy := range externalProxies {
  441. ep, _ := externalProxy.(map[string]any)
  442. newSecurity, _ := ep["forceTls"].(string)
  443. dest, _ := ep["dest"].(string)
  444. port := int(ep["port"].(float64))
  445. link := fmt.Sprintf("vless://%s@%s:%d", uuid, dest, port)
  446. if newSecurity != "same" {
  447. params["security"] = newSecurity
  448. } else {
  449. params["security"] = security
  450. }
  451. url, _ := url.Parse(link)
  452. q := url.Query()
  453. for k, v := range params {
  454. if !(newSecurity == "none" && (k == "alpn" || k == "sni" || k == "fp" || k == "allowInsecure")) {
  455. q.Add(k, v)
  456. }
  457. }
  458. // Set the new query values on the URL
  459. url.RawQuery = q.Encode()
  460. url.Fragment = s.genRemark(inbound, email, ep["remark"].(string))
  461. if index > 0 {
  462. links += "\n"
  463. }
  464. links += url.String()
  465. }
  466. return links
  467. }
  468. link := fmt.Sprintf("vless://%s@%s:%d", uuid, address, port)
  469. url, _ := url.Parse(link)
  470. q := url.Query()
  471. for k, v := range params {
  472. q.Add(k, v)
  473. }
  474. // Set the new query values on the URL
  475. url.RawQuery = q.Encode()
  476. url.Fragment = s.genRemark(inbound, email, "")
  477. return url.String()
  478. }
  479. func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string {
  480. address := s.address
  481. if inbound.Protocol != model.Trojan {
  482. return ""
  483. }
  484. var stream map[string]any
  485. json.Unmarshal([]byte(inbound.StreamSettings), &stream)
  486. clients, _ := s.inboundService.GetClients(inbound)
  487. clientIndex := -1
  488. for i, client := range clients {
  489. if client.Email == email {
  490. clientIndex = i
  491. break
  492. }
  493. }
  494. password := clients[clientIndex].Password
  495. port := inbound.Port
  496. streamNetwork := stream["network"].(string)
  497. params := make(map[string]string)
  498. params["type"] = streamNetwork
  499. switch streamNetwork {
  500. case "tcp":
  501. tcp, _ := stream["tcpSettings"].(map[string]any)
  502. header, _ := tcp["header"].(map[string]any)
  503. typeStr, _ := header["type"].(string)
  504. if typeStr == "http" {
  505. request := header["request"].(map[string]any)
  506. requestPath, _ := request["path"].([]any)
  507. params["path"] = requestPath[0].(string)
  508. headers, _ := request["headers"].(map[string]any)
  509. params["host"] = searchHost(headers)
  510. params["headerType"] = "http"
  511. }
  512. case "kcp":
  513. kcp, _ := stream["kcpSettings"].(map[string]any)
  514. header, _ := kcp["header"].(map[string]any)
  515. params["headerType"] = header["type"].(string)
  516. params["seed"] = kcp["seed"].(string)
  517. case "ws":
  518. ws, _ := stream["wsSettings"].(map[string]any)
  519. params["path"] = ws["path"].(string)
  520. if host, ok := ws["host"].(string); ok && len(host) > 0 {
  521. params["host"] = host
  522. } else {
  523. headers, _ := ws["headers"].(map[string]any)
  524. params["host"] = searchHost(headers)
  525. }
  526. case "grpc":
  527. grpc, _ := stream["grpcSettings"].(map[string]any)
  528. params["serviceName"] = grpc["serviceName"].(string)
  529. params["authority"], _ = grpc["authority"].(string)
  530. if grpc["multiMode"].(bool) {
  531. params["mode"] = "multi"
  532. }
  533. case "httpupgrade":
  534. httpupgrade, _ := stream["httpupgradeSettings"].(map[string]any)
  535. params["path"] = httpupgrade["path"].(string)
  536. if host, ok := httpupgrade["host"].(string); ok && len(host) > 0 {
  537. params["host"] = host
  538. } else {
  539. headers, _ := httpupgrade["headers"].(map[string]any)
  540. params["host"] = searchHost(headers)
  541. }
  542. case "xhttp":
  543. xhttp, _ := stream["xhttpSettings"].(map[string]any)
  544. params["path"] = xhttp["path"].(string)
  545. if host, ok := xhttp["host"].(string); ok && len(host) > 0 {
  546. params["host"] = host
  547. } else {
  548. headers, _ := xhttp["headers"].(map[string]any)
  549. params["host"] = searchHost(headers)
  550. }
  551. params["mode"] = xhttp["mode"].(string)
  552. }
  553. security, _ := stream["security"].(string)
  554. if security == "tls" {
  555. params["security"] = "tls"
  556. tlsSetting, _ := stream["tlsSettings"].(map[string]any)
  557. alpns, _ := tlsSetting["alpn"].([]any)
  558. var alpn []string
  559. for _, a := range alpns {
  560. alpn = append(alpn, a.(string))
  561. }
  562. if len(alpn) > 0 {
  563. params["alpn"] = strings.Join(alpn, ",")
  564. }
  565. if sniValue, ok := searchKey(tlsSetting, "serverName"); ok {
  566. params["sni"], _ = sniValue.(string)
  567. }
  568. tlsSettings, _ := searchKey(tlsSetting, "settings")
  569. if tlsSetting != nil {
  570. if fpValue, ok := searchKey(tlsSettings, "fingerprint"); ok {
  571. params["fp"], _ = fpValue.(string)
  572. }
  573. if insecure, ok := searchKey(tlsSettings, "allowInsecure"); ok {
  574. if insecure.(bool) {
  575. params["allowInsecure"] = "1"
  576. }
  577. }
  578. }
  579. }
  580. if security == "reality" {
  581. params["security"] = "reality"
  582. realitySetting, _ := stream["realitySettings"].(map[string]any)
  583. realitySettings, _ := searchKey(realitySetting, "settings")
  584. if realitySetting != nil {
  585. if sniValue, ok := searchKey(realitySetting, "serverNames"); ok {
  586. sNames, _ := sniValue.([]any)
  587. params["sni"] = sNames[random.Num(len(sNames))].(string)
  588. }
  589. if pbkValue, ok := searchKey(realitySettings, "publicKey"); ok {
  590. params["pbk"], _ = pbkValue.(string)
  591. }
  592. if sidValue, ok := searchKey(realitySetting, "shortIds"); ok {
  593. shortIds, _ := sidValue.([]any)
  594. params["sid"] = shortIds[random.Num(len(shortIds))].(string)
  595. }
  596. if fpValue, ok := searchKey(realitySettings, "fingerprint"); ok {
  597. if fp, ok := fpValue.(string); ok && len(fp) > 0 {
  598. params["fp"] = fp
  599. }
  600. }
  601. if pqvValue, ok := searchKey(realitySettings, "mldsa65Verify"); ok {
  602. if pqv, ok := pqvValue.(string); ok && len(pqv) > 0 {
  603. params["pqv"] = pqv
  604. }
  605. }
  606. params["spx"] = "/" + random.Seq(15)
  607. }
  608. if streamNetwork == "tcp" && len(clients[clientIndex].Flow) > 0 {
  609. params["flow"] = clients[clientIndex].Flow
  610. }
  611. }
  612. if security != "tls" && security != "reality" {
  613. params["security"] = "none"
  614. }
  615. externalProxies, _ := stream["externalProxy"].([]any)
  616. if len(externalProxies) > 0 {
  617. links := ""
  618. for index, externalProxy := range externalProxies {
  619. ep, _ := externalProxy.(map[string]any)
  620. newSecurity, _ := ep["forceTls"].(string)
  621. dest, _ := ep["dest"].(string)
  622. port := int(ep["port"].(float64))
  623. link := fmt.Sprintf("trojan://%s@%s:%d", password, dest, port)
  624. if newSecurity != "same" {
  625. params["security"] = newSecurity
  626. } else {
  627. params["security"] = security
  628. }
  629. url, _ := url.Parse(link)
  630. q := url.Query()
  631. for k, v := range params {
  632. if !(newSecurity == "none" && (k == "alpn" || k == "sni" || k == "fp" || k == "allowInsecure")) {
  633. q.Add(k, v)
  634. }
  635. }
  636. // Set the new query values on the URL
  637. url.RawQuery = q.Encode()
  638. url.Fragment = s.genRemark(inbound, email, ep["remark"].(string))
  639. if index > 0 {
  640. links += "\n"
  641. }
  642. links += url.String()
  643. }
  644. return links
  645. }
  646. link := fmt.Sprintf("trojan://%s@%s:%d", password, address, port)
  647. url, _ := url.Parse(link)
  648. q := url.Query()
  649. for k, v := range params {
  650. q.Add(k, v)
  651. }
  652. // Set the new query values on the URL
  653. url.RawQuery = q.Encode()
  654. url.Fragment = s.genRemark(inbound, email, "")
  655. return url.String()
  656. }
  657. func (s *SubService) genShadowsocksLink(inbound *model.Inbound, email string) string {
  658. address := s.address
  659. if inbound.Protocol != model.Shadowsocks {
  660. return ""
  661. }
  662. var stream map[string]any
  663. json.Unmarshal([]byte(inbound.StreamSettings), &stream)
  664. clients, _ := s.inboundService.GetClients(inbound)
  665. var settings map[string]any
  666. json.Unmarshal([]byte(inbound.Settings), &settings)
  667. inboundPassword := settings["password"].(string)
  668. method := settings["method"].(string)
  669. clientIndex := -1
  670. for i, client := range clients {
  671. if client.Email == email {
  672. clientIndex = i
  673. break
  674. }
  675. }
  676. streamNetwork := stream["network"].(string)
  677. params := make(map[string]string)
  678. params["type"] = streamNetwork
  679. switch streamNetwork {
  680. case "tcp":
  681. tcp, _ := stream["tcpSettings"].(map[string]any)
  682. header, _ := tcp["header"].(map[string]any)
  683. typeStr, _ := header["type"].(string)
  684. if typeStr == "http" {
  685. request := header["request"].(map[string]any)
  686. requestPath, _ := request["path"].([]any)
  687. params["path"] = requestPath[0].(string)
  688. headers, _ := request["headers"].(map[string]any)
  689. params["host"] = searchHost(headers)
  690. params["headerType"] = "http"
  691. }
  692. case "kcp":
  693. kcp, _ := stream["kcpSettings"].(map[string]any)
  694. header, _ := kcp["header"].(map[string]any)
  695. params["headerType"] = header["type"].(string)
  696. params["seed"] = kcp["seed"].(string)
  697. case "ws":
  698. ws, _ := stream["wsSettings"].(map[string]any)
  699. params["path"] = ws["path"].(string)
  700. if host, ok := ws["host"].(string); ok && len(host) > 0 {
  701. params["host"] = host
  702. } else {
  703. headers, _ := ws["headers"].(map[string]any)
  704. params["host"] = searchHost(headers)
  705. }
  706. case "grpc":
  707. grpc, _ := stream["grpcSettings"].(map[string]any)
  708. params["serviceName"] = grpc["serviceName"].(string)
  709. params["authority"], _ = grpc["authority"].(string)
  710. if grpc["multiMode"].(bool) {
  711. params["mode"] = "multi"
  712. }
  713. case "httpupgrade":
  714. httpupgrade, _ := stream["httpupgradeSettings"].(map[string]any)
  715. params["path"] = httpupgrade["path"].(string)
  716. if host, ok := httpupgrade["host"].(string); ok && len(host) > 0 {
  717. params["host"] = host
  718. } else {
  719. headers, _ := httpupgrade["headers"].(map[string]any)
  720. params["host"] = searchHost(headers)
  721. }
  722. case "xhttp":
  723. xhttp, _ := stream["xhttpSettings"].(map[string]any)
  724. params["path"] = xhttp["path"].(string)
  725. if host, ok := xhttp["host"].(string); ok && len(host) > 0 {
  726. params["host"] = host
  727. } else {
  728. headers, _ := xhttp["headers"].(map[string]any)
  729. params["host"] = searchHost(headers)
  730. }
  731. params["mode"] = xhttp["mode"].(string)
  732. }
  733. security, _ := stream["security"].(string)
  734. if security == "tls" {
  735. params["security"] = "tls"
  736. tlsSetting, _ := stream["tlsSettings"].(map[string]any)
  737. alpns, _ := tlsSetting["alpn"].([]any)
  738. var alpn []string
  739. for _, a := range alpns {
  740. alpn = append(alpn, a.(string))
  741. }
  742. if len(alpn) > 0 {
  743. params["alpn"] = strings.Join(alpn, ",")
  744. }
  745. if sniValue, ok := searchKey(tlsSetting, "serverName"); ok {
  746. params["sni"], _ = sniValue.(string)
  747. }
  748. tlsSettings, _ := searchKey(tlsSetting, "settings")
  749. if tlsSetting != nil {
  750. if fpValue, ok := searchKey(tlsSettings, "fingerprint"); ok {
  751. params["fp"], _ = fpValue.(string)
  752. }
  753. if insecure, ok := searchKey(tlsSettings, "allowInsecure"); ok {
  754. if insecure.(bool) {
  755. params["allowInsecure"] = "1"
  756. }
  757. }
  758. }
  759. }
  760. encPart := fmt.Sprintf("%s:%s", method, clients[clientIndex].Password)
  761. if method[0] == '2' {
  762. encPart = fmt.Sprintf("%s:%s:%s", method, inboundPassword, clients[clientIndex].Password)
  763. }
  764. externalProxies, _ := stream["externalProxy"].([]any)
  765. if len(externalProxies) > 0 {
  766. links := ""
  767. for index, externalProxy := range externalProxies {
  768. ep, _ := externalProxy.(map[string]any)
  769. newSecurity, _ := ep["forceTls"].(string)
  770. dest, _ := ep["dest"].(string)
  771. port := int(ep["port"].(float64))
  772. link := fmt.Sprintf("ss://%s@%s:%d", base64.StdEncoding.EncodeToString([]byte(encPart)), dest, port)
  773. if newSecurity != "same" {
  774. params["security"] = newSecurity
  775. } else {
  776. params["security"] = security
  777. }
  778. url, _ := url.Parse(link)
  779. q := url.Query()
  780. for k, v := range params {
  781. if !(newSecurity == "none" && (k == "alpn" || k == "sni" || k == "fp" || k == "allowInsecure")) {
  782. q.Add(k, v)
  783. }
  784. }
  785. // Set the new query values on the URL
  786. url.RawQuery = q.Encode()
  787. url.Fragment = s.genRemark(inbound, email, ep["remark"].(string))
  788. if index > 0 {
  789. links += "\n"
  790. }
  791. links += url.String()
  792. }
  793. return links
  794. }
  795. link := fmt.Sprintf("ss://%s@%s:%d", base64.StdEncoding.EncodeToString([]byte(encPart)), address, inbound.Port)
  796. url, _ := url.Parse(link)
  797. q := url.Query()
  798. for k, v := range params {
  799. q.Add(k, v)
  800. }
  801. // Set the new query values on the URL
  802. url.RawQuery = q.Encode()
  803. url.Fragment = s.genRemark(inbound, email, "")
  804. return url.String()
  805. }
  806. func (s *SubService) genRemark(inbound *model.Inbound, email string, extra string) string {
  807. separationChar := string(s.remarkModel[0])
  808. orderChars := s.remarkModel[1:]
  809. orders := map[byte]string{
  810. 'i': "",
  811. 'e': "",
  812. 'o': "",
  813. }
  814. if len(email) > 0 {
  815. orders['e'] = email
  816. }
  817. if len(inbound.Remark) > 0 {
  818. orders['i'] = inbound.Remark
  819. }
  820. if len(extra) > 0 {
  821. orders['o'] = extra
  822. }
  823. var remark []string
  824. for i := 0; i < len(orderChars); i++ {
  825. char := orderChars[i]
  826. order, exists := orders[char]
  827. if exists && order != "" {
  828. remark = append(remark, order)
  829. }
  830. }
  831. if s.showInfo {
  832. statsExist := false
  833. var stats xray.ClientTraffic
  834. for _, clientStat := range inbound.ClientStats {
  835. if clientStat.Email == email {
  836. stats = clientStat
  837. statsExist = true
  838. break
  839. }
  840. }
  841. // Get remained days
  842. if statsExist {
  843. if !stats.Enable {
  844. return fmt.Sprintf("⛔️N/A%s%s", separationChar, strings.Join(remark, separationChar))
  845. }
  846. if vol := stats.Total - (stats.Up + stats.Down); vol > 0 {
  847. remark = append(remark, fmt.Sprintf("%s%s", common.FormatTraffic(vol), "📊"))
  848. }
  849. now := time.Now().Unix()
  850. switch exp := stats.ExpiryTime / 1000; {
  851. case exp > 0:
  852. remainingSeconds := exp - now
  853. days := remainingSeconds / 86400
  854. hours := (remainingSeconds % 86400) / 3600
  855. minutes := (remainingSeconds % 3600) / 60
  856. if days > 0 {
  857. if hours > 0 {
  858. remark = append(remark, fmt.Sprintf("%dD,%dH⏳", days, hours))
  859. } else {
  860. remark = append(remark, fmt.Sprintf("%dD⏳", days))
  861. }
  862. } else if hours > 0 {
  863. remark = append(remark, fmt.Sprintf("%dH⏳", hours))
  864. } else {
  865. remark = append(remark, fmt.Sprintf("%dM⏳", minutes))
  866. }
  867. case exp < 0:
  868. days := exp / -86400
  869. hours := (exp % -86400) / 3600
  870. minutes := (exp % -3600) / 60
  871. if days > 0 {
  872. if hours > 0 {
  873. remark = append(remark, fmt.Sprintf("%dD,%dH⏳", days, hours))
  874. } else {
  875. remark = append(remark, fmt.Sprintf("%dD⏳", days))
  876. }
  877. } else if hours > 0 {
  878. remark = append(remark, fmt.Sprintf("%dH⏳", hours))
  879. } else {
  880. remark = append(remark, fmt.Sprintf("%dM⏳", minutes))
  881. }
  882. }
  883. }
  884. }
  885. return strings.Join(remark, separationChar)
  886. }
  887. func searchKey(data any, key string) (any, bool) {
  888. switch val := data.(type) {
  889. case map[string]any:
  890. for k, v := range val {
  891. if k == key {
  892. return v, true
  893. }
  894. if result, ok := searchKey(v, key); ok {
  895. return result, true
  896. }
  897. }
  898. case []any:
  899. for _, v := range val {
  900. if result, ok := searchKey(v, key); ok {
  901. return result, true
  902. }
  903. }
  904. }
  905. return nil, false
  906. }
  907. func searchHost(headers any) string {
  908. data, _ := headers.(map[string]any)
  909. for k, v := range data {
  910. if strings.EqualFold(k, "host") {
  911. switch v.(type) {
  912. case []any:
  913. hosts, _ := v.([]any)
  914. if len(hosts) > 0 {
  915. return hosts[0].(string)
  916. } else {
  917. return ""
  918. }
  919. case any:
  920. return v.(string)
  921. }
  922. }
  923. }
  924. return ""
  925. }
  926. // PageData is a view model for subscription.html
  927. type PageData struct {
  928. Host string
  929. BasePath string
  930. SId string
  931. Download string
  932. Upload string
  933. Total string
  934. Used string
  935. Remained string
  936. Expire int64
  937. LastOnline int64
  938. Datepicker string
  939. DownloadByte int64
  940. UploadByte int64
  941. TotalByte int64
  942. SubUrl string
  943. SubJsonUrl string
  944. Result []string
  945. }
  946. // ResolveRequest extracts scheme and host info from request/headers consistently.
  947. func (s *SubService) ResolveRequest(c *gin.Context) (scheme string, host string, hostWithPort string, hostHeader string) {
  948. // scheme
  949. scheme = "http"
  950. if c.Request.TLS != nil || strings.EqualFold(c.GetHeader("X-Forwarded-Proto"), "https") {
  951. scheme = "https"
  952. }
  953. // base host (no port)
  954. if h, err := getHostFromXFH(c.GetHeader("X-Forwarded-Host")); err == nil && h != "" {
  955. host = h
  956. }
  957. if host == "" {
  958. host = c.GetHeader("X-Real-IP")
  959. }
  960. if host == "" {
  961. var err error
  962. host, _, err = net.SplitHostPort(c.Request.Host)
  963. if err != nil {
  964. host = c.Request.Host
  965. }
  966. }
  967. // host:port for URLs
  968. hostWithPort = c.GetHeader("X-Forwarded-Host")
  969. if hostWithPort == "" {
  970. hostWithPort = c.Request.Host
  971. }
  972. if hostWithPort == "" {
  973. hostWithPort = host
  974. }
  975. // header display host
  976. hostHeader = c.GetHeader("X-Forwarded-Host")
  977. if hostHeader == "" {
  978. hostHeader = c.GetHeader("X-Real-IP")
  979. }
  980. if hostHeader == "" {
  981. hostHeader = host
  982. }
  983. return
  984. }
  985. // BuildURLs constructs absolute subscription and json URLs.
  986. func (s *SubService) BuildURLs(scheme, hostWithPort, subPath, subJsonPath, subId string) (subURL, subJsonURL string) {
  987. if strings.HasSuffix(subPath, "/") {
  988. subURL = scheme + "://" + hostWithPort + subPath + subId
  989. } else {
  990. subURL = scheme + "://" + hostWithPort + strings.TrimRight(subPath, "/") + "/" + subId
  991. }
  992. if strings.HasSuffix(subJsonPath, "/") {
  993. subJsonURL = scheme + "://" + hostWithPort + subJsonPath + subId
  994. } else {
  995. subJsonURL = scheme + "://" + hostWithPort + strings.TrimRight(subJsonPath, "/") + "/" + subId
  996. }
  997. return
  998. }
  999. // BuildPageData parses header and prepares the template view model.
  1000. func (s *SubService) BuildPageData(subId string, hostHeader string, traffic xray.ClientTraffic, lastOnline int64, subs []string, subURL, subJsonURL string) PageData {
  1001. download := common.FormatTraffic(traffic.Down)
  1002. upload := common.FormatTraffic(traffic.Up)
  1003. total := "∞"
  1004. used := common.FormatTraffic(traffic.Up + traffic.Down)
  1005. remained := ""
  1006. if traffic.Total > 0 {
  1007. total = common.FormatTraffic(traffic.Total)
  1008. left := traffic.Total - (traffic.Up + traffic.Down)
  1009. if left < 0 {
  1010. left = 0
  1011. }
  1012. remained = common.FormatTraffic(left)
  1013. }
  1014. datepicker := s.datepicker
  1015. if datepicker == "" {
  1016. datepicker = "gregorian"
  1017. }
  1018. return PageData{
  1019. Host: hostHeader,
  1020. BasePath: "/",
  1021. SId: subId,
  1022. Download: download,
  1023. Upload: upload,
  1024. Total: total,
  1025. Used: used,
  1026. Remained: remained,
  1027. Expire: traffic.ExpiryTime / 1000,
  1028. LastOnline: lastOnline,
  1029. Datepicker: datepicker,
  1030. DownloadByte: traffic.Down,
  1031. UploadByte: traffic.Up,
  1032. TotalByte: traffic.Total,
  1033. SubUrl: subURL,
  1034. SubJsonUrl: subJsonURL,
  1035. Result: subs,
  1036. }
  1037. }
  1038. func getHostFromXFH(s string) (string, error) {
  1039. if strings.Contains(s, ":") {
  1040. realHost, _, err := net.SplitHostPort(s)
  1041. if err != nil {
  1042. return "", err
  1043. }
  1044. return realHost, nil
  1045. }
  1046. return s, nil
  1047. }
  1048. func parseInt64(s string) (int64, error) {
  1049. // handle potential quotes
  1050. s = strings.Trim(s, "\"'")
  1051. n, err := strconv.ParseInt(s, 10, 64)
  1052. return n, err
  1053. }