vmess_test.go 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  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 TestVMessAuto(t *testing.T) {
  13. security := "auto"
  14. user, err := uuid.DefaultGenerator.NewV4()
  15. require.NoError(t, err)
  16. t.Run("self", func(t *testing.T) {
  17. testVMessSelf(t, security, user, 0, false, false, false)
  18. })
  19. t.Run("packetaddr", func(t *testing.T) {
  20. testVMessSelf(t, security, user, 0, false, false, true)
  21. })
  22. t.Run("inbound", func(t *testing.T) {
  23. testVMessInboundWithV2Ray(t, security, user, 0, false)
  24. })
  25. t.Run("outbound", func(t *testing.T) {
  26. testVMessOutboundWithV2Ray(t, security, user, false, false, 0)
  27. })
  28. }
  29. func _TestVMess(t *testing.T) {
  30. for _, security := range []string{
  31. "zero",
  32. } {
  33. t.Run(security, func(t *testing.T) {
  34. testVMess0(t, security)
  35. })
  36. }
  37. for _, security := range []string{
  38. "aes-128-gcm", "chacha20-poly1305", "aes-128-cfb",
  39. } {
  40. t.Run(security, func(t *testing.T) {
  41. testVMess1(t, security)
  42. })
  43. }
  44. }
  45. func testVMess0(t *testing.T, security string) {
  46. user, err := uuid.DefaultGenerator.NewV4()
  47. require.NoError(t, err)
  48. t.Run("self", func(t *testing.T) {
  49. testVMessSelf(t, security, user, 0, false, false, false)
  50. })
  51. t.Run("self-legacy", func(t *testing.T) {
  52. testVMessSelf(t, security, user, 1, false, false, false)
  53. })
  54. t.Run("packetaddr", func(t *testing.T) {
  55. testVMessSelf(t, security, user, 0, false, false, true)
  56. })
  57. t.Run("outbound", func(t *testing.T) {
  58. testVMessOutboundWithV2Ray(t, security, user, false, false, 0)
  59. })
  60. t.Run("outbound-legacy", func(t *testing.T) {
  61. testVMessOutboundWithV2Ray(t, security, user, false, false, 1)
  62. })
  63. }
  64. func testVMess1(t *testing.T, security string) {
  65. user, err := uuid.DefaultGenerator.NewV4()
  66. require.NoError(t, err)
  67. t.Run("self", func(t *testing.T) {
  68. testVMessSelf(t, security, user, 0, false, false, false)
  69. })
  70. t.Run("self-padding", func(t *testing.T) {
  71. testVMessSelf(t, security, user, 0, true, false, false)
  72. })
  73. t.Run("self-authid", func(t *testing.T) {
  74. testVMessSelf(t, security, user, 0, false, true, false)
  75. })
  76. t.Run("self-padding-authid", func(t *testing.T) {
  77. testVMessSelf(t, security, user, 0, true, true, false)
  78. })
  79. t.Run("self-legacy", func(t *testing.T) {
  80. testVMessSelf(t, security, user, 1, false, false, false)
  81. })
  82. t.Run("self-legacy-padding", func(t *testing.T) {
  83. testVMessSelf(t, security, user, 1, true, false, false)
  84. })
  85. t.Run("packetaddr", func(t *testing.T) {
  86. testVMessSelf(t, security, user, 0, false, false, true)
  87. })
  88. t.Run("inbound", func(t *testing.T) {
  89. testVMessInboundWithV2Ray(t, security, user, 0, false)
  90. })
  91. t.Run("inbound-authid", func(t *testing.T) {
  92. testVMessInboundWithV2Ray(t, security, user, 0, true)
  93. })
  94. t.Run("inbound-legacy", func(t *testing.T) {
  95. testVMessInboundWithV2Ray(t, security, user, 64, false)
  96. })
  97. t.Run("outbound", func(t *testing.T) {
  98. testVMessOutboundWithV2Ray(t, security, user, false, false, 0)
  99. })
  100. t.Run("outbound-padding", func(t *testing.T) {
  101. testVMessOutboundWithV2Ray(t, security, user, true, false, 0)
  102. })
  103. t.Run("outbound-authid", func(t *testing.T) {
  104. testVMessOutboundWithV2Ray(t, security, user, false, true, 0)
  105. })
  106. t.Run("outbound-padding-authid", func(t *testing.T) {
  107. testVMessOutboundWithV2Ray(t, security, user, true, true, 0)
  108. })
  109. t.Run("outbound-legacy", func(t *testing.T) {
  110. testVMessOutboundWithV2Ray(t, security, user, false, false, 1)
  111. })
  112. t.Run("outbound-legacy-padding", func(t *testing.T) {
  113. testVMessOutboundWithV2Ray(t, security, user, true, false, 1)
  114. })
  115. }
  116. func testVMessInboundWithV2Ray(t *testing.T, security string, uuid uuid.UUID, alterId int, authenticatedLength bool) {
  117. content, err := os.ReadFile("config/vmess-client.json")
  118. require.NoError(t, err)
  119. config, err := ajson.Unmarshal(content)
  120. require.NoError(t, err)
  121. config.MustKey("inbounds").MustIndex(0).MustKey("port").SetNumeric(float64(clientPort))
  122. outbound := config.MustKey("outbounds").MustIndex(0).MustKey("settings").MustKey("vnext").MustIndex(0)
  123. outbound.MustKey("port").SetNumeric(float64(serverPort))
  124. user := outbound.MustKey("users").MustIndex(0)
  125. user.MustKey("id").SetString(uuid.String())
  126. user.MustKey("alterId").SetNumeric(float64(alterId))
  127. user.MustKey("security").SetString(security)
  128. var experiments string
  129. if authenticatedLength {
  130. experiments += "AuthenticatedLength"
  131. }
  132. user.MustKey("experiments").SetString(experiments)
  133. content, err = ajson.Marshal(config)
  134. require.NoError(t, err)
  135. startDockerContainer(t, DockerOptions{
  136. Image: ImageV2RayCore,
  137. Ports: []uint16{serverPort, testPort},
  138. EntryPoint: "v2ray",
  139. Stdin: content,
  140. Env: []string{"V2RAY_VMESS_AEAD_FORCED=false"},
  141. })
  142. startInstance(t, option.Options{
  143. Log: &option.LogOptions{
  144. Level: "error",
  145. },
  146. Inbounds: []option.Inbound{
  147. {
  148. Type: C.TypeVMess,
  149. VMessOptions: option.VMessInboundOptions{
  150. ListenOptions: option.ListenOptions{
  151. Listen: option.ListenAddress(netip.IPv4Unspecified()),
  152. ListenPort: serverPort,
  153. },
  154. Users: []option.VMessUser{
  155. {
  156. Name: "sekai",
  157. UUID: uuid.String(),
  158. AlterId: alterId,
  159. },
  160. },
  161. },
  162. },
  163. },
  164. })
  165. testSuit(t, clientPort, testPort)
  166. }
  167. func testVMessOutboundWithV2Ray(t *testing.T, security string, uuid uuid.UUID, globalPadding bool, authenticatedLength bool, alterId int) {
  168. content, err := os.ReadFile("config/vmess-server.json")
  169. require.NoError(t, err)
  170. config, err := ajson.Unmarshal(content)
  171. require.NoError(t, err)
  172. inbound := config.MustKey("inbounds").MustIndex(0)
  173. inbound.MustKey("port").SetNumeric(float64(serverPort))
  174. inbound.MustKey("settings").MustKey("clients").MustIndex(0).MustKey("id").SetString(uuid.String())
  175. inbound.MustKey("settings").MustKey("clients").MustIndex(0).MustKey("alterId").SetNumeric(float64(alterId))
  176. content, err = ajson.Marshal(config)
  177. require.NoError(t, err)
  178. startDockerContainer(t, DockerOptions{
  179. Image: ImageV2RayCore,
  180. Ports: []uint16{serverPort, testPort},
  181. EntryPoint: "v2ray",
  182. Stdin: content,
  183. Env: []string{"V2RAY_VMESS_AEAD_FORCED=false"},
  184. })
  185. startInstance(t, option.Options{
  186. Log: &option.LogOptions{
  187. Level: "error",
  188. },
  189. Inbounds: []option.Inbound{
  190. {
  191. Type: C.TypeMixed,
  192. MixedOptions: option.HTTPMixedInboundOptions{
  193. ListenOptions: option.ListenOptions{
  194. Listen: option.ListenAddress(netip.IPv4Unspecified()),
  195. ListenPort: clientPort,
  196. },
  197. },
  198. },
  199. },
  200. Outbounds: []option.Outbound{
  201. {
  202. Type: C.TypeVMess,
  203. VMessOptions: option.VMessOutboundOptions{
  204. ServerOptions: option.ServerOptions{
  205. Server: "127.0.0.1",
  206. ServerPort: serverPort,
  207. },
  208. Security: security,
  209. UUID: uuid.String(),
  210. GlobalPadding: globalPadding,
  211. AuthenticatedLength: authenticatedLength,
  212. AlterId: alterId,
  213. },
  214. },
  215. },
  216. })
  217. testSuit(t, clientPort, testPort)
  218. }
  219. func testVMessSelf(t *testing.T, security string, uuid uuid.UUID, alterId int, globalPadding bool, authenticatedLength bool, packetAddr bool) {
  220. startInstance(t, option.Options{
  221. Log: &option.LogOptions{
  222. Level: "trace",
  223. },
  224. Inbounds: []option.Inbound{
  225. {
  226. Type: C.TypeMixed,
  227. Tag: "mixed-in",
  228. MixedOptions: option.HTTPMixedInboundOptions{
  229. ListenOptions: option.ListenOptions{
  230. Listen: option.ListenAddress(netip.IPv4Unspecified()),
  231. ListenPort: clientPort,
  232. },
  233. },
  234. },
  235. {
  236. Type: C.TypeVMess,
  237. VMessOptions: option.VMessInboundOptions{
  238. ListenOptions: option.ListenOptions{
  239. Listen: option.ListenAddress(netip.IPv4Unspecified()),
  240. ListenPort: serverPort,
  241. },
  242. Users: []option.VMessUser{
  243. {
  244. Name: "sekai",
  245. UUID: uuid.String(),
  246. AlterId: alterId,
  247. },
  248. },
  249. },
  250. },
  251. },
  252. Outbounds: []option.Outbound{
  253. {
  254. Type: C.TypeDirect,
  255. },
  256. {
  257. Type: C.TypeVMess,
  258. Tag: "vmess-out",
  259. VMessOptions: option.VMessOutboundOptions{
  260. ServerOptions: option.ServerOptions{
  261. Server: "127.0.0.1",
  262. ServerPort: serverPort,
  263. },
  264. Security: security,
  265. UUID: uuid.String(),
  266. AlterId: alterId,
  267. GlobalPadding: globalPadding,
  268. AuthenticatedLength: authenticatedLength,
  269. PacketAddr: packetAddr,
  270. },
  271. },
  272. },
  273. Route: &option.RouteOptions{
  274. Rules: []option.Rule{
  275. {
  276. DefaultOptions: option.DefaultRule{
  277. Inbound: []string{"mixed-in"},
  278. Outbound: "vmess-out",
  279. },
  280. },
  281. },
  282. },
  283. })
  284. testSuit(t, clientPort, testPort)
  285. }