real_ip.go 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. package features
  2. import (
  3. "bufio"
  4. "crypto/tls"
  5. "fmt"
  6. "net"
  7. "net/http"
  8. "github.com/onsi/ginkgo/v2"
  9. pp "github.com/pires/go-proxyproto"
  10. "github.com/fatedier/frp/pkg/transport"
  11. "github.com/fatedier/frp/pkg/util/log"
  12. "github.com/fatedier/frp/test/e2e/framework"
  13. "github.com/fatedier/frp/test/e2e/framework/consts"
  14. "github.com/fatedier/frp/test/e2e/mock/server/httpserver"
  15. "github.com/fatedier/frp/test/e2e/mock/server/streamserver"
  16. "github.com/fatedier/frp/test/e2e/pkg/request"
  17. "github.com/fatedier/frp/test/e2e/pkg/rpc"
  18. )
  19. var _ = ginkgo.Describe("[Feature: Real IP]", func() {
  20. f := framework.NewDefaultFramework()
  21. ginkgo.Describe("HTTP X-forwarded-For", func() {
  22. ginkgo.It("Client Without Header", func() {
  23. vhostHTTPPort := f.AllocPort()
  24. serverConf := consts.DefaultServerConfig + fmt.Sprintf(`
  25. vhostHTTPPort = %d
  26. `, vhostHTTPPort)
  27. localPort := f.AllocPort()
  28. localServer := httpserver.New(
  29. httpserver.WithBindPort(localPort),
  30. httpserver.WithHandler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
  31. _, _ = w.Write([]byte(req.Header.Get("X-Forwarded-For")))
  32. })),
  33. )
  34. f.RunServer("", localServer)
  35. clientConf := consts.DefaultClientConfig
  36. clientConf += fmt.Sprintf(`
  37. [[proxies]]
  38. name = "test"
  39. type = "http"
  40. localPort = %d
  41. customDomains = ["normal.example.com"]
  42. `, localPort)
  43. f.RunProcesses([]string{serverConf}, []string{clientConf})
  44. framework.NewRequestExpect(f).Port(vhostHTTPPort).
  45. RequestModify(func(r *request.Request) {
  46. r.HTTP().HTTPHost("normal.example.com")
  47. }).
  48. ExpectResp([]byte("127.0.0.1")).
  49. Ensure()
  50. })
  51. ginkgo.It("Client With Header", func() {
  52. vhostHTTPPort := f.AllocPort()
  53. serverConf := consts.DefaultServerConfig + fmt.Sprintf(`
  54. vhostHTTPPort = %d
  55. `, vhostHTTPPort)
  56. localPort := f.AllocPort()
  57. localServer := httpserver.New(
  58. httpserver.WithBindPort(localPort),
  59. httpserver.WithHandler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
  60. _, _ = w.Write([]byte(req.Header.Get("X-Forwarded-For")))
  61. })),
  62. )
  63. f.RunServer("", localServer)
  64. clientConf := consts.DefaultClientConfig
  65. clientConf += fmt.Sprintf(`
  66. [[proxies]]
  67. name = "test"
  68. type = "http"
  69. localPort = %d
  70. customDomains = ["normal.example.com"]
  71. `, localPort)
  72. f.RunProcesses([]string{serverConf}, []string{clientConf})
  73. framework.NewRequestExpect(f).Port(vhostHTTPPort).
  74. RequestModify(func(r *request.Request) {
  75. r.HTTP().HTTPHost("normal.example.com")
  76. r.HTTP().HTTPHeaders(map[string]string{"x-forwarded-for": "2.2.2.2"})
  77. }).
  78. ExpectResp([]byte("2.2.2.2, 127.0.0.1")).
  79. Ensure()
  80. })
  81. ginkgo.It("http2https plugin", func() {
  82. vhostHTTPPort := f.AllocPort()
  83. serverConf := consts.DefaultServerConfig + fmt.Sprintf(`
  84. vhostHTTPPort = %d
  85. `, vhostHTTPPort)
  86. localPort := f.AllocPort()
  87. clientConf := consts.DefaultClientConfig
  88. clientConf += fmt.Sprintf(`
  89. [[proxies]]
  90. name = "test"
  91. type = "http"
  92. customDomains = ["normal.example.com"]
  93. [proxies.plugin]
  94. type = "http2https"
  95. localAddr = "127.0.0.1:%d"
  96. `, localPort)
  97. f.RunProcesses([]string{serverConf}, []string{clientConf})
  98. tlsConfig, err := transport.NewServerTLSConfig("", "", "")
  99. framework.ExpectNoError(err)
  100. localServer := httpserver.New(
  101. httpserver.WithBindPort(localPort),
  102. httpserver.WithHandler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
  103. _, _ = w.Write([]byte(req.Header.Get("X-Forwarded-For")))
  104. })),
  105. httpserver.WithTLSConfig(tlsConfig),
  106. )
  107. f.RunServer("", localServer)
  108. framework.NewRequestExpect(f).Port(vhostHTTPPort).
  109. RequestModify(func(r *request.Request) {
  110. r.HTTP().HTTPHost("normal.example.com")
  111. r.HTTP().HTTPHeaders(map[string]string{"x-forwarded-for": "2.2.2.2, 3.3.3.3"})
  112. }).
  113. ExpectResp([]byte("2.2.2.2, 3.3.3.3, 127.0.0.1")).
  114. Ensure()
  115. })
  116. ginkgo.It("https2http plugin", func() {
  117. vhostHTTPSPort := f.AllocPort()
  118. serverConf := consts.DefaultServerConfig + fmt.Sprintf(`
  119. vhostHTTPSPort = %d
  120. `, vhostHTTPSPort)
  121. localPort := f.AllocPort()
  122. clientConf := consts.DefaultClientConfig
  123. clientConf += fmt.Sprintf(`
  124. [[proxies]]
  125. name = "test"
  126. type = "https"
  127. customDomains = ["normal.example.com"]
  128. [proxies.plugin]
  129. type = "https2http"
  130. localAddr = "127.0.0.1:%d"
  131. `, localPort)
  132. f.RunProcesses([]string{serverConf}, []string{clientConf})
  133. localServer := httpserver.New(
  134. httpserver.WithBindPort(localPort),
  135. httpserver.WithHandler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
  136. _, _ = w.Write([]byte(req.Header.Get("X-Forwarded-For")))
  137. })),
  138. )
  139. f.RunServer("", localServer)
  140. framework.NewRequestExpect(f).Port(vhostHTTPSPort).
  141. RequestModify(func(r *request.Request) {
  142. r.HTTPS().HTTPHost("normal.example.com").
  143. HTTPHeaders(map[string]string{"x-forwarded-for": "2.2.2.2"}).
  144. TLSConfig(&tls.Config{ServerName: "normal.example.com", InsecureSkipVerify: true})
  145. }).
  146. ExpectResp([]byte("2.2.2.2, 127.0.0.1")).
  147. Ensure()
  148. })
  149. })
  150. ginkgo.Describe("Proxy Protocol", func() {
  151. ginkgo.It("TCP", func() {
  152. serverConf := consts.DefaultServerConfig
  153. clientConf := consts.DefaultClientConfig
  154. localPort := f.AllocPort()
  155. localServer := streamserver.New(streamserver.TCP, streamserver.WithBindPort(localPort),
  156. streamserver.WithCustomHandler(func(c net.Conn) {
  157. defer c.Close()
  158. rd := bufio.NewReader(c)
  159. ppHeader, err := pp.Read(rd)
  160. if err != nil {
  161. log.Errorf("read proxy protocol error: %v", err)
  162. return
  163. }
  164. for {
  165. if _, err := rpc.ReadBytes(rd); err != nil {
  166. return
  167. }
  168. buf := []byte(ppHeader.SourceAddr.String())
  169. _, _ = rpc.WriteBytes(c, buf)
  170. }
  171. }))
  172. f.RunServer("", localServer)
  173. remotePort := f.AllocPort()
  174. clientConf += fmt.Sprintf(`
  175. [[proxies]]
  176. name = "tcp"
  177. type = "tcp"
  178. localPort = %d
  179. remotePort = %d
  180. transport.proxyProtocolVersion = "v2"
  181. `, localPort, remotePort)
  182. f.RunProcesses([]string{serverConf}, []string{clientConf})
  183. framework.NewRequestExpect(f).Port(remotePort).Ensure(func(resp *request.Response) bool {
  184. log.Tracef("ProxyProtocol get SourceAddr: %s", string(resp.Content))
  185. addr, err := net.ResolveTCPAddr("tcp", string(resp.Content))
  186. if err != nil {
  187. return false
  188. }
  189. if addr.IP.String() != "127.0.0.1" {
  190. return false
  191. }
  192. return true
  193. })
  194. })
  195. ginkgo.It("HTTP", func() {
  196. vhostHTTPPort := f.AllocPort()
  197. serverConf := consts.DefaultServerConfig + fmt.Sprintf(`
  198. vhostHTTPPort = %d
  199. `, vhostHTTPPort)
  200. clientConf := consts.DefaultClientConfig
  201. localPort := f.AllocPort()
  202. var srcAddrRecord string
  203. localServer := streamserver.New(streamserver.TCP, streamserver.WithBindPort(localPort),
  204. streamserver.WithCustomHandler(func(c net.Conn) {
  205. defer c.Close()
  206. rd := bufio.NewReader(c)
  207. ppHeader, err := pp.Read(rd)
  208. if err != nil {
  209. log.Errorf("read proxy protocol error: %v", err)
  210. return
  211. }
  212. srcAddrRecord = ppHeader.SourceAddr.String()
  213. }))
  214. f.RunServer("", localServer)
  215. clientConf += fmt.Sprintf(`
  216. [[proxies]]
  217. name = "test"
  218. type = "http"
  219. localPort = %d
  220. customDomains = ["normal.example.com"]
  221. transport.proxyProtocolVersion = "v2"
  222. `, localPort)
  223. f.RunProcesses([]string{serverConf}, []string{clientConf})
  224. framework.NewRequestExpect(f).Port(vhostHTTPPort).RequestModify(func(r *request.Request) {
  225. r.HTTP().HTTPHost("normal.example.com")
  226. }).Ensure(framework.ExpectResponseCode(404))
  227. log.Tracef("ProxyProtocol get SourceAddr: %s", srcAddrRecord)
  228. addr, err := net.ResolveTCPAddr("tcp", srcAddrRecord)
  229. framework.ExpectNoError(err, srcAddrRecord)
  230. framework.ExpectEqualValues("127.0.0.1", addr.IP.String())
  231. })
  232. })
  233. })