### Server Plugin frp server plugin is aimed to extend frp's ability without modifying the Golang code. An external server should run in a different process receiving RPC calls from frps. Before frps is doing some operations, it will send RPC requests to notify the external RPC server and act according to its response. ### RPC request RPC requests are based on JSON over HTTP. When a server plugin accepts an operation request, it can respond with three different responses: * Reject operation and return a reason. * Allow operation and keep original content. * Allow operation and return modified content. ### Interface HTTP path can be configured for each manage plugin in frps. We'll assume for this example that it's `/handler`. A request to the RPC server will look like: ``` POST /handler { "version": "0.1.0", "op": "Login", "content": { ... // Operation info } } Request Header: X-Frp-Reqid: for tracing ``` The response can look like any of the following: * Non-200 HTTP response status code (this will automatically tell frps that the request should fail) * Reject operation: ``` { "reject": true, "reject_reason": "invalid user" } ``` * Allow operation and keep original content: ``` { "reject": false, "unchange": true } ``` * Allow operation and modify content ``` { "unchange": "false", "content": { ... // Replaced content } } ``` ### Operation Currently `Login`, `NewProxy`, `Ping` and `NewWorkConn` operations are supported. #### Login Client login operation ``` { "content": { "version": , "hostname": , "os": , "arch": , "user": , "timestamp": , "privilege_key": , "run_id": , "pool_count": , "metas": mapstring } } ``` #### NewProxy Create new proxy ``` { "content": { "user": { "user": , "metas": mapstring "run_id": }, "proxy_name": , "proxy_type": , "use_encryption": , "use_compression": , "group": , "group_key": , // tcp and udp only "remote_port": , // http and https only "custom_domains": [], "subdomain": , "locations": , "http_user": , "http_pwd": , "host_header_rewrite": , "headers": mapstring, // stcp only "sk": , // tcpmux only "multiplexer": "metas": mapstring } } ``` #### Ping Heartbeat from frpc ``` { "content": { "user": { "user": , "metas": mapstring "run_id": }, "timestamp": , "privilege_key": } } ``` #### NewWorkConn New work connection received from frpc (RPC sent after `run_id` is matched with an existing frp connection) ``` { "content": { "user": { "user": , "metas": mapstring "run_id": }, "run_id": "timestamp": , "privilege_key": } } ``` ### Server Plugin Configuration ```ini # frps.ini [common] bind_port = 7000 [plugin.user-manager] addr = 127.0.0.1:9000 path = /handler ops = Login [plugin.port-manager] addr = 127.0.0.1:9001 path = /handler ops = NewProxy ``` addr: the address where the external RPC service listens on. path: http request url path for the POST request. ops: operations plugin needs to handle (e.g. "Login", "NewProxy", ...). ### Metadata Metadata will be sent to the server plugin in each RPC request. There are 2 types of metadata entries - 1 under `[common]` and the other under each proxy configuration. Metadata entries under `[common]` will be sent in `Login` under the key `metas`, and in any other RPC request under `user.metas`. Metadata entries under each proxy configuration will be sent in `NewProxy` op only, under `metas`. Metadata entries start with `meta_`. This is an example of metadata entries in `[common]` and under the proxy named `[ssh]`: ``` # frpc.ini [common] server_addr = 127.0.0.1 server_port = 7000 user = fake meta_token = fake meta_version = 1.0.0 [ssh] type = tcp local_port = 22 remote_port = 6000 meta_id = 123 ```