basic.go 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. package basic
  2. import (
  3. "fmt"
  4. "strings"
  5. "github.com/fatedier/frp/test/e2e/framework"
  6. "github.com/fatedier/frp/test/e2e/framework/consts"
  7. "github.com/fatedier/frp/test/e2e/mock/server/streamserver"
  8. "github.com/fatedier/frp/test/e2e/pkg/port"
  9. "github.com/fatedier/frp/test/e2e/pkg/request"
  10. . "github.com/onsi/ginkgo"
  11. )
  12. var _ = Describe("[Feature: Basic]", func() {
  13. f := framework.NewDefaultFramework()
  14. Describe("TCP && UDP", func() {
  15. types := []string{"tcp", "udp"}
  16. for _, t := range types {
  17. proxyType := t
  18. It(fmt.Sprintf("Expose a %s echo server", strings.ToUpper(proxyType)), func() {
  19. serverConf := consts.DefaultServerConfig
  20. clientConf := consts.DefaultClientConfig
  21. localPortName := ""
  22. protocol := "tcp"
  23. switch proxyType {
  24. case "tcp":
  25. localPortName = framework.TCPEchoServerPort
  26. protocol = "tcp"
  27. case "udp":
  28. localPortName = framework.UDPEchoServerPort
  29. protocol = "udp"
  30. }
  31. getProxyConf := func(proxyName string, portName string, extra string) string {
  32. return fmt.Sprintf(`
  33. [%s]
  34. type = %s
  35. local_port = {{ .%s }}
  36. remote_port = {{ .%s }}
  37. `+extra, proxyName, proxyType, localPortName, portName)
  38. }
  39. tests := []struct {
  40. proxyName string
  41. portName string
  42. extraConfig string
  43. }{
  44. {
  45. proxyName: "normal",
  46. portName: port.GenName("Normal"),
  47. },
  48. {
  49. proxyName: "with-encryption",
  50. portName: port.GenName("WithEncryption"),
  51. extraConfig: "use_encryption = true",
  52. },
  53. {
  54. proxyName: "with-compression",
  55. portName: port.GenName("WithCompression"),
  56. extraConfig: "use_compression = true",
  57. },
  58. {
  59. proxyName: "with-encryption-and-compression",
  60. portName: port.GenName("WithEncryptionAndCompression"),
  61. extraConfig: `
  62. use_encryption = true
  63. use_compression = true
  64. `,
  65. },
  66. }
  67. // build all client config
  68. for _, test := range tests {
  69. clientConf += getProxyConf(test.proxyName, test.portName, test.extraConfig) + "\n"
  70. }
  71. // run frps and frpc
  72. f.RunProcesses([]string{serverConf}, []string{clientConf})
  73. for _, test := range tests {
  74. framework.NewRequestExpect(f).
  75. Protocol(protocol).
  76. PortName(test.portName).
  77. Explain(test.proxyName).
  78. Ensure()
  79. }
  80. })
  81. }
  82. })
  83. Describe("HTTP", func() {
  84. It("proxy to HTTP server", func() {
  85. serverConf := consts.DefaultServerConfig
  86. vhostHTTPPort := f.AllocPort()
  87. serverConf += fmt.Sprintf(`
  88. vhost_http_port = %d
  89. `, vhostHTTPPort)
  90. clientConf := consts.DefaultClientConfig
  91. getProxyConf := func(proxyName string, customDomains string, extra string) string {
  92. return fmt.Sprintf(`
  93. [%s]
  94. type = http
  95. local_port = {{ .%s }}
  96. custom_domains = %s
  97. `+extra, proxyName, framework.HTTPSimpleServerPort, customDomains)
  98. }
  99. tests := []struct {
  100. proxyName string
  101. customDomains string
  102. extraConfig string
  103. }{
  104. {
  105. proxyName: "normal",
  106. },
  107. {
  108. proxyName: "with-encryption",
  109. extraConfig: "use_encryption = true",
  110. },
  111. {
  112. proxyName: "with-compression",
  113. extraConfig: "use_compression = true",
  114. },
  115. {
  116. proxyName: "with-encryption-and-compression",
  117. extraConfig: `
  118. use_encryption = true
  119. use_compression = true
  120. `,
  121. },
  122. {
  123. proxyName: "multiple-custom-domains",
  124. customDomains: "a.example.com, b.example.com",
  125. },
  126. }
  127. // build all client config
  128. for i, test := range tests {
  129. if tests[i].customDomains == "" {
  130. tests[i].customDomains = test.proxyName + ".example.com"
  131. }
  132. clientConf += getProxyConf(test.proxyName, tests[i].customDomains, test.extraConfig) + "\n"
  133. }
  134. // run frps and frpc
  135. f.RunProcesses([]string{serverConf}, []string{clientConf})
  136. for _, test := range tests {
  137. for _, domain := range strings.Split(test.customDomains, ",") {
  138. domain = strings.TrimSpace(domain)
  139. framework.NewRequestExpect(f).
  140. Explain(test.proxyName + "-" + domain).
  141. Port(vhostHTTPPort).
  142. RequestModify(func(r *request.Request) {
  143. r.HTTP().HTTPHost(domain)
  144. }).
  145. Ensure()
  146. }
  147. }
  148. // not exist host
  149. framework.NewRequestExpect(f).
  150. Explain("not exist host").
  151. Port(vhostHTTPPort).
  152. RequestModify(func(r *request.Request) {
  153. r.HTTP().HTTPHost("not-exist.example.com")
  154. }).
  155. Ensure(framework.ExpectResponseCode(404))
  156. })
  157. })
  158. Describe("STCP && SUDP", func() {
  159. types := []string{"stcp", "sudp"}
  160. for _, t := range types {
  161. proxyType := t
  162. It(fmt.Sprintf("Expose echo server with %s", strings.ToUpper(proxyType)), func() {
  163. serverConf := consts.DefaultServerConfig
  164. clientServerConf := consts.DefaultClientConfig
  165. clientVisitorConf := consts.DefaultClientConfig
  166. localPortName := ""
  167. protocol := "tcp"
  168. switch proxyType {
  169. case "stcp":
  170. localPortName = framework.TCPEchoServerPort
  171. protocol = "tcp"
  172. case "sudp":
  173. localPortName = framework.UDPEchoServerPort
  174. protocol = "udp"
  175. }
  176. correctSK := "abc"
  177. wrongSK := "123"
  178. getProxyServerConf := func(proxyName string, extra string) string {
  179. return fmt.Sprintf(`
  180. [%s]
  181. type = %s
  182. role = server
  183. sk = %s
  184. local_port = {{ .%s }}
  185. `+extra, proxyName, proxyType, correctSK, localPortName)
  186. }
  187. getProxyVisitorConf := func(proxyName string, portName, visitorSK, extra string) string {
  188. return fmt.Sprintf(`
  189. [%s]
  190. type = %s
  191. role = visitor
  192. server_name = %s
  193. sk = %s
  194. bind_port = {{ .%s }}
  195. `+extra, proxyName, proxyType, proxyName, visitorSK, portName)
  196. }
  197. tests := []struct {
  198. proxyName string
  199. bindPortName string
  200. visitorSK string
  201. extraConfig string
  202. expectError bool
  203. }{
  204. {
  205. proxyName: "normal",
  206. bindPortName: port.GenName("Normal"),
  207. visitorSK: correctSK,
  208. },
  209. {
  210. proxyName: "with-encryption",
  211. bindPortName: port.GenName("WithEncryption"),
  212. visitorSK: correctSK,
  213. extraConfig: "use_encryption = true",
  214. },
  215. {
  216. proxyName: "with-compression",
  217. bindPortName: port.GenName("WithCompression"),
  218. visitorSK: correctSK,
  219. extraConfig: "use_compression = true",
  220. },
  221. {
  222. proxyName: "with-encryption-and-compression",
  223. bindPortName: port.GenName("WithEncryptionAndCompression"),
  224. visitorSK: correctSK,
  225. extraConfig: `
  226. use_encryption = true
  227. use_compression = true
  228. `,
  229. },
  230. {
  231. proxyName: "with-error-sk",
  232. bindPortName: port.GenName("WithErrorSK"),
  233. visitorSK: wrongSK,
  234. expectError: true,
  235. },
  236. }
  237. // build all client config
  238. for _, test := range tests {
  239. clientServerConf += getProxyServerConf(test.proxyName, test.extraConfig) + "\n"
  240. }
  241. for _, test := range tests {
  242. clientVisitorConf += getProxyVisitorConf(test.proxyName, test.bindPortName, test.visitorSK, test.extraConfig) + "\n"
  243. }
  244. // run frps and frpc
  245. f.RunProcesses([]string{serverConf}, []string{clientServerConf, clientVisitorConf})
  246. for _, test := range tests {
  247. framework.NewRequestExpect(f).
  248. Protocol(protocol).
  249. PortName(test.bindPortName).
  250. Explain(test.proxyName).
  251. ExpectError(test.expectError).
  252. Ensure()
  253. }
  254. })
  255. }
  256. })
  257. Describe("TCPMUX", func() {
  258. It("Type tcpmux", func() {
  259. serverConf := consts.DefaultServerConfig
  260. clientConf := consts.DefaultClientConfig
  261. tcpmuxHTTPConnectPortName := port.GenName("TCPMUX")
  262. serverConf += fmt.Sprintf(`
  263. tcpmux_httpconnect_port = {{ .%s }}
  264. `, tcpmuxHTTPConnectPortName)
  265. getProxyConf := func(proxyName string, extra string) string {
  266. return fmt.Sprintf(`
  267. [%s]
  268. type = tcpmux
  269. multiplexer = httpconnect
  270. local_port = {{ .%s }}
  271. custom_domains = %s
  272. `+extra, proxyName, port.GenName(proxyName), proxyName)
  273. }
  274. tests := []struct {
  275. proxyName string
  276. extraConfig string
  277. }{
  278. {
  279. proxyName: "normal",
  280. },
  281. {
  282. proxyName: "with-encryption",
  283. extraConfig: "use_encryption = true",
  284. },
  285. {
  286. proxyName: "with-compression",
  287. extraConfig: "use_compression = true",
  288. },
  289. {
  290. proxyName: "with-encryption-and-compression",
  291. extraConfig: `
  292. use_encryption = true
  293. use_compression = true
  294. `,
  295. },
  296. }
  297. // build all client config
  298. for _, test := range tests {
  299. clientConf += getProxyConf(test.proxyName, test.extraConfig) + "\n"
  300. localServer := streamserver.New(streamserver.TCP, streamserver.WithBindPort(f.AllocPort()), streamserver.WithRespContent([]byte(test.proxyName)))
  301. f.RunServer(port.GenName(test.proxyName), localServer)
  302. }
  303. // run frps and frpc
  304. f.RunProcesses([]string{serverConf}, []string{clientConf})
  305. // Request without HTTP connect should get error
  306. framework.NewRequestExpect(f).
  307. PortName(tcpmuxHTTPConnectPortName).
  308. ExpectError(true).
  309. Explain("request without HTTP connect expect error").
  310. Ensure()
  311. proxyURL := fmt.Sprintf("http://127.0.0.1:%d", f.PortByName(tcpmuxHTTPConnectPortName))
  312. // Request with incorrect connect hostname
  313. framework.NewRequestExpect(f).RequestModify(func(r *request.Request) {
  314. r.Addr("invalid").Proxy(proxyURL)
  315. }).ExpectError(true).Explain("request without HTTP connect expect error").Ensure()
  316. // Request with correct connect hostname
  317. for _, test := range tests {
  318. framework.NewRequestExpect(f).RequestModify(func(r *request.Request) {
  319. r.Addr(test.proxyName).Proxy(proxyURL)
  320. }).ExpectResp([]byte(test.proxyName)).Explain(test.proxyName).Ensure()
  321. }
  322. })
  323. })
  324. })