1
0

shadowtls_test.go 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. package main
  2. import (
  3. "context"
  4. "net"
  5. "net/http"
  6. "net/netip"
  7. "testing"
  8. C "github.com/sagernet/sing-box/constant"
  9. "github.com/sagernet/sing-box/option"
  10. "github.com/sagernet/sing-shadowsocks/shadowaead_2022"
  11. "github.com/sagernet/sing/common"
  12. F "github.com/sagernet/sing/common/format"
  13. "github.com/sagernet/sing/common/json/badoption"
  14. "github.com/stretchr/testify/require"
  15. )
  16. func TestShadowTLS(t *testing.T) {
  17. t.Run("v1", func(t *testing.T) {
  18. testShadowTLS(t, 1, "", false)
  19. })
  20. t.Run("v2", func(t *testing.T) {
  21. testShadowTLS(t, 2, "hello", false)
  22. })
  23. t.Run("v3", func(t *testing.T) {
  24. testShadowTLS(t, 3, "hello", false)
  25. })
  26. t.Run("v2-utls", func(t *testing.T) {
  27. testShadowTLS(t, 2, "hello", true)
  28. })
  29. t.Run("v3-utls", func(t *testing.T) {
  30. testShadowTLS(t, 3, "hello", true)
  31. })
  32. }
  33. func testShadowTLS(t *testing.T, version int, password string, utlsEanbled bool) {
  34. method := shadowaead_2022.List[0]
  35. ssPassword := mkBase64(t, 16)
  36. startInstance(t, option.Options{
  37. Inbounds: []option.Inbound{
  38. {
  39. Type: C.TypeMixed,
  40. Options: &option.HTTPMixedInboundOptions{
  41. ListenOptions: option.ListenOptions{
  42. Listen: common.Ptr(badoption.Addr(netip.IPv4Unspecified())),
  43. ListenPort: clientPort,
  44. },
  45. },
  46. },
  47. {
  48. Type: C.TypeShadowTLS,
  49. Tag: "in",
  50. Options: &option.ShadowTLSInboundOptions{
  51. ListenOptions: option.ListenOptions{
  52. Listen: common.Ptr(badoption.Addr(netip.IPv4Unspecified())),
  53. ListenPort: serverPort,
  54. InboundOptions: option.InboundOptions{
  55. Detour: "detour",
  56. },
  57. },
  58. Handshake: option.ShadowTLSHandshakeOptions{
  59. ServerOptions: option.ServerOptions{
  60. Server: "google.com",
  61. ServerPort: 443,
  62. },
  63. },
  64. Version: version,
  65. Password: password,
  66. Users: []option.ShadowTLSUser{{Password: password}},
  67. },
  68. },
  69. {
  70. Type: C.TypeShadowsocks,
  71. Tag: "detour",
  72. Options: &option.ShadowsocksInboundOptions{
  73. ListenOptions: option.ListenOptions{
  74. Listen: common.Ptr(badoption.Addr(netip.IPv4Unspecified())),
  75. ListenPort: otherPort,
  76. },
  77. Method: method,
  78. Password: ssPassword,
  79. },
  80. },
  81. },
  82. Outbounds: []option.Outbound{
  83. {
  84. Type: C.TypeShadowsocks,
  85. Options: &option.ShadowsocksOutboundOptions{
  86. Method: method,
  87. Password: ssPassword,
  88. DialerOptions: option.DialerOptions{
  89. Detour: "detour",
  90. },
  91. },
  92. },
  93. {
  94. Type: C.TypeShadowTLS,
  95. Tag: "detour",
  96. Options: &option.ShadowTLSOutboundOptions{
  97. ServerOptions: option.ServerOptions{
  98. Server: "127.0.0.1",
  99. ServerPort: serverPort,
  100. },
  101. OutboundTLSOptionsContainer: option.OutboundTLSOptionsContainer{
  102. TLS: &option.OutboundTLSOptions{
  103. Enabled: true,
  104. ServerName: "google.com",
  105. UTLS: &option.OutboundUTLSOptions{
  106. Enabled: utlsEanbled,
  107. },
  108. },
  109. },
  110. Version: version,
  111. Password: password,
  112. },
  113. },
  114. {
  115. Type: C.TypeDirect,
  116. Tag: "direct",
  117. },
  118. },
  119. Route: &option.RouteOptions{
  120. Rules: []option.Rule{
  121. {
  122. Type: C.RuleTypeDefault,
  123. DefaultOptions: option.DefaultRule{
  124. RawDefaultRule: option.RawDefaultRule{
  125. Inbound: []string{"detour"},
  126. },
  127. RuleAction: option.RuleAction{
  128. Action: C.RuleActionTypeRoute,
  129. RouteOptions: option.RouteActionOptions{
  130. Outbound: "direct",
  131. },
  132. },
  133. },
  134. },
  135. },
  136. },
  137. })
  138. testTCP(t, clientPort, testPort)
  139. }
  140. func TestShadowTLSFallback(t *testing.T) {
  141. startInstance(t, option.Options{
  142. Inbounds: []option.Inbound{
  143. {
  144. Type: C.TypeShadowTLS,
  145. Options: &option.ShadowTLSInboundOptions{
  146. ListenOptions: option.ListenOptions{
  147. Listen: common.Ptr(badoption.Addr(netip.IPv4Unspecified())),
  148. ListenPort: serverPort,
  149. },
  150. Handshake: option.ShadowTLSHandshakeOptions{
  151. ServerOptions: option.ServerOptions{
  152. Server: "google.com",
  153. ServerPort: 443,
  154. },
  155. },
  156. Version: 3,
  157. Users: []option.ShadowTLSUser{
  158. {Password: "hello"},
  159. },
  160. },
  161. },
  162. },
  163. })
  164. client := &http.Client{
  165. Transport: &http.Transport{
  166. DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
  167. var d net.Dialer
  168. return d.DialContext(ctx, network, "127.0.0.1:"+F.ToString(serverPort))
  169. },
  170. },
  171. }
  172. response, err := client.Get("https://google.com")
  173. require.NoError(t, err)
  174. require.Equal(t, response.StatusCode, 200)
  175. response.Body.Close()
  176. client.CloseIdleConnections()
  177. }
  178. func TestShadowTLSInbound(t *testing.T) {
  179. method := shadowaead_2022.List[0]
  180. password := mkBase64(t, 16)
  181. startDockerContainer(t, DockerOptions{
  182. Image: ImageShadowTLS,
  183. Ports: []uint16{serverPort, otherPort},
  184. EntryPoint: "shadow-tls",
  185. Cmd: []string{"--v3", "--threads", "1", "client", "--listen", "0.0.0.0:" + F.ToString(otherPort), "--server", "127.0.0.1:" + F.ToString(serverPort), "--sni", "google.com", "--password", password},
  186. })
  187. startInstance(t, option.Options{
  188. Inbounds: []option.Inbound{
  189. {
  190. Type: C.TypeMixed,
  191. Tag: "in",
  192. Options: &option.HTTPMixedInboundOptions{
  193. ListenOptions: option.ListenOptions{
  194. Listen: common.Ptr(badoption.Addr(netip.IPv4Unspecified())),
  195. ListenPort: clientPort,
  196. },
  197. },
  198. },
  199. {
  200. Type: C.TypeShadowTLS,
  201. Options: &option.ShadowTLSInboundOptions{
  202. ListenOptions: option.ListenOptions{
  203. Listen: common.Ptr(badoption.Addr(netip.IPv4Unspecified())),
  204. ListenPort: serverPort,
  205. InboundOptions: option.InboundOptions{
  206. Detour: "detour",
  207. },
  208. },
  209. Handshake: option.ShadowTLSHandshakeOptions{
  210. ServerOptions: option.ServerOptions{
  211. Server: "google.com",
  212. ServerPort: 443,
  213. },
  214. },
  215. Version: 3,
  216. Users: []option.ShadowTLSUser{
  217. {Password: password},
  218. },
  219. },
  220. },
  221. {
  222. Type: C.TypeShadowsocks,
  223. Tag: "detour",
  224. Options: &option.ShadowsocksInboundOptions{
  225. ListenOptions: option.ListenOptions{
  226. Listen: common.Ptr(badoption.Addr(netip.IPv4Unspecified())),
  227. },
  228. Method: method,
  229. Password: password,
  230. },
  231. },
  232. },
  233. Outbounds: []option.Outbound{
  234. {
  235. Type: C.TypeDirect,
  236. },
  237. {
  238. Type: C.TypeShadowsocks,
  239. Tag: "out",
  240. Options: &option.ShadowsocksOutboundOptions{
  241. ServerOptions: option.ServerOptions{
  242. Server: "127.0.0.1",
  243. ServerPort: otherPort,
  244. },
  245. Method: method,
  246. Password: password,
  247. },
  248. },
  249. },
  250. Route: &option.RouteOptions{
  251. Rules: []option.Rule{
  252. {
  253. Type: C.RuleTypeDefault,
  254. DefaultOptions: option.DefaultRule{
  255. RawDefaultRule: option.RawDefaultRule{
  256. Inbound: []string{"in"},
  257. },
  258. RuleAction: option.RuleAction{
  259. Action: C.RuleActionTypeRoute,
  260. RouteOptions: option.RouteActionOptions{
  261. Outbound: "out",
  262. },
  263. },
  264. },
  265. },
  266. },
  267. },
  268. })
  269. testTCP(t, clientPort, testPort)
  270. }
  271. func TestShadowTLSOutbound(t *testing.T) {
  272. method := shadowaead_2022.List[0]
  273. password := mkBase64(t, 16)
  274. startDockerContainer(t, DockerOptions{
  275. Image: ImageShadowTLS,
  276. Ports: []uint16{serverPort, otherPort},
  277. EntryPoint: "shadow-tls",
  278. Cmd: []string{"--v3", "--threads", "1", "server", "--listen", "0.0.0.0:" + F.ToString(serverPort), "--server", "127.0.0.1:" + F.ToString(otherPort), "--tls", "google.com:443", "--password", "hello"},
  279. Env: []string{"RUST_LOG=trace"},
  280. })
  281. startInstance(t, option.Options{
  282. Inbounds: []option.Inbound{
  283. {
  284. Type: C.TypeMixed,
  285. Options: &option.HTTPMixedInboundOptions{
  286. ListenOptions: option.ListenOptions{
  287. Listen: common.Ptr(badoption.Addr(netip.IPv4Unspecified())),
  288. ListenPort: clientPort,
  289. },
  290. },
  291. },
  292. {
  293. Type: C.TypeShadowsocks,
  294. Tag: "detour",
  295. Options: &option.ShadowsocksInboundOptions{
  296. ListenOptions: option.ListenOptions{
  297. Listen: common.Ptr(badoption.Addr(netip.IPv4Unspecified())),
  298. ListenPort: otherPort,
  299. },
  300. Method: method,
  301. Password: password,
  302. },
  303. },
  304. },
  305. Outbounds: []option.Outbound{
  306. {
  307. Type: C.TypeShadowsocks,
  308. Options: &option.ShadowsocksOutboundOptions{
  309. Method: method,
  310. Password: password,
  311. DialerOptions: option.DialerOptions{
  312. Detour: "detour",
  313. },
  314. },
  315. },
  316. {
  317. Type: C.TypeShadowTLS,
  318. Tag: "detour",
  319. Options: &option.ShadowTLSOutboundOptions{
  320. ServerOptions: option.ServerOptions{
  321. Server: "127.0.0.1",
  322. ServerPort: serverPort,
  323. },
  324. OutboundTLSOptionsContainer: option.OutboundTLSOptionsContainer{
  325. TLS: &option.OutboundTLSOptions{
  326. Enabled: true,
  327. ServerName: "google.com",
  328. },
  329. },
  330. Version: 3,
  331. Password: "hello",
  332. },
  333. },
  334. {
  335. Type: C.TypeDirect,
  336. Tag: "direct",
  337. },
  338. },
  339. Route: &option.RouteOptions{
  340. Rules: []option.Rule{
  341. {
  342. Type: C.RuleTypeDefault,
  343. DefaultOptions: option.DefaultRule{
  344. RawDefaultRule: option.RawDefaultRule{
  345. Inbound: []string{"detour"},
  346. },
  347. RuleAction: option.RuleAction{
  348. Action: C.RuleActionTypeRoute,
  349. RouteOptions: option.RouteActionOptions{
  350. Outbound: "direct",
  351. },
  352. },
  353. },
  354. },
  355. },
  356. },
  357. })
  358. testTCP(t, clientPort, testPort)
  359. }