frp/doc/server_plugin.md

266 lines
5.6 KiB
Markdown

### 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
{
"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`, `CloseProxy`, `Ping`, `NewWorkConn` and `NewUserConn` operations are supported.
#### Login
Client login operation
```
{
"content": {
"version": <string>,
"hostname": <string>,
"os": <string>,
"arch": <string>,
"user": <string>,
"timestamp": <int64>,
"privilege_key": <string>,
"run_id": <string>,
"pool_count": <int>,
"metas": map<string>string,
"client_address": <string>
}
}
```
#### NewProxy
Create new proxy
```
{
"content": {
"user": {
"user": <string>,
"metas": map<string>string
"run_id": <string>
},
"proxy_name": <string>,
"proxy_type": <string>,
"use_encryption": <bool>,
"use_compression": <bool>,
"bandwidth_limit": <string>,
"bandwidth_limit_mode": <string>,
"group": <string>,
"group_key": <string>,
// tcp and udp only
"remote_port": <int>,
// http and https only
"custom_domains": []<string>,
"subdomain": <string>,
"locations": <string>,
"http_user": <string>,
"http_pwd": <string>,
"host_header_rewrite": <string>,
"headers": map<string>string,
// stcp only
"sk": <string>,
// tcpmux only
"multiplexer": <string>
"metas": map<string>string
}
}
```
#### CloseProxy
A previously created proxy is closed.
Please note that one request will be sent for every proxy that is closed, do **NOT** use this
if you have too many proxies bound to a single client, as this may exhaust the server's resources.
```
{
"content": {
"user": {
"user": <string>,
"metas": map<string>string
"run_id": <string>
},
"proxy_name": <string>
}
}
```
#### Ping
Heartbeat from frpc
```
{
"content": {
"user": {
"user": <string>,
"metas": map<string>string
"run_id": <string>
},
"timestamp": <int64>,
"privilege_key": <string>
}
}
```
#### NewWorkConn
New work connection received from frpc (RPC sent after `run_id` is matched with an existing frp connection)
```
{
"content": {
"user": {
"user": <string>,
"metas": map<string>string
"run_id": <string>
},
"run_id": <string>
"timestamp": <int64>,
"privilege_key": <string>
}
}
```
#### NewUserConn
New user connection received from proxy (support `tcp`, `stcp`, `https` and `tcpmux`) .
```
{
"content": {
"user": {
"user": <string>,
"metas": map<string>string
"run_id": <string>
},
"proxy_name": <string>,
"proxy_type": <string>,
"remote_addr": <string>
}
}
```
### Server Plugin Configuration
```toml
# frps.toml
bindPort = 7000
[[httpPlugins]]
name = "user-manager"
addr = "127.0.0.1:9000"
path = "/handler"
ops = ["Login"]
[[httpPlugins]]
name = "port-manager"
addr = "127.0.0.1:9001"
path = "/handler"
ops = ["NewProxy"]
```
- addr: the address where the external RPC service listens. Defaults to http. For https, specify the schema: `addr = "https://127.0.0.1:9001"`.
- path: http request url path for the POST request.
- ops: operations plugin needs to handle (e.g. "Login", "NewProxy", ...).
- tlsVerify: When the schema is https, we verify by default. Set this value to false if you want to skip verification.
### Metadata
Metadata will be sent to the server plugin in each RPC request.
There are 2 types of metadata entries - global one and the other under each proxy configuration.
Global metadata entries 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`.
This is an example of metadata entries:
```toml
# frpc.toml
serverAddr = "127.0.0.1"
serverPort = 7000
user = "fake"
metadatas.token = "fake"
metadatas.version = "1.0.0"
[[proxies]]
name = "ssh"
type = "tcp"
localPort = 22
remotePort = 6000
metadatas.id = "123"
```