service_flow_test.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. package sub
  2. import (
  3. "strings"
  4. "testing"
  5. "github.com/mhsanaei/3x-ui/v3/internal/database/model"
  6. )
  7. // Issue #5232: a vision flow set on a VLESS+XHTTP+REALITY (vlessenc) client
  8. // must survive into subscription output, not just the inbound JSON.
  9. const testMlkemEncryption = "mlkem768x25519plus.native.0rtt.dGVzdC1rZXk"
  10. func TestVlessFlowAllowed(t *testing.T) {
  11. enc := map[string]any{"encryption": testMlkemEncryption}
  12. noEnc := map[string]any{"encryption": "none"}
  13. tests := []struct {
  14. name string
  15. network string
  16. security string
  17. settings map[string]any
  18. want bool
  19. }{
  20. {"tcp tls", "tcp", "tls", noEnc, true},
  21. {"tcp reality", "tcp", "reality", noEnc, true},
  22. {"tcp none", "tcp", "none", noEnc, false},
  23. {"tcp none vlessenc", "tcp", "none", enc, true},
  24. {"ws none vlessenc", "ws", "none", enc, true},
  25. {"xhttp none vlessenc", "xhttp", "none", enc, true},
  26. {"xhttp reality vlessenc (#5232)", "xhttp", "reality", enc, true},
  27. {"xhttp tls vlessenc", "xhttp", "tls", enc, true},
  28. {"xhttp reality no vlessenc", "xhttp", "reality", noEnc, false},
  29. {"ws tls", "ws", "tls", noEnc, false},
  30. }
  31. for _, tc := range tests {
  32. t.Run(tc.name, func(t *testing.T) {
  33. if got := vlessFlowAllowed(tc.network, tc.security, tc.settings); got != tc.want {
  34. t.Fatalf("vlessFlowAllowed(%q, %q, %v) = %v, want %v", tc.network, tc.security, tc.settings, got, tc.want)
  35. }
  36. })
  37. }
  38. }
  39. func flowTestInbound(streamSettings, encryption string) *model.Inbound {
  40. return &model.Inbound{
  41. Listen: "203.0.113.1",
  42. Port: 443,
  43. Protocol: model.VLESS,
  44. Remark: "flowtest",
  45. Settings: `{"clients":[{"id":"11111111-2222-4333-8444-555555555555","email":"user","flow":"xtls-rprx-vision"}],` +
  46. `"decryption":"` + encryption + `","encryption":"` + encryption + `"}`,
  47. StreamSettings: streamSettings,
  48. }
  49. }
  50. const xhttpRealityStream = `{
  51. "network": "xhttp",
  52. "security": "reality",
  53. "xhttpSettings": {"path": "/", "mode": "auto"},
  54. "realitySettings": {
  55. "serverNames": ["example.com"],
  56. "shortIds": ["abcd"],
  57. "settings": {"publicKey": "pub", "fingerprint": "chrome"}
  58. }
  59. }`
  60. func TestGenVlessLink_FlowXhttpRealityVlessenc(t *testing.T) {
  61. s := &SubService{}
  62. link := s.genVlessLink(flowTestInbound(xhttpRealityStream, testMlkemEncryption), "user")
  63. if !strings.Contains(link, "flow=xtls-rprx-vision") {
  64. t.Fatalf("xhttp+reality+vlessenc link must carry the vision flow (#5232), got %q", link)
  65. }
  66. }
  67. func TestGenVlessLink_NoFlowXhttpRealityWithoutVlessenc(t *testing.T) {
  68. s := &SubService{}
  69. link := s.genVlessLink(flowTestInbound(xhttpRealityStream, "none"), "user")
  70. if strings.Contains(link, "flow=") {
  71. t.Fatalf("xhttp+reality without vlessenc must not carry a flow, got %q", link)
  72. }
  73. }
  74. func TestGenVlessLink_DisableFlowSuppressesFlow(t *testing.T) {
  75. s := &SubService{}
  76. ib := flowTestInbound(xhttpRealityStream, testMlkemEncryption)
  77. ib.DisableFlow = true
  78. link := s.genVlessLink(ib, "user")
  79. if strings.Contains(link, "flow=") {
  80. t.Fatalf("DisableFlow inbound must not carry a flow even when the transport is capable, got %q", link)
  81. }
  82. }
  83. func TestGenVlessLink_FlowTcpRealityStillWorks(t *testing.T) {
  84. stream := `{
  85. "network": "tcp",
  86. "security": "reality",
  87. "tcpSettings": {"header": {"type": "none"}},
  88. "realitySettings": {
  89. "serverNames": ["example.com"],
  90. "shortIds": ["abcd"],
  91. "settings": {"publicKey": "pub", "fingerprint": "chrome"}
  92. }
  93. }`
  94. s := &SubService{}
  95. link := s.genVlessLink(flowTestInbound(stream, "none"), "user")
  96. if !strings.Contains(link, "flow=xtls-rprx-vision") {
  97. t.Fatalf("tcp+reality link must keep the vision flow, got %q", link)
  98. }
  99. }