server.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. package plugin
  2. import (
  3. "fmt"
  4. "time"
  5. "github.com/onsi/ginkgo/v2"
  6. plugin "github.com/fatedier/frp/pkg/plugin/server"
  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. pluginpkg "github.com/fatedier/frp/test/e2e/pkg/plugin"
  11. )
  12. var _ = ginkgo.Describe("[Feature: Server-Plugins]", func() {
  13. f := framework.NewDefaultFramework()
  14. ginkgo.Describe("Login", func() {
  15. newFunc := func() *plugin.Request {
  16. var r plugin.Request
  17. r.Content = &plugin.LoginContent{}
  18. return &r
  19. }
  20. ginkgo.It("Auth for custom meta token", func() {
  21. localPort := f.AllocPort()
  22. clientAddressGot := false
  23. handler := func(req *plugin.Request) *plugin.Response {
  24. var ret plugin.Response
  25. content := req.Content.(*plugin.LoginContent)
  26. if content.ClientAddress != "" {
  27. clientAddressGot = true
  28. }
  29. if content.Metas["token"] == "123" {
  30. ret.Unchange = true
  31. } else {
  32. ret.Reject = true
  33. ret.RejectReason = "invalid token"
  34. }
  35. return &ret
  36. }
  37. pluginServer := pluginpkg.NewHTTPPluginServer(localPort, newFunc, handler, nil)
  38. f.RunServer("", pluginServer)
  39. serverConf := consts.LegacyDefaultServerConfig + fmt.Sprintf(`
  40. [plugin.user-manager]
  41. addr = 127.0.0.1:%d
  42. path = /handler
  43. ops = Login
  44. `, localPort)
  45. clientConf := consts.LegacyDefaultClientConfig
  46. remotePort := f.AllocPort()
  47. clientConf += fmt.Sprintf(`
  48. meta_token = 123
  49. [tcp]
  50. type = tcp
  51. local_port = {{ .%s }}
  52. remote_port = %d
  53. `, framework.TCPEchoServerPort, remotePort)
  54. remotePort2 := f.AllocPort()
  55. invalidTokenClientConf := consts.LegacyDefaultClientConfig + fmt.Sprintf(`
  56. [tcp2]
  57. type = tcp
  58. local_port = {{ .%s }}
  59. remote_port = %d
  60. `, framework.TCPEchoServerPort, remotePort2)
  61. f.RunProcesses([]string{serverConf}, []string{clientConf, invalidTokenClientConf})
  62. framework.NewRequestExpect(f).Port(remotePort).Ensure()
  63. framework.NewRequestExpect(f).Port(remotePort2).ExpectError(true).Ensure()
  64. framework.ExpectTrue(clientAddressGot)
  65. })
  66. })
  67. ginkgo.Describe("NewProxy", func() {
  68. newFunc := func() *plugin.Request {
  69. var r plugin.Request
  70. r.Content = &plugin.NewProxyContent{}
  71. return &r
  72. }
  73. ginkgo.It("Validate Info", func() {
  74. localPort := f.AllocPort()
  75. handler := func(req *plugin.Request) *plugin.Response {
  76. var ret plugin.Response
  77. content := req.Content.(*plugin.NewProxyContent)
  78. if content.ProxyName == "tcp" {
  79. ret.Unchange = true
  80. } else {
  81. ret.Reject = true
  82. }
  83. return &ret
  84. }
  85. pluginServer := pluginpkg.NewHTTPPluginServer(localPort, newFunc, handler, nil)
  86. f.RunServer("", pluginServer)
  87. serverConf := consts.LegacyDefaultServerConfig + fmt.Sprintf(`
  88. [plugin.test]
  89. addr = 127.0.0.1:%d
  90. path = /handler
  91. ops = NewProxy
  92. `, localPort)
  93. clientConf := consts.LegacyDefaultClientConfig
  94. remotePort := f.AllocPort()
  95. clientConf += fmt.Sprintf(`
  96. [tcp]
  97. type = tcp
  98. local_port = {{ .%s }}
  99. remote_port = %d
  100. `, framework.TCPEchoServerPort, remotePort)
  101. f.RunProcesses([]string{serverConf}, []string{clientConf})
  102. framework.NewRequestExpect(f).Port(remotePort).Ensure()
  103. })
  104. ginkgo.It("Modify RemotePort", func() {
  105. localPort := f.AllocPort()
  106. remotePort := f.AllocPort()
  107. handler := func(req *plugin.Request) *plugin.Response {
  108. var ret plugin.Response
  109. content := req.Content.(*plugin.NewProxyContent)
  110. content.RemotePort = remotePort
  111. ret.Content = content
  112. return &ret
  113. }
  114. pluginServer := pluginpkg.NewHTTPPluginServer(localPort, newFunc, handler, nil)
  115. f.RunServer("", pluginServer)
  116. serverConf := consts.LegacyDefaultServerConfig + fmt.Sprintf(`
  117. [plugin.test]
  118. addr = 127.0.0.1:%d
  119. path = /handler
  120. ops = NewProxy
  121. `, localPort)
  122. clientConf := consts.LegacyDefaultClientConfig
  123. clientConf += fmt.Sprintf(`
  124. [tcp]
  125. type = tcp
  126. local_port = {{ .%s }}
  127. remote_port = 0
  128. `, framework.TCPEchoServerPort)
  129. f.RunProcesses([]string{serverConf}, []string{clientConf})
  130. framework.NewRequestExpect(f).Port(remotePort).Ensure()
  131. })
  132. })
  133. ginkgo.Describe("CloseProxy", func() {
  134. newFunc := func() *plugin.Request {
  135. var r plugin.Request
  136. r.Content = &plugin.CloseProxyContent{}
  137. return &r
  138. }
  139. ginkgo.It("Validate Info", func() {
  140. localPort := f.AllocPort()
  141. var recordProxyName string
  142. handler := func(req *plugin.Request) *plugin.Response {
  143. var ret plugin.Response
  144. content := req.Content.(*plugin.CloseProxyContent)
  145. recordProxyName = content.ProxyName
  146. return &ret
  147. }
  148. pluginServer := pluginpkg.NewHTTPPluginServer(localPort, newFunc, handler, nil)
  149. f.RunServer("", pluginServer)
  150. serverConf := consts.LegacyDefaultServerConfig + fmt.Sprintf(`
  151. [plugin.test]
  152. addr = 127.0.0.1:%d
  153. path = /handler
  154. ops = CloseProxy
  155. `, localPort)
  156. clientConf := consts.LegacyDefaultClientConfig
  157. remotePort := f.AllocPort()
  158. clientConf += fmt.Sprintf(`
  159. [tcp]
  160. type = tcp
  161. local_port = {{ .%s }}
  162. remote_port = %d
  163. `, framework.TCPEchoServerPort, remotePort)
  164. _, clients := f.RunProcesses([]string{serverConf}, []string{clientConf})
  165. framework.NewRequestExpect(f).Port(remotePort).Ensure()
  166. for _, c := range clients {
  167. _ = c.Stop()
  168. }
  169. time.Sleep(1 * time.Second)
  170. framework.ExpectEqual(recordProxyName, "tcp")
  171. })
  172. })
  173. ginkgo.Describe("Ping", func() {
  174. newFunc := func() *plugin.Request {
  175. var r plugin.Request
  176. r.Content = &plugin.PingContent{}
  177. return &r
  178. }
  179. ginkgo.It("Validate Info", func() {
  180. localPort := f.AllocPort()
  181. var record string
  182. handler := func(req *plugin.Request) *plugin.Response {
  183. var ret plugin.Response
  184. content := req.Content.(*plugin.PingContent)
  185. record = content.Ping.PrivilegeKey
  186. ret.Unchange = true
  187. return &ret
  188. }
  189. pluginServer := pluginpkg.NewHTTPPluginServer(localPort, newFunc, handler, nil)
  190. f.RunServer("", pluginServer)
  191. serverConf := consts.LegacyDefaultServerConfig + fmt.Sprintf(`
  192. [plugin.test]
  193. addr = 127.0.0.1:%d
  194. path = /handler
  195. ops = Ping
  196. `, localPort)
  197. remotePort := f.AllocPort()
  198. clientConf := consts.LegacyDefaultClientConfig
  199. clientConf += fmt.Sprintf(`
  200. heartbeat_interval = 1
  201. authenticate_heartbeats = true
  202. [tcp]
  203. type = tcp
  204. local_port = {{ .%s }}
  205. remote_port = %d
  206. `, framework.TCPEchoServerPort, remotePort)
  207. f.RunProcesses([]string{serverConf}, []string{clientConf})
  208. framework.NewRequestExpect(f).Port(remotePort).Ensure()
  209. time.Sleep(3 * time.Second)
  210. framework.ExpectNotEqual("", record)
  211. })
  212. })
  213. ginkgo.Describe("NewWorkConn", func() {
  214. newFunc := func() *plugin.Request {
  215. var r plugin.Request
  216. r.Content = &plugin.NewWorkConnContent{}
  217. return &r
  218. }
  219. ginkgo.It("Validate Info", func() {
  220. localPort := f.AllocPort()
  221. var record string
  222. handler := func(req *plugin.Request) *plugin.Response {
  223. var ret plugin.Response
  224. content := req.Content.(*plugin.NewWorkConnContent)
  225. record = content.NewWorkConn.RunID
  226. ret.Unchange = true
  227. return &ret
  228. }
  229. pluginServer := pluginpkg.NewHTTPPluginServer(localPort, newFunc, handler, nil)
  230. f.RunServer("", pluginServer)
  231. serverConf := consts.LegacyDefaultServerConfig + fmt.Sprintf(`
  232. [plugin.test]
  233. addr = 127.0.0.1:%d
  234. path = /handler
  235. ops = NewWorkConn
  236. `, localPort)
  237. remotePort := f.AllocPort()
  238. clientConf := consts.LegacyDefaultClientConfig
  239. clientConf += fmt.Sprintf(`
  240. [tcp]
  241. type = tcp
  242. local_port = {{ .%s }}
  243. remote_port = %d
  244. `, framework.TCPEchoServerPort, remotePort)
  245. f.RunProcesses([]string{serverConf}, []string{clientConf})
  246. framework.NewRequestExpect(f).Port(remotePort).Ensure()
  247. framework.ExpectNotEqual("", record)
  248. })
  249. })
  250. ginkgo.Describe("NewUserConn", func() {
  251. newFunc := func() *plugin.Request {
  252. var r plugin.Request
  253. r.Content = &plugin.NewUserConnContent{}
  254. return &r
  255. }
  256. ginkgo.It("Validate Info", func() {
  257. localPort := f.AllocPort()
  258. var record string
  259. handler := func(req *plugin.Request) *plugin.Response {
  260. var ret plugin.Response
  261. content := req.Content.(*plugin.NewUserConnContent)
  262. record = content.RemoteAddr
  263. ret.Unchange = true
  264. return &ret
  265. }
  266. pluginServer := pluginpkg.NewHTTPPluginServer(localPort, newFunc, handler, nil)
  267. f.RunServer("", pluginServer)
  268. serverConf := consts.LegacyDefaultServerConfig + fmt.Sprintf(`
  269. [plugin.test]
  270. addr = 127.0.0.1:%d
  271. path = /handler
  272. ops = NewUserConn
  273. `, localPort)
  274. remotePort := f.AllocPort()
  275. clientConf := consts.LegacyDefaultClientConfig
  276. clientConf += fmt.Sprintf(`
  277. [tcp]
  278. type = tcp
  279. local_port = {{ .%s }}
  280. remote_port = %d
  281. `, framework.TCPEchoServerPort, remotePort)
  282. f.RunProcesses([]string{serverConf}, []string{clientConf})
  283. framework.NewRequestExpect(f).Port(remotePort).Ensure()
  284. framework.ExpectNotEqual("", record)
  285. })
  286. })
  287. ginkgo.Describe("HTTPS Protocol", func() {
  288. newFunc := func() *plugin.Request {
  289. var r plugin.Request
  290. r.Content = &plugin.NewUserConnContent{}
  291. return &r
  292. }
  293. ginkgo.It("Validate Login Info, disable tls verify", func() {
  294. localPort := f.AllocPort()
  295. var record string
  296. handler := func(req *plugin.Request) *plugin.Response {
  297. var ret plugin.Response
  298. content := req.Content.(*plugin.NewUserConnContent)
  299. record = content.RemoteAddr
  300. ret.Unchange = true
  301. return &ret
  302. }
  303. tlsConfig, err := transport.NewServerTLSConfig("", "", "")
  304. framework.ExpectNoError(err)
  305. pluginServer := pluginpkg.NewHTTPPluginServer(localPort, newFunc, handler, tlsConfig)
  306. f.RunServer("", pluginServer)
  307. serverConf := consts.LegacyDefaultServerConfig + fmt.Sprintf(`
  308. [plugin.test]
  309. addr = https://127.0.0.1:%d
  310. path = /handler
  311. ops = NewUserConn
  312. `, localPort)
  313. remotePort := f.AllocPort()
  314. clientConf := consts.LegacyDefaultClientConfig
  315. clientConf += fmt.Sprintf(`
  316. [tcp]
  317. type = tcp
  318. local_port = {{ .%s }}
  319. remote_port = %d
  320. `, framework.TCPEchoServerPort, remotePort)
  321. f.RunProcesses([]string{serverConf}, []string{clientConf})
  322. framework.NewRequestExpect(f).Port(remotePort).Ensure()
  323. framework.ExpectNotEqual("", record)
  324. })
  325. })
  326. })