tcpmux.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. package basic
  2. import (
  3. "bufio"
  4. "fmt"
  5. "net"
  6. "net/http"
  7. "github.com/onsi/ginkgo/v2"
  8. httppkg "github.com/fatedier/frp/pkg/util/http"
  9. "github.com/fatedier/frp/test/e2e/framework"
  10. "github.com/fatedier/frp/test/e2e/framework/consts"
  11. "github.com/fatedier/frp/test/e2e/mock/server/streamserver"
  12. "github.com/fatedier/frp/test/e2e/pkg/request"
  13. "github.com/fatedier/frp/test/e2e/pkg/rpc"
  14. )
  15. var _ = ginkgo.Describe("[Feature: TCPMUX httpconnect]", func() {
  16. f := framework.NewDefaultFramework()
  17. getDefaultServerConf := func(httpconnectPort int) string {
  18. conf := consts.DefaultServerConfig + `
  19. tcpmuxHTTPConnectPort = %d
  20. `
  21. return fmt.Sprintf(conf, httpconnectPort)
  22. }
  23. newServer := func(port int, respContent string) *streamserver.Server {
  24. return streamserver.New(
  25. streamserver.TCP,
  26. streamserver.WithBindPort(port),
  27. streamserver.WithRespContent([]byte(respContent)),
  28. )
  29. }
  30. proxyURLWithAuth := func(username, password string, port int) string {
  31. if username == "" {
  32. return fmt.Sprintf("http://127.0.0.1:%d", port)
  33. }
  34. return fmt.Sprintf("http://%s:%s@127.0.0.1:%d", username, password, port)
  35. }
  36. ginkgo.It("Route by HTTP user", func() {
  37. vhostPort := f.AllocPort()
  38. serverConf := getDefaultServerConf(vhostPort)
  39. fooPort := f.AllocPort()
  40. f.RunServer("", newServer(fooPort, "foo"))
  41. barPort := f.AllocPort()
  42. f.RunServer("", newServer(barPort, "bar"))
  43. otherPort := f.AllocPort()
  44. f.RunServer("", newServer(otherPort, "other"))
  45. clientConf := consts.DefaultClientConfig
  46. clientConf += fmt.Sprintf(`
  47. [[proxies]]
  48. name = "foo"
  49. type = "tcpmux"
  50. multiplexer = "httpconnect"
  51. localPort = %d
  52. customDomains = ["normal.example.com"]
  53. routeByHTTPUser = "user1"
  54. [[proxies]]
  55. name = "bar"
  56. type = "tcpmux"
  57. multiplexer = "httpconnect"
  58. localPort = %d
  59. customDomains = ["normal.example.com"]
  60. routeByHTTPUser = "user2"
  61. [[proxies]]
  62. name = "catchAll"
  63. type = "tcpmux"
  64. multiplexer = "httpconnect"
  65. localPort = %d
  66. customDomains = ["normal.example.com"]
  67. `, fooPort, barPort, otherPort)
  68. f.RunProcesses([]string{serverConf}, []string{clientConf})
  69. // user1
  70. framework.NewRequestExpect(f).Explain("user1").
  71. RequestModify(func(r *request.Request) {
  72. r.Addr("normal.example.com").Proxy(proxyURLWithAuth("user1", "", vhostPort))
  73. }).
  74. ExpectResp([]byte("foo")).
  75. Ensure()
  76. // user2
  77. framework.NewRequestExpect(f).Explain("user2").
  78. RequestModify(func(r *request.Request) {
  79. r.Addr("normal.example.com").Proxy(proxyURLWithAuth("user2", "", vhostPort))
  80. }).
  81. ExpectResp([]byte("bar")).
  82. Ensure()
  83. // other user
  84. framework.NewRequestExpect(f).Explain("other user").
  85. RequestModify(func(r *request.Request) {
  86. r.Addr("normal.example.com").Proxy(proxyURLWithAuth("user3", "", vhostPort))
  87. }).
  88. ExpectResp([]byte("other")).
  89. Ensure()
  90. })
  91. ginkgo.It("Proxy auth", func() {
  92. vhostPort := f.AllocPort()
  93. serverConf := getDefaultServerConf(vhostPort)
  94. fooPort := f.AllocPort()
  95. f.RunServer("", newServer(fooPort, "foo"))
  96. clientConf := consts.DefaultClientConfig
  97. clientConf += fmt.Sprintf(`
  98. [[proxies]]
  99. name = "test"
  100. type = "tcpmux"
  101. multiplexer = "httpconnect"
  102. localPort = %d
  103. customDomains = ["normal.example.com"]
  104. httpUser = "test"
  105. httpPassword = "test"
  106. `, fooPort)
  107. f.RunProcesses([]string{serverConf}, []string{clientConf})
  108. // not set auth header
  109. framework.NewRequestExpect(f).Explain("no auth").
  110. RequestModify(func(r *request.Request) {
  111. r.Addr("normal.example.com").Proxy(proxyURLWithAuth("", "", vhostPort))
  112. }).
  113. ExpectError(true).
  114. Ensure()
  115. // set incorrect auth header
  116. framework.NewRequestExpect(f).Explain("incorrect auth").
  117. RequestModify(func(r *request.Request) {
  118. r.Addr("normal.example.com").Proxy(proxyURLWithAuth("test", "invalid", vhostPort))
  119. }).
  120. ExpectError(true).
  121. Ensure()
  122. // set correct auth header
  123. framework.NewRequestExpect(f).Explain("correct auth").
  124. RequestModify(func(r *request.Request) {
  125. r.Addr("normal.example.com").Proxy(proxyURLWithAuth("test", "test", vhostPort))
  126. }).
  127. ExpectResp([]byte("foo")).
  128. Ensure()
  129. })
  130. ginkgo.It("TCPMux Passthrough", func() {
  131. vhostPort := f.AllocPort()
  132. serverConf := getDefaultServerConf(vhostPort)
  133. serverConf += `
  134. tcpmuxPassthrough = true
  135. `
  136. var (
  137. respErr error
  138. connectRequestHost string
  139. )
  140. newServer := func(port int) *streamserver.Server {
  141. return streamserver.New(
  142. streamserver.TCP,
  143. streamserver.WithBindPort(port),
  144. streamserver.WithCustomHandler(func(conn net.Conn) {
  145. defer conn.Close()
  146. // read HTTP CONNECT request
  147. bufioReader := bufio.NewReader(conn)
  148. req, err := http.ReadRequest(bufioReader)
  149. if err != nil {
  150. respErr = err
  151. return
  152. }
  153. connectRequestHost = req.Host
  154. // return ok response
  155. res := httppkg.OkResponse()
  156. if res.Body != nil {
  157. defer res.Body.Close()
  158. }
  159. _ = res.Write(conn)
  160. buf, err := rpc.ReadBytes(conn)
  161. if err != nil {
  162. respErr = err
  163. return
  164. }
  165. _, _ = rpc.WriteBytes(conn, buf)
  166. }),
  167. )
  168. }
  169. localPort := f.AllocPort()
  170. f.RunServer("", newServer(localPort))
  171. clientConf := consts.DefaultClientConfig
  172. clientConf += fmt.Sprintf(`
  173. [[proxies]]
  174. name = "test"
  175. type = "tcpmux"
  176. multiplexer = "httpconnect"
  177. localPort = %d
  178. customDomains = ["normal.example.com"]
  179. `, localPort)
  180. f.RunProcesses([]string{serverConf}, []string{clientConf})
  181. framework.NewRequestExpect(f).
  182. RequestModify(func(r *request.Request) {
  183. r.Addr("normal.example.com").Proxy(proxyURLWithAuth("", "", vhostPort)).Body([]byte("frp"))
  184. }).
  185. ExpectResp([]byte("frp")).
  186. Ensure()
  187. framework.ExpectNoError(respErr)
  188. framework.ExpectEqualValues(connectRequestHost, "normal.example.com")
  189. })
  190. })