shadowsocks_test.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. package main
  2. import (
  3. "crypto/rand"
  4. "encoding/base64"
  5. "net/netip"
  6. "testing"
  7. C "github.com/sagernet/sing-box/constant"
  8. "github.com/sagernet/sing-box/option"
  9. F "github.com/sagernet/sing/common/format"
  10. "github.com/stretchr/testify/require"
  11. )
  12. func TestShadowsocks(t *testing.T) {
  13. for _, method16 := range []string{
  14. "2022-blake3-aes-128-gcm",
  15. } {
  16. t.Run(method16+"-inbound", func(t *testing.T) {
  17. testShadowsocksInboundWithShadowsocksRust(t, method16, mkBase64(t, 16))
  18. })
  19. t.Run(method16+"-outbound", func(t *testing.T) {
  20. testShadowsocksOutboundWithShadowsocksRust(t, method16, mkBase64(t, 16))
  21. })
  22. t.Run(method16+"-self", func(t *testing.T) {
  23. testShadowsocksSelf(t, method16, mkBase64(t, 16))
  24. })
  25. }
  26. for _, method32 := range []string{
  27. "2022-blake3-aes-256-gcm",
  28. "2022-blake3-chacha20-poly1305",
  29. } {
  30. t.Run(method32+"-inbound", func(t *testing.T) {
  31. testShadowsocksInboundWithShadowsocksRust(t, method32, mkBase64(t, 32))
  32. })
  33. t.Run(method32+"-outbound", func(t *testing.T) {
  34. testShadowsocksOutboundWithShadowsocksRust(t, method32, mkBase64(t, 32))
  35. })
  36. t.Run(method32+"-self", func(t *testing.T) {
  37. testShadowsocksSelf(t, method32, mkBase64(t, 32))
  38. })
  39. }
  40. }
  41. func testShadowsocksInboundWithShadowsocksRust(t *testing.T, method string, password string) {
  42. t.Parallel()
  43. serverPort := mkPort(t)
  44. clientPort := mkPort(t)
  45. testPort := mkPort(t)
  46. startDockerContainer(t, DockerOptions{
  47. Image: ImageShadowsocksRustClient,
  48. EntryPoint: "sslocal",
  49. Ports: []uint16{serverPort, clientPort},
  50. Cmd: []string{"-s", F.ToString("127.0.0.1:", serverPort), "-b", F.ToString("0.0.0.0:", clientPort), "-m", method, "-k", password, "-U"},
  51. })
  52. startInstance(t, option.Options{
  53. Log: &option.LogOption{
  54. Disabled: true,
  55. },
  56. Inbounds: []option.Inbound{
  57. {
  58. Type: C.TypeShadowsocks,
  59. ShadowsocksOptions: option.ShadowsocksInboundOptions{
  60. ListenOptions: option.ListenOptions{
  61. Listen: option.ListenAddress(netip.IPv4Unspecified()),
  62. ListenPort: serverPort,
  63. },
  64. Method: method,
  65. Password: password,
  66. },
  67. },
  68. },
  69. })
  70. testSuit(t, clientPort, testPort)
  71. }
  72. func testShadowsocksOutboundWithShadowsocksRust(t *testing.T, method string, password string) {
  73. t.Parallel()
  74. serverPort := mkPort(t)
  75. clientPort := mkPort(t)
  76. testPort := mkPort(t)
  77. startDockerContainer(t, DockerOptions{
  78. Image: ImageShadowsocksRustServer,
  79. EntryPoint: "ssserver",
  80. Ports: []uint16{serverPort, testPort},
  81. Cmd: []string{"-s", F.ToString("0.0.0.0:", serverPort), "-m", method, "-k", password, "-U"},
  82. })
  83. startInstance(t, option.Options{
  84. Log: &option.LogOption{
  85. Disabled: true,
  86. },
  87. Inbounds: []option.Inbound{
  88. {
  89. Type: C.TypeMixed,
  90. MixedOptions: option.SimpleInboundOptions{
  91. ListenOptions: option.ListenOptions{
  92. Listen: option.ListenAddress(netip.IPv4Unspecified()),
  93. ListenPort: clientPort,
  94. },
  95. },
  96. },
  97. },
  98. Outbounds: []option.Outbound{
  99. {
  100. Type: C.TypeShadowsocks,
  101. ShadowsocksOptions: option.ShadowsocksOutboundOptions{
  102. ServerOptions: option.ServerOptions{
  103. Server: "127.0.0.1",
  104. ServerPort: serverPort,
  105. },
  106. Method: method,
  107. Password: password,
  108. },
  109. },
  110. },
  111. })
  112. testSuit(t, clientPort, testPort)
  113. }
  114. func testShadowsocksSelf(t *testing.T, method string, password string) {
  115. t.Parallel()
  116. serverPort := mkPort(t)
  117. clientPort := mkPort(t)
  118. testPort := mkPort(t)
  119. startInstance(t, option.Options{
  120. Log: &option.LogOption{
  121. Disabled: true,
  122. },
  123. Inbounds: []option.Inbound{
  124. {
  125. Type: C.TypeMixed,
  126. Tag: "mixed-in",
  127. MixedOptions: option.SimpleInboundOptions{
  128. ListenOptions: option.ListenOptions{
  129. Listen: option.ListenAddress(netip.IPv4Unspecified()),
  130. ListenPort: clientPort,
  131. },
  132. },
  133. },
  134. {
  135. Type: C.TypeShadowsocks,
  136. ShadowsocksOptions: option.ShadowsocksInboundOptions{
  137. ListenOptions: option.ListenOptions{
  138. Listen: option.ListenAddress(netip.IPv4Unspecified()),
  139. ListenPort: serverPort,
  140. },
  141. Method: method,
  142. Password: password,
  143. },
  144. },
  145. },
  146. Outbounds: []option.Outbound{
  147. {
  148. Type: C.TypeDirect,
  149. },
  150. {
  151. Type: C.TypeShadowsocks,
  152. Tag: "ss-out",
  153. ShadowsocksOptions: option.ShadowsocksOutboundOptions{
  154. ServerOptions: option.ServerOptions{
  155. Server: "127.0.0.1",
  156. ServerPort: serverPort,
  157. },
  158. Method: method,
  159. Password: password,
  160. },
  161. },
  162. },
  163. Route: &option.RouteOptions{
  164. Rules: []option.Rule{
  165. {
  166. DefaultOptions: option.DefaultRule{
  167. Inbound: []string{"mixed-in"},
  168. Outbound: "ss-out",
  169. },
  170. },
  171. },
  172. },
  173. })
  174. testSuit(t, clientPort, testPort)
  175. }
  176. func mkBase64(t *testing.T, length int) string {
  177. psk := make([]byte, length)
  178. _, err := rand.Read(psk)
  179. require.NoError(t, err)
  180. return base64.StdEncoding.EncodeToString(psk)
  181. }