client_server.go 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. package basic
  2. import (
  3. "fmt"
  4. "strings"
  5. "github.com/onsi/ginkgo/v2"
  6. "github.com/fatedier/frp/test/e2e/framework"
  7. "github.com/fatedier/frp/test/e2e/framework/consts"
  8. "github.com/fatedier/frp/test/e2e/pkg/cert"
  9. "github.com/fatedier/frp/test/e2e/pkg/port"
  10. )
  11. type generalTestConfigures struct {
  12. server string
  13. client string
  14. expectError bool
  15. }
  16. func renderBindPortConfig(protocol string) string {
  17. if protocol == "kcp" {
  18. return fmt.Sprintf(`kcp_bind_port = {{ .%s }}`, consts.PortServerName)
  19. } else if protocol == "quic" {
  20. return fmt.Sprintf(`quic_bind_port = {{ .%s }}`, consts.PortServerName)
  21. }
  22. return ""
  23. }
  24. func runClientServerTest(f *framework.Framework, configures *generalTestConfigures) {
  25. serverConf := consts.DefaultServerConfig
  26. clientConf := consts.DefaultClientConfig
  27. serverConf += fmt.Sprintf(`
  28. %s
  29. `, configures.server)
  30. tcpPortName := port.GenName("TCP")
  31. udpPortName := port.GenName("UDP")
  32. clientConf += fmt.Sprintf(`
  33. %s
  34. [tcp]
  35. type = tcp
  36. local_port = {{ .%s }}
  37. remote_port = {{ .%s }}
  38. [udp]
  39. type = udp
  40. local_port = {{ .%s }}
  41. remote_port = {{ .%s }}
  42. `, configures.client,
  43. framework.TCPEchoServerPort, tcpPortName,
  44. framework.UDPEchoServerPort, udpPortName,
  45. )
  46. f.RunProcesses([]string{serverConf}, []string{clientConf})
  47. framework.NewRequestExpect(f).PortName(tcpPortName).ExpectError(configures.expectError).Explain("tcp proxy").Ensure()
  48. framework.NewRequestExpect(f).Protocol("udp").
  49. PortName(udpPortName).ExpectError(configures.expectError).Explain("udp proxy").Ensure()
  50. }
  51. // defineClientServerTest test a normal tcp and udp proxy with specified TestConfigures.
  52. func defineClientServerTest(desc string, f *framework.Framework, configures *generalTestConfigures) {
  53. ginkgo.It(desc, func() {
  54. runClientServerTest(f, configures)
  55. })
  56. }
  57. var _ = ginkgo.Describe("[Feature: Client-Server]", func() {
  58. f := framework.NewDefaultFramework()
  59. ginkgo.Describe("Protocol", func() {
  60. supportProtocols := []string{"tcp", "kcp", "quic", "websocket"}
  61. for _, protocol := range supportProtocols {
  62. configures := &generalTestConfigures{
  63. server: fmt.Sprintf(`
  64. %s
  65. `, renderBindPortConfig(protocol)),
  66. client: "protocol = " + protocol,
  67. }
  68. defineClientServerTest(protocol, f, configures)
  69. }
  70. })
  71. ginkgo.Describe("Authentication", func() {
  72. defineClientServerTest("Token Correct", f, &generalTestConfigures{
  73. server: "token = 123456",
  74. client: "token = 123456",
  75. })
  76. defineClientServerTest("Token Incorrect", f, &generalTestConfigures{
  77. server: "token = 123456",
  78. client: "token = invalid",
  79. expectError: true,
  80. })
  81. })
  82. ginkgo.Describe("TLS", func() {
  83. supportProtocols := []string{"tcp", "kcp", "quic", "websocket"}
  84. for _, protocol := range supportProtocols {
  85. tmp := protocol
  86. // Since v0.50.0, the default value of tls_enable has been changed to true.
  87. // Therefore, here it needs to be set as false to test the scenario of turning it off.
  88. defineClientServerTest("Disable TLS over "+strings.ToUpper(tmp), f, &generalTestConfigures{
  89. server: fmt.Sprintf(`
  90. %s
  91. `, renderBindPortConfig(protocol)),
  92. client: fmt.Sprintf(`tls_enable = false
  93. protocol = %s
  94. `, protocol),
  95. })
  96. }
  97. defineClientServerTest("enable tls_only, client with TLS", f, &generalTestConfigures{
  98. server: "tls_only = true",
  99. })
  100. defineClientServerTest("enable tls_only, client without TLS", f, &generalTestConfigures{
  101. server: "tls_only = true",
  102. client: "tls_enable = false",
  103. expectError: true,
  104. })
  105. })
  106. ginkgo.Describe("TLS with custom certificate", func() {
  107. supportProtocols := []string{"tcp", "kcp", "quic", "websocket"}
  108. var (
  109. caCrtPath string
  110. serverCrtPath, serverKeyPath string
  111. clientCrtPath, clientKeyPath string
  112. )
  113. ginkgo.JustBeforeEach(func() {
  114. generator := &cert.SelfSignedCertGenerator{}
  115. artifacts, err := generator.Generate("127.0.0.1")
  116. framework.ExpectNoError(err)
  117. caCrtPath = f.WriteTempFile("ca.crt", string(artifacts.CACert))
  118. serverCrtPath = f.WriteTempFile("server.crt", string(artifacts.Cert))
  119. serverKeyPath = f.WriteTempFile("server.key", string(artifacts.Key))
  120. generator.SetCA(artifacts.CACert, artifacts.CAKey)
  121. _, err = generator.Generate("127.0.0.1")
  122. framework.ExpectNoError(err)
  123. clientCrtPath = f.WriteTempFile("client.crt", string(artifacts.Cert))
  124. clientKeyPath = f.WriteTempFile("client.key", string(artifacts.Key))
  125. })
  126. for _, protocol := range supportProtocols {
  127. tmp := protocol
  128. ginkgo.It("one-way authentication: "+tmp, func() {
  129. runClientServerTest(f, &generalTestConfigures{
  130. server: fmt.Sprintf(`
  131. %s
  132. tls_trusted_ca_file = %s
  133. `, renderBindPortConfig(tmp), caCrtPath),
  134. client: fmt.Sprintf(`
  135. protocol = %s
  136. tls_cert_file = %s
  137. tls_key_file = %s
  138. `, tmp, clientCrtPath, clientKeyPath),
  139. })
  140. })
  141. ginkgo.It("mutual authentication: "+tmp, func() {
  142. runClientServerTest(f, &generalTestConfigures{
  143. server: fmt.Sprintf(`
  144. %s
  145. tls_cert_file = %s
  146. tls_key_file = %s
  147. tls_trusted_ca_file = %s
  148. `, renderBindPortConfig(tmp), serverCrtPath, serverKeyPath, caCrtPath),
  149. client: fmt.Sprintf(`
  150. protocol = %s
  151. tls_cert_file = %s
  152. tls_key_file = %s
  153. tls_trusted_ca_file = %s
  154. `, tmp, clientCrtPath, clientKeyPath, caCrtPath),
  155. })
  156. })
  157. }
  158. })
  159. ginkgo.Describe("TLS with custom certificate and specified server name", func() {
  160. var (
  161. caCrtPath string
  162. serverCrtPath, serverKeyPath string
  163. clientCrtPath, clientKeyPath string
  164. )
  165. ginkgo.JustBeforeEach(func() {
  166. generator := &cert.SelfSignedCertGenerator{}
  167. artifacts, err := generator.Generate("example.com")
  168. framework.ExpectNoError(err)
  169. caCrtPath = f.WriteTempFile("ca.crt", string(artifacts.CACert))
  170. serverCrtPath = f.WriteTempFile("server.crt", string(artifacts.Cert))
  171. serverKeyPath = f.WriteTempFile("server.key", string(artifacts.Key))
  172. generator.SetCA(artifacts.CACert, artifacts.CAKey)
  173. _, err = generator.Generate("example.com")
  174. framework.ExpectNoError(err)
  175. clientCrtPath = f.WriteTempFile("client.crt", string(artifacts.Cert))
  176. clientKeyPath = f.WriteTempFile("client.key", string(artifacts.Key))
  177. })
  178. ginkgo.It("mutual authentication", func() {
  179. runClientServerTest(f, &generalTestConfigures{
  180. server: fmt.Sprintf(`
  181. tls_cert_file = %s
  182. tls_key_file = %s
  183. tls_trusted_ca_file = %s
  184. `, serverCrtPath, serverKeyPath, caCrtPath),
  185. client: fmt.Sprintf(`
  186. tls_server_name = example.com
  187. tls_cert_file = %s
  188. tls_key_file = %s
  189. tls_trusted_ca_file = %s
  190. `, clientCrtPath, clientKeyPath, caCrtPath),
  191. })
  192. })
  193. ginkgo.It("mutual authentication with incorrect server name", func() {
  194. runClientServerTest(f, &generalTestConfigures{
  195. server: fmt.Sprintf(`
  196. tls_cert_file = %s
  197. tls_key_file = %s
  198. tls_trusted_ca_file = %s
  199. `, serverCrtPath, serverKeyPath, caCrtPath),
  200. client: fmt.Sprintf(`
  201. tls_server_name = invalid.com
  202. tls_cert_file = %s
  203. tls_key_file = %s
  204. tls_trusted_ca_file = %s
  205. `, clientCrtPath, clientKeyPath, caCrtPath),
  206. expectError: true,
  207. })
  208. })
  209. })
  210. ginkgo.Describe("TLS with disable_custom_tls_first_byte set to false", func() {
  211. supportProtocols := []string{"tcp", "kcp", "quic", "websocket"}
  212. for _, protocol := range supportProtocols {
  213. tmp := protocol
  214. defineClientServerTest("TLS over "+strings.ToUpper(tmp), f, &generalTestConfigures{
  215. server: fmt.Sprintf(`
  216. %s
  217. `, renderBindPortConfig(protocol)),
  218. client: fmt.Sprintf(`
  219. protocol = %s
  220. disable_custom_tls_first_byte = false
  221. `, protocol),
  222. })
  223. }
  224. })
  225. ginkgo.Describe("IPv6 bind address", func() {
  226. supportProtocols := []string{"tcp", "kcp", "quic", "websocket"}
  227. for _, protocol := range supportProtocols {
  228. tmp := protocol
  229. defineClientServerTest("IPv6 bind address: "+strings.ToUpper(tmp), f, &generalTestConfigures{
  230. server: fmt.Sprintf(`
  231. bind_addr = ::
  232. %s
  233. `, renderBindPortConfig(protocol)),
  234. client: fmt.Sprintf(`
  235. protocol = %s
  236. `, protocol),
  237. })
  238. }
  239. })
  240. })