subService.go 31 KB

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