v2ray_ws_test.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. package main
  2. import (
  3. "net/netip"
  4. "os"
  5. "testing"
  6. C "github.com/sagernet/sing-box/constant"
  7. "github.com/sagernet/sing-box/option"
  8. "github.com/gofrs/uuid"
  9. "github.com/spyzhov/ajson"
  10. "github.com/stretchr/testify/require"
  11. )
  12. func TestV2RayWebsocket(t *testing.T) {
  13. t.Run("self", func(t *testing.T) {
  14. testV2RayTransportSelf(t, &option.V2RayTransportOptions{
  15. Type: C.V2RayTransportTypeWebsocket,
  16. })
  17. })
  18. t.Run("self-early-data", func(t *testing.T) {
  19. testV2RayTransportSelf(t, &option.V2RayTransportOptions{
  20. Type: C.V2RayTransportTypeWebsocket,
  21. WebsocketOptions: option.V2RayWebsocketOptions{
  22. MaxEarlyData: 2048,
  23. },
  24. })
  25. })
  26. t.Run("self-xray-early-data", func(t *testing.T) {
  27. testV2RayTransportSelf(t, &option.V2RayTransportOptions{
  28. Type: C.V2RayTransportTypeWebsocket,
  29. WebsocketOptions: option.V2RayWebsocketOptions{
  30. MaxEarlyData: 2048,
  31. EarlyDataHeaderName: "Sec-WebSocket-Protocol",
  32. },
  33. })
  34. })
  35. t.Run("inbound", func(t *testing.T) {
  36. testV2RayWebsocketInbound(t, 0, "")
  37. })
  38. t.Run("inbound-early-data", func(t *testing.T) {
  39. testV2RayWebsocketInbound(t, 2048, "")
  40. })
  41. t.Run("inbound-xray-early-data", func(t *testing.T) {
  42. testV2RayWebsocketInbound(t, 2048, "Sec-WebSocket-Protocol")
  43. })
  44. t.Run("outbound", func(t *testing.T) {
  45. testV2RayWebsocketOutbound(t, 0, "")
  46. })
  47. t.Run("outbound-early-data", func(t *testing.T) {
  48. testV2RayWebsocketOutbound(t, 2048, "")
  49. })
  50. t.Run("outbound-xray-early-data", func(t *testing.T) {
  51. testV2RayWebsocketOutbound(t, 2048, "Sec-WebSocket-Protocol")
  52. })
  53. }
  54. func testV2RayWebsocketInbound(t *testing.T, maxEarlyData uint32, earlyDataHeaderName string) {
  55. userId, err := uuid.DefaultGenerator.NewV4()
  56. require.NoError(t, err)
  57. _, certPem, keyPem := createSelfSignedCertificate(t, "example.org")
  58. startInstance(t, option.Options{
  59. Inbounds: []option.Inbound{
  60. {
  61. Type: C.TypeVMess,
  62. VMessOptions: option.VMessInboundOptions{
  63. ListenOptions: option.ListenOptions{
  64. Listen: option.ListenAddress(netip.IPv4Unspecified()),
  65. ListenPort: serverPort,
  66. },
  67. Users: []option.VMessUser{
  68. {
  69. Name: "sekai",
  70. UUID: userId.String(),
  71. },
  72. },
  73. TLS: &option.InboundTLSOptions{
  74. Enabled: true,
  75. ServerName: "example.org",
  76. CertificatePath: certPem,
  77. KeyPath: keyPem,
  78. },
  79. Transport: &option.V2RayTransportOptions{
  80. Type: C.V2RayTransportTypeWebsocket,
  81. WebsocketOptions: option.V2RayWebsocketOptions{
  82. MaxEarlyData: maxEarlyData,
  83. EarlyDataHeaderName: earlyDataHeaderName,
  84. },
  85. },
  86. },
  87. },
  88. },
  89. })
  90. content, err := os.ReadFile("config/vmess-ws-client.json")
  91. require.NoError(t, err)
  92. config, err := ajson.Unmarshal(content)
  93. require.NoError(t, err)
  94. config.MustKey("inbounds").MustIndex(0).MustKey("port").SetNumeric(float64(clientPort))
  95. outbound := config.MustKey("outbounds").MustIndex(0)
  96. settings := outbound.MustKey("settings").MustKey("vnext").MustIndex(0)
  97. settings.MustKey("port").SetNumeric(float64(serverPort))
  98. user := settings.MustKey("users").MustIndex(0)
  99. user.MustKey("id").SetString(userId.String())
  100. wsSettings := outbound.MustKey("streamSettings").MustKey("wsSettings")
  101. wsSettings.MustKey("maxEarlyData").SetNumeric(float64(maxEarlyData))
  102. wsSettings.MustKey("earlyDataHeaderName").SetString(earlyDataHeaderName)
  103. content, err = ajson.Marshal(config)
  104. require.NoError(t, err)
  105. startDockerContainer(t, DockerOptions{
  106. Image: ImageV2RayCore,
  107. Ports: []uint16{serverPort, testPort},
  108. EntryPoint: "v2ray",
  109. Stdin: content,
  110. Bind: map[string]string{
  111. certPem: "/path/to/certificate.crt",
  112. keyPem: "/path/to/private.key",
  113. },
  114. })
  115. testSuitSimple(t, clientPort, testPort)
  116. }
  117. func testV2RayWebsocketOutbound(t *testing.T, maxEarlyData uint32, earlyDataHeaderName string) {
  118. userId, err := uuid.DefaultGenerator.NewV4()
  119. require.NoError(t, err)
  120. _, certPem, keyPem := createSelfSignedCertificate(t, "example.org")
  121. content, err := os.ReadFile("config/vmess-ws-server.json")
  122. require.NoError(t, err)
  123. config, err := ajson.Unmarshal(content)
  124. require.NoError(t, err)
  125. inbound := config.MustKey("inbounds").MustIndex(0)
  126. inbound.MustKey("port").SetNumeric(float64(serverPort))
  127. inbound.MustKey("settings").MustKey("clients").MustIndex(0).MustKey("id").SetString(userId.String())
  128. wsSettings := inbound.MustKey("streamSettings").MustKey("wsSettings")
  129. wsSettings.MustKey("maxEarlyData").SetNumeric(float64(maxEarlyData))
  130. wsSettings.MustKey("earlyDataHeaderName").SetString(earlyDataHeaderName)
  131. content, err = ajson.Marshal(config)
  132. require.NoError(t, err)
  133. startDockerContainer(t, DockerOptions{
  134. Image: ImageV2RayCore,
  135. Ports: []uint16{serverPort, testPort},
  136. EntryPoint: "v2ray",
  137. Stdin: content,
  138. Env: []string{"V2RAY_VMESS_AEAD_FORCED=false"},
  139. Bind: map[string]string{
  140. certPem: "/path/to/certificate.crt",
  141. keyPem: "/path/to/private.key",
  142. },
  143. })
  144. startInstance(t, option.Options{
  145. Inbounds: []option.Inbound{
  146. {
  147. Type: C.TypeMixed,
  148. Tag: "mixed-in",
  149. MixedOptions: option.HTTPMixedInboundOptions{
  150. ListenOptions: option.ListenOptions{
  151. Listen: option.ListenAddress(netip.IPv4Unspecified()),
  152. ListenPort: clientPort,
  153. },
  154. },
  155. },
  156. },
  157. Outbounds: []option.Outbound{
  158. {
  159. Type: C.TypeVMess,
  160. Tag: "vmess-out",
  161. VMessOptions: option.VMessOutboundOptions{
  162. ServerOptions: option.ServerOptions{
  163. Server: "127.0.0.1",
  164. ServerPort: serverPort,
  165. },
  166. UUID: userId.String(),
  167. Security: "zero",
  168. TLS: &option.OutboundTLSOptions{
  169. Enabled: true,
  170. ServerName: "example.org",
  171. CertificatePath: certPem,
  172. },
  173. Transport: &option.V2RayTransportOptions{
  174. Type: C.V2RayTransportTypeWebsocket,
  175. WebsocketOptions: option.V2RayWebsocketOptions{
  176. MaxEarlyData: maxEarlyData,
  177. EarlyDataHeaderName: earlyDataHeaderName,
  178. },
  179. },
  180. },
  181. },
  182. },
  183. })
  184. testSuit(t, clientPort, testPort)
  185. }