subService.go 33 KB

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