server.go 10 KB

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