shadowsocks_test.go 5.1 KB

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