summaryrefslogtreecommitdiffhomepage
path: root/applications/luci-app-frps
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2020-02-02 22:30:28 +0100
committerGitHub <noreply@github.com>2020-02-02 22:30:28 +0100
commit3d63732c4e22260148761ef57afb3500cb5a0fab (patch)
treed9257b0c3c9230dd0d2527fdcb1e0094c25f01ce /applications/luci-app-frps
parenta50e25ddfd7ff0671d505aeb39208de3378ad33c (diff)
parent51d38ee06dc871027387735185af5e2c4cb93736 (diff)
Merge pull request #3173 from ysc3839/frp
[RFC] luci-app-frp: add new packages
Diffstat (limited to 'applications/luci-app-frps')
-rw-r--r--applications/luci-app-frps/Makefile13
-rw-r--r--applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js114
-rw-r--r--applications/luci-app-frps/po/templates/frps.pot320
-rw-r--r--applications/luci-app-frps/root/usr/share/luci/menu.d/luci-app-frps.json9
-rw-r--r--applications/luci-app-frps/root/usr/share/rpcd/acl.d/luci-app-frps.json8
5 files changed, 464 insertions, 0 deletions
diff --git a/applications/luci-app-frps/Makefile b/applications/luci-app-frps/Makefile
new file mode 100644
index 0000000000..4d77b03c07
--- /dev/null
+++ b/applications/luci-app-frps/Makefile
@@ -0,0 +1,13 @@
+# This is free software, licensed under the Apache License, Version 2.0
+
+include $(TOPDIR)/rules.mk
+
+LUCI_TITLE:=LuCI Support for frp server
+LUCI_DEPENDS:=+frps
+
+PKG_LICENSE:=Apache-2.0
+PKG_MAINTAINER:=Richard Yu <yurichard3839@gmail.com>
+
+include ../../luci.mk
+
+# call BuildPackage - OpenWrt buildroot signature
diff --git a/applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js b/applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js
new file mode 100644
index 0000000000..d941a99379
--- /dev/null
+++ b/applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js
@@ -0,0 +1,114 @@
+'use strict';
+'require form';
+'require tools.widgets as widgets';
+
+// [Widget, Option, Title, Description, {Param: 'Value'}],
+var startupConf = [
+ [form.Flag, 'stdout', _('Log stdout')],
+ [form.Flag, 'stderr', _('Log stderr')],
+ [widgets.UserSelect, 'user', _('Run daemon as user')],
+ [widgets.GroupSelect, 'group', _('Run daemon as group')],
+ [form.Flag, 'respawn', _('Respawn when crashed')],
+ [form.DynamicList, 'env', _('Environment variable'), _('OS environments pass to frp for config file template, see <a href="https://github.com/fatedier/frp#configuration-file-template">frp README</a>'), {placeholder: 'ENV_NAME=value'}],
+ [form.DynamicList, 'conf_inc', _('Additional configs'), _('Config files include in temporary config file'), {placeholder: '/etc/frp/frps.d/frps_full.ini'}]
+];
+
+var commonConf = [
+ [form.Value, 'bind_addr', _('Bind address'), _('BindAddr specifies the address that the server binds to.<br>By default, this value is "0.0.0.0".'), {datatype: 'ipaddr'}],
+ [form.Value, 'bind_port', _('Bind port'), _('BindPort specifies the port that the server listens on.<br>By default, this value is 7000.'), {datatype: 'port'}],
+ [form.Value, 'bind_udp_port', _('UDP bind port'), _('BindUdpPort specifies the UDP port that the server listens on. If this value is 0, the server will not listen for UDP connections.<br>By default, this value is 0'), {datatype: 'port'}],
+ [form.Value, 'kcp_bind_port', _('KCP bind port'), _('BindKcpPort specifies the KCP port that the server listens on. If this value is 0, the server will not listen for KCP connections.<br>By default, this value is 0.'), {datatype: 'port'}],
+ [form.Value, 'proxy_bind_addr', _('Proxy bind address'), _('ProxyBindAddr specifies the address that the proxy binds to. This value may be the same as BindAddr.<br>By default, this value is "0.0.0.0".'), {datatype: 'ipaddr'}],
+ [form.Value, 'vhost_http_port', _('Vhost HTTP port'), _('VhostHttpPort specifies the port that the server listens for HTTP Vhost requests. If this value is 0, the server will not listen for HTTP requests.<br>By default, this value is 0.'), {datatype: 'port'}],
+ [form.Value, 'vhost_https_port', _('Vhost HTTPS port'), _('VhostHttpsPort specifies the port that the server listens for HTTPS Vhost requests. If this value is 0, the server will not listen for HTTPS requests.<br>By default, this value is 0.'), {datatype: 'port'}],
+ [form.Value, 'vhost_http_timeout', _('Vhost HTTP timeout'), _('VhostHttpTimeout specifies the response header timeout for the Vhost HTTP server, in seconds.<br>By default, this value is 60.'), {datatype: 'uinteger'}],
+ [form.Value, 'dashboard_addr', _('Dashboard address'), _('DashboardAddr specifies the address that the dashboard binds to.<br>By default, this value is "0.0.0.0".'), {datatype: 'ipaddr'}],
+ [form.Value, 'dashboard_port', _('Dashboard port'), _('DashboardPort specifies the port that the dashboard listens on. If this value is 0, the dashboard will not be started.<br>By default, this value is 0.'), {datatype: 'port'}],
+ [form.Value, 'dashboard_user', _('Dashboard user'), _('DashboardUser specifies the username that the dashboard will use for login.<br>By default, this value is "admin".')],
+ [form.Value, 'dashboard_pwd', _('Dashboard password'), _('DashboardPwd specifies the password that the dashboard will use for login.<br>By default, this value is "admin".'), {password: true}],
+ [form.Value, 'assets_dir', _('Assets dir'), _('AssetsDir specifies the local directory that the dashboard will load resources from. If this value is "", assets will be loaded from the bundled executable using statik.<br>By default, this value is "".')],
+ [form.Value, 'log_file', _('Log file'), _('LogFile specifies a file where logs will be written to. This value will only be used if LogWay is set appropriately.<br>By default, this value is "console".')],
+ [form.ListValue, 'log_level', _('Log level'), _('LogLevel specifies the minimum log level. Valid values are "trace", "debug", "info", "warn", and "error".<br>By default, this value is "info".'), {values: ['trace', 'debug', 'info', 'warn', 'error']}],
+ [form.Value, 'log_max_days', _('Log max days'), _('LogMaxDays specifies the maximum number of days to store log information before deletion. This is only used if LogWay == "file".<br>By default, this value is 0.'), {datatype: 'uinteger'}],
+ [form.Flag, 'disable_log_color', _('Disable log color'), _('DisableLogColor disables log colors when LogWay == "console" when set to true.<br>By default, this value is false.'), {datatype: 'bool', default: 'true'}],
+ [form.Value, 'token', _('Token'), _('Token specifies the authorization token used to authenticate keys received from clients. Clients must have a matching token to be authorized to use the server.<br>By default, this value is "".')],
+ [form.Value, 'subdomain_host', _('Subdomain host'), _('SubDomainHost specifies the domain that will be attached to sub-domains requested by the client when using Vhost proxying. For example, if this value is set to "frps.com" and the client requested the subdomain "test", the resulting URL would be "test.frps.com".<br>By default, this value is "".')],
+ [form.Flag, 'tcp_mux', _('TCP mux'), _('TcpMux toggles TCP stream multiplexing. This allows multiple requests from a client to share a single TCP connection.<br>By default, this value is true.'), {datatype: 'bool', default: 'true'}],
+ [form.Value, 'custom_404_page', _('Custom 404 page'), _('Custom404Page specifies a path to a custom 404 page to display. If this value is "", a default page will be displayed.<br>By default, this value is "".')],
+ [form.Value, 'allow_ports', _('Allow ports'), _('AllowPorts specifies a set of ports that clients are able to proxy to. If the length of this value is 0, all ports are allowed.<br>By default, this value is an empty set.')],
+ [form.Value, 'max_ports_per_client', _('Max ports per client'), _('MaxPortsPerClient specifies the maximum number of ports a single client may proxy to. If this value is 0, no limit will be applied.<br>By default, this value is 0.'), {datatype: 'uinteger'}],
+ [form.Value, 'heartbeat_timeout', _('Heartbeat timeout'), _('HeartBeatTimeout specifies the maximum time to wait for a heartbeat before terminating the connection. It is not recommended to change this value.<br>By default, this value is 90.'), {datatype: 'uinteger'}]
+];
+
+function setParams(o, params) {
+ if (!params) return;
+ for (var key in params) {
+ var val = params[key];
+ if (key === 'values') {
+ for (var j = 0; j < val.length; j++) {
+ var args = val[j];
+ if (!Array.isArray(args))
+ args = [args];
+ o.value.apply(o, args);
+ }
+ } else if (key === 'depends') {
+ if (!Array.isArray(val))
+ val = [val];
+ for (var j = 0; j < val.length; j++) {
+ var args = val[j];
+ if (!Array.isArray(args))
+ args = [args];
+ o.depends.apply(o, args);
+ }
+ } else {
+ o[key] = params[key];
+ }
+ }
+ if (params['datatype'] === 'bool') {
+ o.enabled = 'true';
+ o.disabled = 'false';
+ }
+}
+
+function defTabOpts(s, t, opts, params) {
+ for (var i = 0; i < opts.length; i++) {
+ var opt = opts[i];
+ var o = s.taboption(t, opt[0], opt[1], opt[2], opt[3]);
+ setParams(o, opt[4]);
+ setParams(o, params);
+ }
+}
+
+function defOpts(s, opts, params) {
+ for (var i = 0; i < opts.length; i++) {
+ var opt = opts[i];
+ var o = s.option(opt[0], opt[1], opt[2], opt[3]);
+ setParams(o, opt[4]);
+ setParams(o, params);
+ }
+}
+
+return L.view.extend({
+ render: function() {
+ var m, s, o;
+
+ m = new form.Map('frps', _('frp Server'));
+
+ s = m.section(form.NamedSection, 'common', 'conf');
+ s.dynamic = true;
+
+ s.tab('common', _('Common settings'));
+ s.tab('init', _('Startup settings'));
+
+ defTabOpts(s, 'common', commonConf, {optional: true});
+
+ o = s.taboption('init', form.SectionValue, 'init', form.TypedSection, 'init', _('Startup settings'));
+ s = o.subsection;
+ s.anonymous = true;
+ s.dynamic = true;
+
+ defOpts(s, startupConf);
+
+ return m.render();
+ }
+});
diff --git a/applications/luci-app-frps/po/templates/frps.pot b/applications/luci-app-frps/po/templates/frps.pot
new file mode 100644
index 0000000000..11c320870b
--- /dev/null
+++ b/applications/luci-app-frps/po/templates/frps.pot
@@ -0,0 +1,320 @@
+msgid ""
+msgstr "Content-Type: text/plain; charset=UTF-8"
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:13
+msgid "Additional configs"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:38
+msgid "AllowPorts"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:38
+msgid ""
+"AllowPorts specifies a set of ports that clients are able to proxy to. If "
+"the length of this value is 0, all ports are allowed.<br>By default, this "
+"value is an empty set."
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:29
+msgid "AssetsDir"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:29
+msgid ""
+"AssetsDir specifies the local directory that the dashboard will load "
+"resources from. If this value is \"\", assets will be loaded from the "
+"bundled executable using statik.<br>By default, this value is \"\"."
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:17
+msgid "BindAddr"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:17
+msgid ""
+"BindAddr specifies the address that the server binds to.<br>By default, this "
+"value is \"0.0.0.0\"."
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:20
+msgid "BindKcpPort"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:20
+msgid ""
+"BindKcpPort specifies the KCP port that the server listens on. If this value "
+"is 0, the server will not listen for KCP connections.<br>By default, this "
+"value is 0."
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:18
+msgid "BindPort"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:18
+msgid ""
+"BindPort specifies the port that the server listens on.<br>By default, this "
+"value is 7000."
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:19
+msgid "BindUdpPort"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:19
+msgid ""
+"BindUdpPort specifies the UDP port that the server listens on. If this value "
+"is 0, the server will not listen for UDP connections.<br>By default, this "
+"value is 0"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:101
+msgid "Common settings"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:13
+msgid "Config files include in temporary config file"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:37
+msgid "Custom404Page"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:37
+msgid ""
+"Custom404Page specifies a path to a custom 404 page to display. If this "
+"value is \"\", a default page will be displayed.<br>By default, this value "
+"is \"\"."
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:25
+msgid "DashboardAddr"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:25
+msgid ""
+"DashboardAddr specifies the address that the dashboard binds to.<br>By "
+"default, this value is \"0.0.0.0\"."
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:26
+msgid "DashboardPort"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:26
+msgid ""
+"DashboardPort specifies the port that the dashboard listens on. If this "
+"value is 0, the dashboard will not be started.<br>By default, this value is "
+"0."
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:28
+msgid "DashboardPwd"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:28
+msgid ""
+"DashboardPwd specifies the password that the dashboard will use for login."
+"<br>By default, this value is \"admin\"."
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:27
+msgid "DashboardUser"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:27
+msgid ""
+"DashboardUser specifies the username that the dashboard will use for login."
+"<br>By default, this value is \"admin\"."
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:33
+msgid "DisableLogColor"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:33
+msgid ""
+"DisableLogColor disables log colors when LogWay == \"console\" when set to "
+"true.<br>By default, this value is false."
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:12
+msgid "Environment variable"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:41
+msgid "HeartBeatTimeout"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:41
+msgid ""
+"HeartBeatTimeout specifies the maximum time to wait for a heartbeat before "
+"terminating the connection. It is not recommended to change this value."
+"<br>By default, this value is 90."
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:8
+msgid "Log stderr"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:7
+msgid "Log stdout"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:30
+msgid "LogFile"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:30
+msgid ""
+"LogFile specifies a file where logs will be written to. This value will only "
+"be used if LogWay is set appropriately.<br>By default, this value is "
+"\"console\"."
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:31
+msgid "LogLevel"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:31
+msgid ""
+"LogLevel specifies the minimum log level. Valid values are \"trace\", \"debug"
+"\", \"info\", \"warn\", and \"error\".<br>By default, this value is \"info\"."
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:32
+msgid "LogMaxDays"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:32
+msgid ""
+"LogMaxDays specifies the maximum number of days to store log information "
+"before deletion. This is only used if LogWay == \"file\".<br>By default, "
+"this value is 0."
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:39
+msgid "MaxPoolCount"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:39
+msgid ""
+"MaxPoolCount specifies the maximum pool size for each proxy.<br>By default, "
+"this value is 5."
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:40
+msgid "MaxPortsPerClient"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:40
+msgid ""
+"MaxPortsPerClient specifies the maximum number of ports a single client may "
+"proxy to. If this value is 0, no limit will be applied.<br>By default, this "
+"value is 0."
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:12
+msgid ""
+"OS environments pass to frp for config file template, see <a href=\"https://"
+"github.com/fatedier/frp#configuration-file-template\">frp README</a>"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:21
+msgid "ProxyBindAddr"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:21
+msgid ""
+"ProxyBindAddr specifies the address that the proxy binds to. This value may "
+"be the same as BindAddr.<br>By default, this value is \"0.0.0.0\"."
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:11
+msgid "Respawn when crashed"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:10
+msgid "Run daemon as group"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:9
+msgid "Run daemon as user"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:102
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:106
+msgid "Startup settings"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:35
+msgid "SubDomainHost"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:35
+msgid ""
+"SubDomainHost specifies the domain that will be attached to sub-domains "
+"requested by the client when using Vhost proxying. For example, if this "
+"value is set to \"frps.com\" and the client requested the subdomain \"test"
+"\", the resulting URL would be \"test.frps.com\".<br>By default, this value "
+"is \"\"."
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:36
+msgid "TcpMux"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:36
+msgid ""
+"TcpMux toggles TCP stream multiplexing. This allows multiple requests from a "
+"client to share a single TCP connection.<br>By default, this value is true."
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:34
+msgid "Token"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:34
+msgid ""
+"Token specifies the authorization token used to authenticate keys received "
+"from clients. Clients must have a matching token to be authorized to use the "
+"server.<br>By default, this value is \"\"."
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:22
+msgid "VhostHttpPort"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:22
+msgid ""
+"VhostHttpPort specifies the port that the server listens for HTTP Vhost "
+"requests. If this value is 0, the server will not listen for HTTP requests."
+"<br>By default, this value is 0."
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:24
+msgid "VhostHttpTimeout"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:24
+msgid ""
+"VhostHttpTimeout specifies the response header timeout for the Vhost HTTP "
+"server, in seconds.<br>By default, this value is 60."
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:23
+msgid "VhostHttpsPort"
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:23
+msgid ""
+"VhostHttpsPort specifies the port that the server listens for HTTPS Vhost "
+"requests. If this value is 0, the server will not listen for HTTPS requests."
+"<br>By default, this value is 0."
+msgstr ""
+
+#: applications/luci-app-frps/htdocs/luci-static/resources/view/frps.js:96
+#: applications/luci-app-frps/root/usr/share/luci/menu.d/luci-app-frps.json:3
+msgid "frp Server"
+msgstr ""
diff --git a/applications/luci-app-frps/root/usr/share/luci/menu.d/luci-app-frps.json b/applications/luci-app-frps/root/usr/share/luci/menu.d/luci-app-frps.json
new file mode 100644
index 0000000000..3b87114515
--- /dev/null
+++ b/applications/luci-app-frps/root/usr/share/luci/menu.d/luci-app-frps.json
@@ -0,0 +1,9 @@
+{
+ "admin/services/frps": {
+ "title": "frp Server",
+ "action": {
+ "type": "view",
+ "path": "frps"
+ }
+ }
+}
diff --git a/applications/luci-app-frps/root/usr/share/rpcd/acl.d/luci-app-frps.json b/applications/luci-app-frps/root/usr/share/rpcd/acl.d/luci-app-frps.json
new file mode 100644
index 0000000000..8c0f8f5a06
--- /dev/null
+++ b/applications/luci-app-frps/root/usr/share/rpcd/acl.d/luci-app-frps.json
@@ -0,0 +1,8 @@
+{
+ "luci-app-frps": {
+ "description": "Grant access to LuCI app frps",
+ "write": {
+ "uci": ["frps"]
+ }
+ }
+}