You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

215 lines
5.0 KiB

  1. // Copyright 2011 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package proxy
  5. import (
  6. "bytes"
  7. "fmt"
  8. "io"
  9. "net"
  10. "net/url"
  11. "os"
  12. "strconv"
  13. "strings"
  14. "sync"
  15. "testing"
  16. )
  17. type proxyFromEnvTest struct {
  18. allProxyEnv string
  19. noProxyEnv string
  20. wantTypeOf Dialer
  21. }
  22. func (t proxyFromEnvTest) String() string {
  23. var buf bytes.Buffer
  24. space := func() {
  25. if buf.Len() > 0 {
  26. buf.WriteByte(' ')
  27. }
  28. }
  29. if t.allProxyEnv != "" {
  30. fmt.Fprintf(&buf, "all_proxy=%q", t.allProxyEnv)
  31. }
  32. if t.noProxyEnv != "" {
  33. space()
  34. fmt.Fprintf(&buf, "no_proxy=%q", t.noProxyEnv)
  35. }
  36. return strings.TrimSpace(buf.String())
  37. }
  38. func TestFromEnvironment(t *testing.T) {
  39. ResetProxyEnv()
  40. type dummyDialer struct {
  41. direct
  42. }
  43. RegisterDialerType("irc", func(_ *url.URL, _ Dialer) (Dialer, error) {
  44. return dummyDialer{}, nil
  45. })
  46. proxyFromEnvTests := []proxyFromEnvTest{
  47. {allProxyEnv: "127.0.0.1:8080", noProxyEnv: "localhost, 127.0.0.1", wantTypeOf: direct{}},
  48. {allProxyEnv: "ftp://example.com:8000", noProxyEnv: "localhost, 127.0.0.1", wantTypeOf: direct{}},
  49. {allProxyEnv: "socks5://example.com:8080", noProxyEnv: "localhost, 127.0.0.1", wantTypeOf: &PerHost{}},
  50. {allProxyEnv: "irc://example.com:8000", wantTypeOf: dummyDialer{}},
  51. {noProxyEnv: "localhost, 127.0.0.1", wantTypeOf: direct{}},
  52. {wantTypeOf: direct{}},
  53. }
  54. for _, tt := range proxyFromEnvTests {
  55. os.Setenv("ALL_PROXY", tt.allProxyEnv)
  56. os.Setenv("NO_PROXY", tt.noProxyEnv)
  57. ResetCachedEnvironment()
  58. d := FromEnvironment()
  59. if got, want := fmt.Sprintf("%T", d), fmt.Sprintf("%T", tt.wantTypeOf); got != want {
  60. t.Errorf("%v: got type = %T, want %T", tt, d, tt.wantTypeOf)
  61. }
  62. }
  63. }
  64. func TestFromURL(t *testing.T) {
  65. endSystem, err := net.Listen("tcp", "127.0.0.1:0")
  66. if err != nil {
  67. t.Fatalf("net.Listen failed: %v", err)
  68. }
  69. defer endSystem.Close()
  70. gateway, err := net.Listen("tcp", "127.0.0.1:0")
  71. if err != nil {
  72. t.Fatalf("net.Listen failed: %v", err)
  73. }
  74. defer gateway.Close()
  75. var wg sync.WaitGroup
  76. wg.Add(1)
  77. go socks5Gateway(t, gateway, endSystem, socks5Domain, &wg)
  78. url, err := url.Parse("socks5://user:password@" + gateway.Addr().String())
  79. if err != nil {
  80. t.Fatalf("url.Parse failed: %v", err)
  81. }
  82. proxy, err := FromURL(url, Direct)
  83. if err != nil {
  84. t.Fatalf("FromURL failed: %v", err)
  85. }
  86. _, port, err := net.SplitHostPort(endSystem.Addr().String())
  87. if err != nil {
  88. t.Fatalf("net.SplitHostPort failed: %v", err)
  89. }
  90. if c, err := proxy.Dial("tcp", "localhost:"+port); err != nil {
  91. t.Fatalf("FromURL.Dial failed: %v", err)
  92. } else {
  93. c.Close()
  94. }
  95. wg.Wait()
  96. }
  97. func TestSOCKS5(t *testing.T) {
  98. endSystem, err := net.Listen("tcp", "127.0.0.1:0")
  99. if err != nil {
  100. t.Fatalf("net.Listen failed: %v", err)
  101. }
  102. defer endSystem.Close()
  103. gateway, err := net.Listen("tcp", "127.0.0.1:0")
  104. if err != nil {
  105. t.Fatalf("net.Listen failed: %v", err)
  106. }
  107. defer gateway.Close()
  108. var wg sync.WaitGroup
  109. wg.Add(1)
  110. go socks5Gateway(t, gateway, endSystem, socks5IP4, &wg)
  111. proxy, err := SOCKS5("tcp", gateway.Addr().String(), nil, Direct)
  112. if err != nil {
  113. t.Fatalf("SOCKS5 failed: %v", err)
  114. }
  115. if c, err := proxy.Dial("tcp", endSystem.Addr().String()); err != nil {
  116. t.Fatalf("SOCKS5.Dial failed: %v", err)
  117. } else {
  118. c.Close()
  119. }
  120. wg.Wait()
  121. }
  122. func socks5Gateway(t *testing.T, gateway, endSystem net.Listener, typ byte, wg *sync.WaitGroup) {
  123. defer wg.Done()
  124. c, err := gateway.Accept()
  125. if err != nil {
  126. t.Errorf("net.Listener.Accept failed: %v", err)
  127. return
  128. }
  129. defer c.Close()
  130. b := make([]byte, 32)
  131. var n int
  132. if typ == socks5Domain {
  133. n = 4
  134. } else {
  135. n = 3
  136. }
  137. if _, err := io.ReadFull(c, b[:n]); err != nil {
  138. t.Errorf("io.ReadFull failed: %v", err)
  139. return
  140. }
  141. if _, err := c.Write([]byte{socks5Version, socks5AuthNone}); err != nil {
  142. t.Errorf("net.Conn.Write failed: %v", err)
  143. return
  144. }
  145. if typ == socks5Domain {
  146. n = 16
  147. } else {
  148. n = 10
  149. }
  150. if _, err := io.ReadFull(c, b[:n]); err != nil {
  151. t.Errorf("io.ReadFull failed: %v", err)
  152. return
  153. }
  154. if b[0] != socks5Version || b[1] != socks5Connect || b[2] != 0x00 || b[3] != typ {
  155. t.Errorf("got an unexpected packet: %#02x %#02x %#02x %#02x", b[0], b[1], b[2], b[3])
  156. return
  157. }
  158. if typ == socks5Domain {
  159. copy(b[:5], []byte{socks5Version, 0x00, 0x00, socks5Domain, 9})
  160. b = append(b, []byte("localhost")...)
  161. } else {
  162. copy(b[:4], []byte{socks5Version, 0x00, 0x00, socks5IP4})
  163. }
  164. host, port, err := net.SplitHostPort(endSystem.Addr().String())
  165. if err != nil {
  166. t.Errorf("net.SplitHostPort failed: %v", err)
  167. return
  168. }
  169. b = append(b, []byte(net.ParseIP(host).To4())...)
  170. p, err := strconv.Atoi(port)
  171. if err != nil {
  172. t.Errorf("strconv.Atoi failed: %v", err)
  173. return
  174. }
  175. b = append(b, []byte{byte(p >> 8), byte(p)}...)
  176. if _, err := c.Write(b); err != nil {
  177. t.Errorf("net.Conn.Write failed: %v", err)
  178. return
  179. }
  180. }
  181. func ResetProxyEnv() {
  182. for _, env := range []*envOnce{allProxyEnv, noProxyEnv} {
  183. for _, v := range env.names {
  184. os.Setenv(v, "")
  185. }
  186. }
  187. ResetCachedEnvironment()
  188. }
  189. func ResetCachedEnvironment() {
  190. allProxyEnv.reset()
  191. noProxyEnv.reset()
  192. }