服务端插件

frp 服务端插件的作用是在不侵入自身代码的前提下,扩展 frp 服务端的能力。

frp 服务端插件会以单独进程的形式运行,并且监听在一个端口上,对外提供 RPC 接口,响应 frps 的请求。

frps 在执行某些操作前,会根据配置向服务端插件发送 RPC 请求,根据插件的响应来执行相应的操作。

RPC 请求

服务端插件接收到操作请求后,可以给出三种回应。

  • 拒绝操作,需要返回拒绝操作的原因。
  • 允许操作,不需要修改操作内容。
  • 允许操作,对操作请求进行修改后,返回修改后的内容。

接口

接口路径可以在 frps 配置中为每个插件单独配置,这里以 /handler 为例。

Request

POST /handler?version=0.1.0&op=Login
    {
        "content": {
            ... // 具体的操作信息
        }
    }
    
    请求 Header
    X-Frp-Reqid: 用于追踪请求
    

Response

非 200 的返回都认为是请求异常。

拒绝执行操作

{
        "reject": true,
        "reject_reason": "invalid user"
    }
    

允许且内容不需要变动

{
        "reject": false,
        "unchange": true
    }
    

允许且需要替换操作内容

{
        "unchange": "false",
        "content": {
            ... // 替换后的操作信息,格式必须和请求时的一致
        }
    }
    

操作类型

目前插件支持管理的操作类型有 LoginNewProxyCloseProxyPingNewWorkConnNewUserConn

Login

用户登录操作信息

{
        "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

创建代理的相关信息

{
        "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

代理关闭。(仅用于通知)

注意: 当单个 frpc 会注册大量 proxy 时,慎重使用此接口,可能会由于连接数超限而影响服务的可用性。

{
        "content": {
            "user": {
                "user": <string>,
                "metas": map<string>string
                "run_id": <string>
            },
            "proxy_name": <string>
        }
    }
    

Ping

心跳相关信息

{
        "content": {
            "user": {
                "user": <string>,
                "metas": map<string>string
                "run_id": <string>
            },
            "timestamp": <int64>,
            "privilege_key": <string>
        }
    }
    

NewWorkConn

创建工作连接

{
        "content": {
            "user": {
                "user": <string>,
                "metas": map<string>string
                "run_id": <string>
            },
            "run_id": <string>
            "timestamp": <int64>,
            "privilege_key": <string>
        }
    }
    

NewUserConn

创建用户连接 (支持 tcpstcphttpstcpmux 协议)。

{
        "content": {
            "user": {
                "user": <string>,
                "metas": map<string>string
                "run_id": <string>
            },
            "proxy_name": <string>,
            "proxy_type": <string>,
            "remote_addr": <string>
        }
    }
    

frps 中插件配置

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: 插件监听的网络地址,支持 HTTP 和 HTTPS,默认为 HTTP。
  • path: 插件监听的请求路径。
  • ops: 插件需要处理的操作列表,多个 op 以英文逗号分隔。
  • tls_verify: 如果是 HTTPS 协议,支持忽略 TLS 身份验证。

元数据

为了减少 frps 的代码修改,同时提高管理插件的扩展能力,在 frpc 的配置文件中引入自定义元数据的概念。元数据会在调用 RPC 请求时发送给插件。

有两种类型的元数据条目,全局条目和每个代理配置下的条目。全局元数据将在客户端登录时附加在 Login 请求中,并在其他 RPC 请求中附加在 user.metas 中。

每个代理配置下的元数据条目仅会在 NewProxy 操作中通过 metas 传递。

# 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"
    
最后修改 November 15, 2023: fix 404 (#71) (626ce4d)

Server side Plug-in

The function of frp Server side Plug in is to extend without intruding into its own code The ability of frp Server side.

Frp Server side Plug in will run as a separate process and listen on a single port, providing external support RPC interface, responding to requests from frps.

Before performing certain operations, FRPS will report to the Server side based on Configuration Plug in sends RPC requests and performs corresponding operations based on the response of Plug in.

RPC request

After receiving an operation request, the Server Side Plug in can provide three types of responses

  • Refuse the operation and return the reason for the rejection
  • Allow operation without modifying the operation content
  • Allow operations, modify the operation request, and return the modified content

Interface

The interface path can be found in FRPS In the Configuration, each Plug in is configured separately. Here Taking/handleras an example.

Request

POST /handler?version=0.1.0&op=Login
  {
  " Content: {
  ...//Specific operation information
  }
  }
  Request Header
  X-Frp Reqid: used for tracking requests
                      

Response

Non 200 returns are considered as request exceptions

Refuse to perform operation

{
                      " Reject: True,
                      " Reject_ Reason&# 34;:&# 34; Invalid user;
                      }
                      

Allow and do not require any changes to the content

{
  " Reject: False,
  " Unchange&# 34;: True
  }
                      

Allow and require replacement of operation content

{
  " Unchange&# 34;:&# 34; False;,
  " Content: {
  ...//The format of the replaced operation information must be consistent with the requested one
  }
  }
    

Operation Type

Currently, the types of operations that Plug in supports management include LoginNewProxy,CloseProxy,Ping,NewWorkConn AndNewUserConn.

Login

User login operation information

{
        "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

创建Agent 的相关信息

{
        "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

Agent shutdown. (For notification only)

Note: When a single FRPC registers a large number of proxies Be cautious when using this interface, as it may affect service availability due to exceeding the connection limit.

{
        "content": {
            "user": {
                "user": <string>,
                "metas": map<string>string
                "run_id": <string>
            },
            "proxy_name": <string>
        }
    }
    

Ping

Heartbeat related information

{
        "content": {
            "user": {
                "user": <string>,
                "metas": map<string>string
                "run_id": <string>
            },
            "timestamp": <int64>,
            "privilege_key": <string>
        }
    }
    

NewWorkConn

Create a working connection

{
        "content": {
            "user": {
                "user": <string>,
                "metas": map<string>string
                "run_id": <string>
            },
            "run_id": <string>
            "timestamp": <int64>,
            "privilege_key": <string>
        }
    }
    

NewUserConn

Create a user connection (supportTCP,stcp,Https Andtcpmuxprotocol)

{
        "content": {
            "user": {
                "user": <string>,
                "metas": map<string>string
                "run_id": <string>
            },
            "proxy_name": <string>,
            "proxy_type": <string>,
            "remote_addr": <string>
        }
    }
    

frps 中Plug-inConfiguration

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 network address that the Plug in listens to, supports HTTP and HTTPS, and defaults to HTTP.
  • Path: The request path that Plug in listens to
  • Ops: A list of operations that Plug in needs to handle, with multiple ops separated by English commas.
  • Tls_ Verify: If it is the HTTPS protocol, it supports ignoring TLS authentication.

metadata

In order to reduce code modifications in FRPS and improve the scalability of managing Plug ins, the Configuration of frpc Introduce the concept of custom metadata in file. The metadata will be called in RPC Send the request to Plug in.

There are two types of metadata entries, global entries and each agent entry Entry under Configuration. Global metadata will be attached to the Login during client login In the request and attached in other RPC requests Inuser. metrics.

The metadata entries under each Agent Configuration will only be available in NewProxy Passed through metadata during operation.

# 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"
    
Last modified November 15, 2023: fix 404 (#71) (626ce4d)