client.go 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. package plugin
  2. import (
  3. "crypto/tls"
  4. "fmt"
  5. "strconv"
  6. "github.com/onsi/ginkgo/v2"
  7. "github.com/fatedier/frp/pkg/transport"
  8. "github.com/fatedier/frp/test/e2e/framework"
  9. "github.com/fatedier/frp/test/e2e/framework/consts"
  10. "github.com/fatedier/frp/test/e2e/mock/server/httpserver"
  11. "github.com/fatedier/frp/test/e2e/pkg/cert"
  12. "github.com/fatedier/frp/test/e2e/pkg/port"
  13. "github.com/fatedier/frp/test/e2e/pkg/request"
  14. )
  15. var _ = ginkgo.Describe("[Feature: Client-Plugins]", func() {
  16. f := framework.NewDefaultFramework()
  17. ginkgo.Describe("UnixDomainSocket", func() {
  18. ginkgo.It("Expose a unix domain socket echo server", func() {
  19. serverConf := consts.LegacyDefaultServerConfig
  20. clientConf := consts.LegacyDefaultClientConfig
  21. getProxyConf := func(proxyName string, portName string, extra string) string {
  22. return fmt.Sprintf(`
  23. [%s]
  24. type = tcp
  25. remote_port = {{ .%s }}
  26. plugin = unix_domain_socket
  27. plugin_unix_path = {{ .%s }}
  28. `+extra, proxyName, portName, framework.UDSEchoServerAddr)
  29. }
  30. tests := []struct {
  31. proxyName string
  32. portName string
  33. extraConfig string
  34. }{
  35. {
  36. proxyName: "normal",
  37. portName: port.GenName("Normal"),
  38. },
  39. {
  40. proxyName: "with-encryption",
  41. portName: port.GenName("WithEncryption"),
  42. extraConfig: "use_encryption = true",
  43. },
  44. {
  45. proxyName: "with-compression",
  46. portName: port.GenName("WithCompression"),
  47. extraConfig: "use_compression = true",
  48. },
  49. {
  50. proxyName: "with-encryption-and-compression",
  51. portName: port.GenName("WithEncryptionAndCompression"),
  52. extraConfig: `
  53. use_encryption = true
  54. use_compression = true
  55. `,
  56. },
  57. }
  58. // build all client config
  59. for _, test := range tests {
  60. clientConf += getProxyConf(test.proxyName, test.portName, test.extraConfig) + "\n"
  61. }
  62. // run frps and frpc
  63. f.RunProcesses([]string{serverConf}, []string{clientConf})
  64. for _, test := range tests {
  65. framework.NewRequestExpect(f).Port(f.PortByName(test.portName)).Ensure()
  66. }
  67. })
  68. })
  69. ginkgo.It("http_proxy", func() {
  70. serverConf := consts.LegacyDefaultServerConfig
  71. clientConf := consts.LegacyDefaultClientConfig
  72. remotePort := f.AllocPort()
  73. clientConf += fmt.Sprintf(`
  74. [tcp]
  75. type = tcp
  76. remote_port = %d
  77. plugin = http_proxy
  78. plugin_http_user = abc
  79. plugin_http_passwd = 123
  80. `, remotePort)
  81. f.RunProcesses([]string{serverConf}, []string{clientConf})
  82. // http proxy, no auth info
  83. framework.NewRequestExpect(f).PortName(framework.HTTPSimpleServerPort).RequestModify(func(r *request.Request) {
  84. r.HTTP().Proxy("http://127.0.0.1:" + strconv.Itoa(remotePort))
  85. }).Ensure(framework.ExpectResponseCode(407))
  86. // http proxy, correct auth
  87. framework.NewRequestExpect(f).PortName(framework.HTTPSimpleServerPort).RequestModify(func(r *request.Request) {
  88. r.HTTP().Proxy("http://abc:123@127.0.0.1:" + strconv.Itoa(remotePort))
  89. }).Ensure()
  90. // connect TCP server by CONNECT method
  91. framework.NewRequestExpect(f).PortName(framework.TCPEchoServerPort).RequestModify(func(r *request.Request) {
  92. r.TCP().Proxy("http://abc:123@127.0.0.1:" + strconv.Itoa(remotePort))
  93. })
  94. })
  95. ginkgo.It("socks5 proxy", func() {
  96. serverConf := consts.LegacyDefaultServerConfig
  97. clientConf := consts.LegacyDefaultClientConfig
  98. remotePort := f.AllocPort()
  99. clientConf += fmt.Sprintf(`
  100. [tcp]
  101. type = tcp
  102. remote_port = %d
  103. plugin = socks5
  104. plugin_user = abc
  105. plugin_passwd = 123
  106. `, remotePort)
  107. f.RunProcesses([]string{serverConf}, []string{clientConf})
  108. // http proxy, no auth info
  109. framework.NewRequestExpect(f).PortName(framework.TCPEchoServerPort).RequestModify(func(r *request.Request) {
  110. r.TCP().Proxy("socks5://127.0.0.1:" + strconv.Itoa(remotePort))
  111. }).ExpectError(true).Ensure()
  112. // http proxy, correct auth
  113. framework.NewRequestExpect(f).PortName(framework.TCPEchoServerPort).RequestModify(func(r *request.Request) {
  114. r.TCP().Proxy("socks5://abc:123@127.0.0.1:" + strconv.Itoa(remotePort))
  115. }).Ensure()
  116. })
  117. ginkgo.It("static_file", func() {
  118. vhostPort := f.AllocPort()
  119. serverConf := consts.LegacyDefaultServerConfig + fmt.Sprintf(`
  120. vhost_http_port = %d
  121. `, vhostPort)
  122. clientConf := consts.LegacyDefaultClientConfig
  123. remotePort := f.AllocPort()
  124. f.WriteTempFile("test_static_file", "foo")
  125. clientConf += fmt.Sprintf(`
  126. [tcp]
  127. type = tcp
  128. remote_port = %d
  129. plugin = static_file
  130. plugin_local_path = %s
  131. [http]
  132. type = http
  133. custom_domains = example.com
  134. plugin = static_file
  135. plugin_local_path = %s
  136. [http-with-auth]
  137. type = http
  138. custom_domains = other.example.com
  139. plugin = static_file
  140. plugin_local_path = %s
  141. plugin_http_user = abc
  142. plugin_http_passwd = 123
  143. `, remotePort, f.TempDirectory, f.TempDirectory, f.TempDirectory)
  144. f.RunProcesses([]string{serverConf}, []string{clientConf})
  145. // from tcp proxy
  146. framework.NewRequestExpect(f).Request(
  147. framework.NewHTTPRequest().HTTPPath("/test_static_file").Port(remotePort),
  148. ).ExpectResp([]byte("foo")).Ensure()
  149. // from http proxy without auth
  150. framework.NewRequestExpect(f).Request(
  151. framework.NewHTTPRequest().HTTPHost("example.com").HTTPPath("/test_static_file").Port(vhostPort),
  152. ).ExpectResp([]byte("foo")).Ensure()
  153. // from http proxy with auth
  154. framework.NewRequestExpect(f).Request(
  155. framework.NewHTTPRequest().HTTPHost("other.example.com").HTTPPath("/test_static_file").Port(vhostPort).HTTPAuth("abc", "123"),
  156. ).ExpectResp([]byte("foo")).Ensure()
  157. })
  158. ginkgo.It("http2https", func() {
  159. serverConf := consts.LegacyDefaultServerConfig
  160. vhostHTTPPort := f.AllocPort()
  161. serverConf += fmt.Sprintf(`
  162. vhost_http_port = %d
  163. `, vhostHTTPPort)
  164. localPort := f.AllocPort()
  165. clientConf := consts.LegacyDefaultClientConfig + fmt.Sprintf(`
  166. [http2https]
  167. type = http
  168. custom_domains = example.com
  169. plugin = http2https
  170. plugin_local_addr = 127.0.0.1:%d
  171. `, localPort)
  172. f.RunProcesses([]string{serverConf}, []string{clientConf})
  173. tlsConfig, err := transport.NewServerTLSConfig("", "", "")
  174. framework.ExpectNoError(err)
  175. localServer := httpserver.New(
  176. httpserver.WithBindPort(localPort),
  177. httpserver.WithTLSConfig(tlsConfig),
  178. httpserver.WithResponse([]byte("test")),
  179. )
  180. f.RunServer("", localServer)
  181. framework.NewRequestExpect(f).
  182. Port(vhostHTTPPort).
  183. RequestModify(func(r *request.Request) {
  184. r.HTTP().HTTPHost("example.com")
  185. }).
  186. ExpectResp([]byte("test")).
  187. Ensure()
  188. })
  189. ginkgo.It("https2http", func() {
  190. generator := &cert.SelfSignedCertGenerator{}
  191. artifacts, err := generator.Generate("example.com")
  192. framework.ExpectNoError(err)
  193. crtPath := f.WriteTempFile("server.crt", string(artifacts.Cert))
  194. keyPath := f.WriteTempFile("server.key", string(artifacts.Key))
  195. serverConf := consts.LegacyDefaultServerConfig
  196. vhostHTTPSPort := f.AllocPort()
  197. serverConf += fmt.Sprintf(`
  198. vhost_https_port = %d
  199. `, vhostHTTPSPort)
  200. localPort := f.AllocPort()
  201. clientConf := consts.LegacyDefaultClientConfig + fmt.Sprintf(`
  202. [https2http]
  203. type = https
  204. custom_domains = example.com
  205. plugin = https2http
  206. plugin_local_addr = 127.0.0.1:%d
  207. plugin_crt_path = %s
  208. plugin_key_path = %s
  209. `, localPort, crtPath, keyPath)
  210. f.RunProcesses([]string{serverConf}, []string{clientConf})
  211. localServer := httpserver.New(
  212. httpserver.WithBindPort(localPort),
  213. httpserver.WithResponse([]byte("test")),
  214. )
  215. f.RunServer("", localServer)
  216. framework.NewRequestExpect(f).
  217. Port(vhostHTTPSPort).
  218. RequestModify(func(r *request.Request) {
  219. r.HTTPS().HTTPHost("example.com").TLSConfig(&tls.Config{
  220. ServerName: "example.com",
  221. InsecureSkipVerify: true,
  222. })
  223. }).
  224. ExpectResp([]byte("test")).
  225. Ensure()
  226. })
  227. ginkgo.It("https2https", func() {
  228. generator := &cert.SelfSignedCertGenerator{}
  229. artifacts, err := generator.Generate("example.com")
  230. framework.ExpectNoError(err)
  231. crtPath := f.WriteTempFile("server.crt", string(artifacts.Cert))
  232. keyPath := f.WriteTempFile("server.key", string(artifacts.Key))
  233. serverConf := consts.LegacyDefaultServerConfig
  234. vhostHTTPSPort := f.AllocPort()
  235. serverConf += fmt.Sprintf(`
  236. vhost_https_port = %d
  237. `, vhostHTTPSPort)
  238. localPort := f.AllocPort()
  239. clientConf := consts.LegacyDefaultClientConfig + fmt.Sprintf(`
  240. [https2https]
  241. type = https
  242. custom_domains = example.com
  243. plugin = https2https
  244. plugin_local_addr = 127.0.0.1:%d
  245. plugin_crt_path = %s
  246. plugin_key_path = %s
  247. `, localPort, crtPath, keyPath)
  248. f.RunProcesses([]string{serverConf}, []string{clientConf})
  249. tlsConfig, err := transport.NewServerTLSConfig("", "", "")
  250. framework.ExpectNoError(err)
  251. localServer := httpserver.New(
  252. httpserver.WithBindPort(localPort),
  253. httpserver.WithResponse([]byte("test")),
  254. httpserver.WithTLSConfig(tlsConfig),
  255. )
  256. f.RunServer("", localServer)
  257. framework.NewRequestExpect(f).
  258. Port(vhostHTTPSPort).
  259. RequestModify(func(r *request.Request) {
  260. r.HTTPS().HTTPHost("example.com").TLSConfig(&tls.Config{
  261. ServerName: "example.com",
  262. InsecureSkipVerify: true,
  263. })
  264. }).
  265. ExpectResp([]byte("test")).
  266. Ensure()
  267. })
  268. })