server.go 10 KB

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