[GH-ISSUE #1403] Feature: Server Manage Plugin #1105

Closed
opened 2026-05-05 12:42:45 -06:00 by gitea-mirror · 5 comments
Owner

Originally created by @fatedier on GitHub (Aug 21, 2019).
Original GitHub issue: https://github.com/fatedier/frp/issues/1403

To track design for server manage plugin.

Originally created by @fatedier on GitHub (Aug 21, 2019). Original GitHub issue: https://github.com/fatedier/frp/issues/1403 To track design for server manage plugin.
gitea-mirror 2026-05-05 12:42:45 -06:00
  • closed this issue
  • added the
    todo
    label
Author
Owner

@fatedier commented on GitHub (Dec 2, 2019):

插件

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": {
        ... // 替换后的操作信息,格式必须和请求时的一致
    }
}

操作类型

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

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
    }
}

NewProxy

创建代理的相关信息

{
    "content": {
        "user": {
            "user": <string>,
            "metas": map<string>string
        },
        "proxy_name": <string>,
        "proxy_type": <string>,
        "use_encryption": <bool>,
        "use_compression": <bool>,
        "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,

        "metas": map<string>string
    }
}

frps 中插件配置

[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: 插件监听的网络地址。
path: 插件监听的 HTTP 请求路径。
ops: 插件需要处理的操作列表,多个 op 以英文逗号分隔。

元数据

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

元数据以 meta_ 开头,可以配置多个,元数据分为两种,一种配置在 common 下,一种配置在各个 proxy 中。

# 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
<!-- gh-comment-id:560296482 --> @fatedier commented on GitHub (Dec 2, 2019): ### 插件 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": { ... // 替换后的操作信息,格式必须和请求时的一致 } } ``` ### 操作类型 目前插件支持管理的操作类型有 `Login` 和 `NewProxy`。 #### 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 } } ``` #### NewProxy 创建代理的相关信息 ``` { "content": { "user": { "user": <string>, "metas": map<string>string }, "proxy_name": <string>, "proxy_type": <string>, "use_encryption": <bool>, "use_compression": <bool>, "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, "metas": map<string>string } } ``` ### 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: 插件监听的网络地址。 path: 插件监听的 HTTP 请求路径。 ops: 插件需要处理的操作列表,多个 op 以英文逗号分隔。 ### 元数据 为了减少 frps 的代码修改,同时提高管理插件的扩展能力,在 frpc 的配置文件中引入自定义元数据的概念。元数据会在调用 RPC 请求时发送给插件。 元数据以 `meta_` 开头,可以配置多个,元数据分为两种,一种配置在 `common` 下,一种配置在各个 proxy 中。 ``` # 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 ```
Author
Owner

@fatedier commented on GitHub (Dec 2, 2019):

Manage Plugin

frp manage plugin is aim to extend frp's ability without modifing self code.

It runs as a process and listen on a port to provide RPC interface. Before frps doing some operations, frps will send RPC requests to manage plugin and do operations by it's response.

RPC request

Support HTTP first.

When manage plugin accept the operation request, it can give three different responses.

  • Reject operation and return the 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. Assume here is /handler.

Request

POST /handler
{
    "version": "0.1.0",
    "op": "Login",
    "content": {
        ... // Operation info
    }
}

Request Header
X-Frp-Reqid: for tracing

Response

Error if not return 200 http code.

Reject opeartion

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

Allow operation and keep original content

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

Allow opeartion and modify content

{
    "unchange": "false",
    "content": {
        ... // Replaced content
    }
}

Operation

Now it supports Login and NewProxy.

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
    }
}

NewProxy

Create new proxy

{
    "content": {
        "user": {
            "user": <string>,
            "metas": map<string>string
        },
        "proxy_name": <string>,
        "proxy_type": <string>,
        "use_encryption": <bool>,
        "use_compression": <bool>,
        "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,

        "metas": map<string>string
    }
}

manage plugin configure

[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: plugin listen on.
path: http request url path.
ops: opeartions plugin needs handle.

meta data

Meta data will be sent to manage plugin in each RCP request.

Meta data start with meta_. It can be configured in common and each proxy.

# 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
<!-- gh-comment-id:560303837 --> @fatedier commented on GitHub (Dec 2, 2019): ### Manage Plugin frp manage plugin is aim to extend frp's ability without modifing self code. It runs as a process and listen on a port to provide RPC interface. Before frps doing some operations, frps will send RPC requests to manage plugin and do operations by it's response. ### RPC request Support HTTP first. When manage plugin accept the operation request, it can give three different responses. * Reject operation and return the 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. Assume here is `/handler`. Request ``` POST /handler { "version": "0.1.0", "op": "Login", "content": { ... // Operation info } } Request Header X-Frp-Reqid: for tracing ``` Response Error if not return 200 http code. Reject opeartion ``` { "reject": true, "reject_reason": "invalid user" } ``` Allow operation and keep original content ``` { "reject": false, "unchange": true } ``` Allow opeartion and modify content ``` { "unchange": "false", "content": { ... // Replaced content } } ``` ### Operation Now it supports `Login` and `NewProxy`. #### 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 } } ``` #### NewProxy Create new proxy ``` { "content": { "user": { "user": <string>, "metas": map<string>string }, "proxy_name": <string>, "proxy_type": <string>, "use_encryption": <bool>, "use_compression": <bool>, "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, "metas": map<string>string } } ``` ### manage plugin configure ```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: plugin listen on. path: http request url path. ops: opeartions plugin needs handle. ### meta data Meta data will be sent to manage plugin in each RCP request. Meta data start with `meta_`. It can be configured in `common` and each proxy. ``` # 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 ```
Author
Owner

@mesoar commented on GitHub (Dec 9, 2019):

想请问下这个插件或API目前可以用了吗?

<!-- gh-comment-id:563409095 --> @mesoar commented on GitHub (Dec 9, 2019): 想请问下这个插件或API目前可以用了吗?
Author
Owner

@thofd commented on GitHub (Dec 23, 2019):

支持这个功能早日实现

<!-- gh-comment-id:568341207 --> @thofd commented on GitHub (Dec 23, 2019): 支持这个功能早日实现
Author
Owner

@fatedier commented on GitHub (Jan 3, 2020):

Supported in v0.31.0.

If anyone want to share your plugin, create an issue on https://github.com/gofrp/plugin .

<!-- gh-comment-id:570479198 --> @fatedier commented on GitHub (Jan 3, 2020): Supported in v0.31.0. If anyone want to share your plugin, create an issue on https://github.com/gofrp/plugin .
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: github-starred/frp#1105
No description provided.