From a468cde26b009547dddbc7678b983ad214a2b40b Mon Sep 17 00:00:00 2001 From: okxlin <61420215+okxlin@users.noreply.github.com> Date: Fri, 4 Aug 2023 10:50:49 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E6=B7=BB=E5=8A=A0filebrowser=E3=80=81frpc?= =?UTF-8?q?=E3=80=81frps=E3=80=81home-assistant=E3=80=81nextcloud=E3=80=81?= =?UTF-8?q?hexo=E3=80=81zfile=20(#299)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/filebrowser/2.24.1/data.yml | 17 + .../filebrowser/2.24.1/data/.filebrowser.json | 8 + apps/filebrowser/2.24.1/data/database.db | 0 apps/filebrowser/2.24.1/docker-compose.yml | 21 + apps/filebrowser/README.md | 44 + apps/filebrowser/data.yml | 20 + apps/filebrowser/logo.png | Bin 0 -> 7872 bytes apps/frpc/0.51.2/data.yml | 9 + apps/frpc/0.51.2/data/frpc.ini | 9 + apps/frpc/0.51.2/data/frpc_full.ini | 365 ++++++ apps/frpc/0.51.2/data/frps.ini | 2 + apps/frpc/0.51.2/data/frps_full.ini | 168 +++ apps/frpc/0.51.2/docker-compose.yml | 11 + apps/frpc/README.md | 1151 +++++++++++++++++ apps/frpc/data.yml | 20 + apps/frpc/logo.png | Bin 0 -> 26073 bytes apps/frps/0.51.2/data.yml | 9 + apps/frps/0.51.2/data/frpc.ini | 9 + apps/frps/0.51.2/data/frpc_full.ini | 365 ++++++ apps/frps/0.51.2/data/frps.ini | 2 + apps/frps/0.51.2/data/frps_full.ini | 168 +++ apps/frps/0.51.2/docker-compose.yml | 11 + apps/frps/README.md | 1151 +++++++++++++++++ apps/frps/data.yml | 20 + apps/frps/logo.png | Bin 0 -> 26073 bytes apps/hexo/README.md | 102 ++ apps/hexo/data.yml | 20 + apps/hexo/logo.png | Bin 0 -> 5336 bytes apps/hexo/stable-23-07-01/data.yml | 24 + apps/hexo/stable-23-07-01/docker-compose.yml | 24 + .../2023.8.0.dev20230723/data.yml | 10 + .../2023.8.0.dev20230723/docker-compose.yml | 13 + apps/home-assistant/README.md | 33 + apps/home-assistant/data.yml | 20 + apps/home-assistant/logo.png | Bin 0 -> 7060 bytes apps/nextcloud/27.0.1/data.yml | 12 + apps/nextcloud/27.0.1/docker-compose.yml | 23 + apps/nextcloud/README.md | 163 +++ apps/nextcloud/data.yml | 20 + apps/nextcloud/logo.png | Bin 0 -> 8999 bytes apps/zfile/4.1.5/data.yml | 17 + apps/zfile/4.1.5/docker-compose.yml | 20 + apps/zfile/README.md | 71 + apps/zfile/data.yml | 20 + apps/zfile/logo.png | Bin 0 -> 5737 bytes 45 files changed, 4172 insertions(+) create mode 100644 apps/filebrowser/2.24.1/data.yml create mode 100644 apps/filebrowser/2.24.1/data/.filebrowser.json create mode 100644 apps/filebrowser/2.24.1/data/database.db create mode 100644 apps/filebrowser/2.24.1/docker-compose.yml create mode 100644 apps/filebrowser/README.md create mode 100644 apps/filebrowser/data.yml create mode 100644 apps/filebrowser/logo.png create mode 100644 apps/frpc/0.51.2/data.yml create mode 100644 apps/frpc/0.51.2/data/frpc.ini create mode 100644 apps/frpc/0.51.2/data/frpc_full.ini create mode 100644 apps/frpc/0.51.2/data/frps.ini create mode 100644 apps/frpc/0.51.2/data/frps_full.ini create mode 100644 apps/frpc/0.51.2/docker-compose.yml create mode 100644 apps/frpc/README.md create mode 100644 apps/frpc/data.yml create mode 100644 apps/frpc/logo.png create mode 100644 apps/frps/0.51.2/data.yml create mode 100644 apps/frps/0.51.2/data/frpc.ini create mode 100644 apps/frps/0.51.2/data/frpc_full.ini create mode 100644 apps/frps/0.51.2/data/frps.ini create mode 100644 apps/frps/0.51.2/data/frps_full.ini create mode 100644 apps/frps/0.51.2/docker-compose.yml create mode 100644 apps/frps/README.md create mode 100644 apps/frps/data.yml create mode 100644 apps/frps/logo.png create mode 100644 apps/hexo/README.md create mode 100644 apps/hexo/data.yml create mode 100644 apps/hexo/logo.png create mode 100644 apps/hexo/stable-23-07-01/data.yml create mode 100644 apps/hexo/stable-23-07-01/docker-compose.yml create mode 100644 apps/home-assistant/2023.8.0.dev20230723/data.yml create mode 100644 apps/home-assistant/2023.8.0.dev20230723/docker-compose.yml create mode 100644 apps/home-assistant/README.md create mode 100644 apps/home-assistant/data.yml create mode 100644 apps/home-assistant/logo.png create mode 100644 apps/nextcloud/27.0.1/data.yml create mode 100644 apps/nextcloud/27.0.1/docker-compose.yml create mode 100644 apps/nextcloud/README.md create mode 100644 apps/nextcloud/data.yml create mode 100644 apps/nextcloud/logo.png create mode 100644 apps/zfile/4.1.5/data.yml create mode 100644 apps/zfile/4.1.5/docker-compose.yml create mode 100644 apps/zfile/README.md create mode 100644 apps/zfile/data.yml create mode 100644 apps/zfile/logo.png diff --git a/apps/filebrowser/2.24.1/data.yml b/apps/filebrowser/2.24.1/data.yml new file mode 100644 index 000000000..cd96ae14e --- /dev/null +++ b/apps/filebrowser/2.24.1/data.yml @@ -0,0 +1,17 @@ +additionalProperties: + formFields: + - default: 40071 + edit: true + envKey: PANEL_APP_PORT_HTTP + labelEn: HTTP Port + labelZh: HTTP端口 + required: true + rule: paramPort + type: number + - default: ./data/mnt + edit: true + envKey: MOUNT_PATH + labelEn: Mount folder path + labelZh: 挂载文件夹路径 + required: true + type: text diff --git a/apps/filebrowser/2.24.1/data/.filebrowser.json b/apps/filebrowser/2.24.1/data/.filebrowser.json new file mode 100644 index 000000000..fbcf6a1a7 --- /dev/null +++ b/apps/filebrowser/2.24.1/data/.filebrowser.json @@ -0,0 +1,8 @@ +{ + "port": 80, + "baseURL": "", + "address": "", + "log": "stdout", + "database": "/database/filebrowser.db", + "root": "/srv" + } \ No newline at end of file diff --git a/apps/filebrowser/2.24.1/data/database.db b/apps/filebrowser/2.24.1/data/database.db new file mode 100644 index 000000000..e69de29bb diff --git a/apps/filebrowser/2.24.1/docker-compose.yml b/apps/filebrowser/2.24.1/docker-compose.yml new file mode 100644 index 000000000..fe4f611a3 --- /dev/null +++ b/apps/filebrowser/2.24.1/docker-compose.yml @@ -0,0 +1,21 @@ +version: '3' +services: + filebrowser: + container_name: ${CONTAINER_NAME} + restart: always + networks: + - 1panel-network + ports: + - "${PANEL_APP_PORT_HTTP}:80" + volumes: + - "${MOUNT_PATH}:/srv" + - "./data/database.db:/database.db" + - "./data/.filebrowser.json:/.filebrowser.json" + user: "${UID}:${GID}" + image: filebrowser/filebrowser:v2.24.1 + labels: + createdBy: "Apps" + +networks: + 1panel-network: + external: true diff --git a/apps/filebrowser/README.md b/apps/filebrowser/README.md new file mode 100644 index 000000000..31d513480 --- /dev/null +++ b/apps/filebrowser/README.md @@ -0,0 +1,44 @@ +# 使用说明 + +- 默认账户密码 + +``` +username:admin +password:admin +``` + +# 原始相关 + +
+
+
iHZ7G1;0%M~SozY&M zDedT*cC)9QGC7?}gve<37NbVY)mGR(?yhL4?xz`7AXvz5sq=CL``fbaLf|Oi2&E`l z0bO82(COZU)cTobp*1~IA}#^Y4OFD cf} z0>y}bON74~pC#NP@d&NaN`bbJq wi72!zR_}bl#8C+l5BGuQ;Fic z;~nY@!50c;2ul!Kw@wi_D{JQwD&Q>O9AJ&Y)g`ffsS$F2y&v{`8@7F$bJ5(dLR!0n zpjZX01?J$4&C65)=a;z-YI}x?g;Vc)5H1Gbe+&HGqHa1L{WW~_UlkvFos5e*wXnJ( z+&f@-!!>tMP<13MOf73VBBUcVjyUTToVuo$(afJstYXE21~)#~%eNjXvwV(w8byZr zpL$B-i7G&A$FPll;QMW#A3u0ycy`J;`;>BRYgh(Uo%K<` gxyv99kla9I1(%>$u_?iw_g3yZ_WJR3) z9VTUm(%j!j`G$cf0|R|M?$u*S!j38R-;rI0rerbm$hiVkxgr_kUen2CD~gebzDx zJRHK8B;lK5nb^w;dKN<6`Q5{b<^2{;7YnAyS1{1o30ku=Nw`uejs%j}@KwRRf~%aZ zBSi68fma|Lh082dz@QbLFq-Q{_+qV=xko^}kCAvkCkAESnFtpsSce Nn7BKS>>1HP!C+0Xv=?eAKd -}l9m7ql~IVAFlwOQ;TAq=%`E~=kuI$$ps1>VTGRnszYBY(WN5E> zJCv5X_pvDh>4 8bP_3wTax_EE?Fl-MxRWuLt6IN~5Oyu0khhrQG$B z-C!yZb`z+S-bTWxq>PmdE?V_;r< PoqkjMKg|-1f)v8o zotI`Y0;N#aG6zuBFk} C0Zv-K#A; zGXO99gyQNy5-xm+Gm%S|E@sP?=ZNE&FboeUY5}ZO% cE8xia z&T$Nc&(5v$)p(|?k}Qa#t$Tf~$8#{IZjV#n#XXX8b}Ibv@cFQ72rmAj;`Ybf^MC7? z7!F^xnEvOVr `2~OJrtx;dx8Y ztp`Lso`W%C`l!;7#N3xQIm(25$tW&3W+{x;;hLW~aj#p_!@Btqhxaw;En6ZZBo;;+ znr%ZNkL@b5sXt_I73O!s(Tm)sLEPji4Sx#!`1iEV^ZWrbYd*A6pkXKx-e5K7g()8? zg}iv}BA2 +!p%W4rgUk%OHl&CMh2e5*K3fYWBR) z95lf{+a|raQRik9uPPR}L@Qq1U8cLIJmC_wAK#7$cZubzN^?DKBf|f$iaftJ4(W*% zg%hnc+-?=OD@#RUHdw{+Dqy)X%t0vP)^>v;?9}k6wcIa?ZR$6OBYHf)3+m8f$sW&t z4E*Hp$rWDEo?PJt?a38h(4Ji31?|ZdUeKOg;RWr<6<*MuT;T=n$rWDEo?PJt?a38h z(4Ji31?|ZdUeKOg;RWr<6<*MuT;T=n$rWDEo?PJt?a38h(4Ji31?|ZdUeKOg;RWr< z6<*MuT;T=n$rWDEo?PJt?a38h(4Ji31?|ZdUeKOg;RWr<6<*MuT;T=n$rWDEo?PJt z?a38h(4Ji31?|ZdUeKOg;RWr<6<*MuT;T=n$rWDEo?PJt?a38h(4Ji31?|ZdUeKOg z;RWr<6<*MuT;T=n$rWDEo?PJt?a38h(4Ji31?|ZdUeKOg;RWr<6<*MuT;T=n$rWDE zo?PJt?a38h(4Ji31?|ZdUeKOg;RWr<6<*MuT;T=n$rWDEo?PJt?a38h(4Ji31?|Zd eUeKOg@qYnD1-H(P$||G)0000 " "var1= " to the additional parameters. +# oidc_additional_audience = https://dev.auth.com/api/v2/ +# oidc_additional_var1 = foobar + +# set admin address for control frpc's action by http api such as reload +admin_addr = 127.0.0.1 +admin_port = 7400 +admin_user = admin +admin_pwd = admin +# Admin assets directory. By default, these assets are bundled with frpc. +# assets_dir = ./static + +# connections will be established in advance, default value is zero +pool_count = 5 + +# if tcp stream multiplexing is used, default is true, it must be same with frps +# tcp_mux = true + +# specify keep alive interval for tcp mux. +# only valid if tcp_mux is true. +# tcp_mux_keepalive_interval = 60 + +# your proxy name will be changed to {user}.{proxy} +user = your_name + +# decide if exit program when first login failed, otherwise continuous relogin to frps +# default is true +login_fail_exit = true + +# communication protocol used to connect to server +# supports tcp, kcp, quic and websocket now, default is tcp +protocol = tcp + +# set client binding ip when connect server, default is empty. +# only when protocol = tcp or websocket, the value will be used. +connect_server_local_ip = 0.0.0.0 + +# quic protocol options +# quic_keepalive_period = 10 +# quic_max_idle_timeout = 30 +# quic_max_incoming_streams = 100000 + +# if tls_enable is true, frpc will connect frps by tls +tls_enable = true + +# tls_cert_file = client.crt +# tls_key_file = client.key +# tls_trusted_ca_file = ca.crt +# tls_server_name = example.com + +# specify a dns server, so frpc will use this instead of default one +# dns_server = 8.8.8.8 + +# proxy names you want to start separated by ',' +# default is empty, means all proxies +# start = ssh,dns + +# heartbeat configure, it's not recommended to modify the default value +# The default value of heartbeat_interval is 10 and heartbeat_timeout is 90. Set negative value +# to disable it. +# heartbeat_interval = 30 +# heartbeat_timeout = 90 + +# additional meta info for client +meta_var1 = 123 +meta_var2 = 234 + +# specify udp packet size, unit is byte. If not set, the default value is 1500. +# This parameter should be same between client and server. +# It affects the udp and sudp proxy. +udp_packet_size = 1500 + +# include other config files for proxies. +# includes = ./confd/*.ini + +# By default, frpc will connect frps with first custom byte if tls is enabled. +# If DisableCustomTLSFirstByte is true, frpc will not send that custom byte. +disable_custom_tls_first_byte = false + +# Enable golang pprof handlers in admin listener. +# Admin port must be set first. +pprof_enable = false + +# 'ssh' is the unique proxy name +# if user in [common] section is not empty, it will be changed to {user}.{proxy} such as 'your_name.ssh' +[ssh] +# tcp | udp | http | https | stcp | xtcp, default is tcp +type = tcp +local_ip = 127.0.0.1 +local_port = 22 +# limit bandwidth for this proxy, unit is KB and MB +bandwidth_limit = 1MB +# where to limit bandwidth, can be 'client' or 'server', default is 'client' +bandwidth_limit_mode = client +# true or false, if true, messages between frps and frpc will be encrypted, default is false +use_encryption = false +# if true, message will be compressed +use_compression = false +# remote port listen by frps +remote_port = 6001 +# frps will load balancing connections for proxies in same group +group = test_group +# group should have same group key +group_key = 123456 +# enable health check for the backend service, it support 'tcp' and 'http' now +# frpc will connect local service's port to detect it's healthy status +health_check_type = tcp +# health check connection timeout +health_check_timeout_s = 3 +# if continuous failed in 3 times, the proxy will be removed from frps +health_check_max_failed = 3 +# every 10 seconds will do a health check +health_check_interval_s = 10 +# additional meta info for each proxy +meta_var1 = 123 +meta_var2 = 234 + +[ssh_random] +type = tcp +local_ip = 127.0.0.1 +local_port = 22 +# if remote_port is 0, frps will assign a random port for you +remote_port = 0 + +# if you want to expose multiple ports, add 'range:' prefix to the section name +# frpc will generate multiple proxies such as 'tcp_port_6010', 'tcp_port_6011' and so on. +[range:tcp_port] +type = tcp +local_ip = 127.0.0.1 +local_port = 6010-6020,6022,6024-6028 +remote_port = 6010-6020,6022,6024-6028 +use_encryption = false +use_compression = false + +[dns] +type = udp +local_ip = 114.114.114.114 +local_port = 53 +remote_port = 6002 +use_encryption = false +use_compression = false + +[range:udp_port] +type = udp +local_ip = 127.0.0.1 +local_port = 6010-6020 +remote_port = 6010-6020 +use_encryption = false +use_compression = false + +# Resolve your domain names to [server_addr] so you can use http://web01.yourdomain.com to browse web01 and http://web02.yourdomain.com to browse web02 +[web01] +type = http +local_ip = 127.0.0.1 +local_port = 80 +use_encryption = false +use_compression = true +# http username and password are safety certification for http protocol +# if not set, you can access this custom_domains without certification +http_user = admin +http_pwd = admin +# if domain for frps is frps.com, then you can access [web01] proxy by URL http://web01.frps.com +subdomain = web01 +custom_domains = web01.yourdomain.com +# locations is only available for http type +locations = /,/pic +# route requests to this service if http basic auto user is abc +# route_by_http_user = abc +host_header_rewrite = example.com +# params with prefix "header_" will be used to update http request headers +header_X-From-Where = frp +health_check_type = http +# frpc will send a GET http request '/status' to local http service +# http service is alive when it return 2xx http response code +health_check_url = /status +health_check_interval_s = 10 +health_check_max_failed = 3 +health_check_timeout_s = 3 + +[web02] +type = https +local_ip = 127.0.0.1 +local_port = 8000 +use_encryption = false +use_compression = false +subdomain = web01 +custom_domains = web02.yourdomain.com +# if not empty, frpc will use proxy protocol to transfer connection info to your local service +# v1 or v2 or empty +proxy_protocol_version = v2 + +[plugin_unix_domain_socket] +type = tcp +remote_port = 6003 +# if plugin is defined, local_ip and local_port is useless +# plugin will handle connections got from frps +plugin = unix_domain_socket +# params with prefix "plugin_" that plugin needed +plugin_unix_path = /var/run/docker.sock + +[plugin_http_proxy] +type = tcp +remote_port = 6004 +plugin = http_proxy +plugin_http_user = abc +plugin_http_passwd = abc + +[plugin_socks5] +type = tcp +remote_port = 6005 +plugin = socks5 +plugin_user = abc +plugin_passwd = abc + +[plugin_static_file] +type = tcp +remote_port = 6006 +plugin = static_file +plugin_local_path = /var/www/blog +plugin_strip_prefix = static +plugin_http_user = abc +plugin_http_passwd = abc + +[plugin_https2http] +type = https +custom_domains = test.yourdomain.com +plugin = https2http +plugin_local_addr = 127.0.0.1:80 +plugin_crt_path = ./server.crt +plugin_key_path = ./server.key +plugin_host_header_rewrite = 127.0.0.1 +plugin_header_X-From-Where = frp + +[plugin_https2https] +type = https +custom_domains = test.yourdomain.com +plugin = https2https +plugin_local_addr = 127.0.0.1:443 +plugin_crt_path = ./server.crt +plugin_key_path = ./server.key +plugin_host_header_rewrite = 127.0.0.1 +plugin_header_X-From-Where = frp + +[plugin_http2https] +type = http +custom_domains = test.yourdomain.com +plugin = http2https +plugin_local_addr = 127.0.0.1:443 +plugin_host_header_rewrite = 127.0.0.1 +plugin_header_X-From-Where = frp + +[secret_tcp] +# If the type is secret tcp, remote_port is useless +# Who want to connect local port should deploy another frpc with stcp proxy and role is visitor +type = stcp +# sk used for authentication for visitors +sk = abcdefg +local_ip = 127.0.0.1 +local_port = 22 +use_encryption = false +use_compression = false + +# user of frpc should be same in both stcp server and stcp visitor +[secret_tcp_visitor] +# frpc role visitor -> frps -> frpc role server +role = visitor +type = stcp +# the server name you want to visitor +server_name = secret_tcp +sk = abcdefg +# connect this address to visitor stcp server +bind_addr = 127.0.0.1 +bind_port = 9000 +use_encryption = false +use_compression = false + +[p2p_tcp] +type = xtcp +sk = abcdefg +local_ip = 127.0.0.1 +local_port = 22 +use_encryption = false +use_compression = false + +[p2p_tcp_visitor] +role = visitor +type = xtcp +server_name = p2p_tcp +sk = abcdefg +bind_addr = 127.0.0.1 +bind_port = 9001 +use_encryption = false +use_compression = false + +[tcpmuxhttpconnect] +type = tcpmux +multiplexer = httpconnect +local_ip = 127.0.0.1 +local_port = 10701 +custom_domains = tunnel1 +# route_by_http_user = user1 diff --git a/apps/frpc/0.51.2/data/frps.ini b/apps/frpc/0.51.2/data/frps.ini new file mode 100644 index 000000000..229567a9d --- /dev/null +++ b/apps/frpc/0.51.2/data/frps.ini @@ -0,0 +1,2 @@ +[common] +bind_port = 7000 diff --git a/apps/frpc/0.51.2/data/frps_full.ini b/apps/frpc/0.51.2/data/frps_full.ini new file mode 100644 index 000000000..2d5e08e17 --- /dev/null +++ b/apps/frpc/0.51.2/data/frps_full.ini @@ -0,0 +1,168 @@ +# [common] is integral section +[common] +# A literal address or host name for IPv6 must be enclosed +# in square brackets, as in "[::1]:80", "[ipv6-host]:http" or "[ipv6-host%zone]:80" +# For single "bind_addr" field, no need square brackets, like "bind_addr = ::". +bind_addr = 0.0.0.0 +bind_port = 7000 + +# udp port to help make udp hole to penetrate nat +bind_udp_port = 7001 + +# udp port used for kcp protocol, it can be same with 'bind_port'. +# if not set, kcp is disabled in frps. +kcp_bind_port = 7000 + +# udp port used for quic protocol. +# if not set, quic is disabled in frps. +# quic_bind_port = 7002 +# quic protocol options +# quic_keepalive_period = 10 +# quic_max_idle_timeout = 30 +# quic_max_incoming_streams = 100000 + +# specify which address proxy will listen for, default value is same with bind_addr +# proxy_bind_addr = 127.0.0.1 + +# if you want to support virtual host, you must set the http port for listening (optional) +# Note: http port and https port can be same with bind_port +vhost_http_port = 80 +vhost_https_port = 443 + +# response header timeout(seconds) for vhost http server, default is 60s +# vhost_http_timeout = 60 + +# tcpmux_httpconnect_port specifies the port that the server listens for TCP +# HTTP CONNECT requests. If the value is 0, the server will not multiplex TCP +# requests on one single port. If it's not - it will listen on this value for +# HTTP CONNECT requests. By default, this value is 0. +# tcpmux_httpconnect_port = 1337 + +# If tcpmux_passthrough is true, frps won't do any update on traffic. +# tcpmux_passthrough = false + +# set dashboard_addr and dashboard_port to view dashboard of frps +# dashboard_addr's default value is same with bind_addr +# dashboard is available only if dashboard_port is set +dashboard_addr = 0.0.0.0 +dashboard_port = 7500 + +# dashboard user and passwd for basic auth protect +dashboard_user = admin +dashboard_pwd = admin + +# dashboard TLS mode +dashboard_tls_mode = false +# dashboard_tls_cert_file = server.crt +# dashboard_tls_key_file = server.key + +# enable_prometheus will export prometheus metrics on {dashboard_addr}:{dashboard_port} in /metrics api. +enable_prometheus = true + +# dashboard assets directory(only for debug mode) +# assets_dir = ./static + +# console or real logFile path like ./frps.log +log_file = ./frps.log + +# trace, debug, info, warn, error +log_level = info + +log_max_days = 3 + +# disable log colors when log_file is console, default is false +disable_log_color = false + +# DetailedErrorsToClient defines whether to send the specific error (with debug info) to frpc. By default, this value is true. +detailed_errors_to_client = true + +# authentication_method specifies what authentication method to use authenticate frpc with frps. +# If "token" is specified - token will be read into login message. +# If "oidc" is specified - OIDC (Open ID Connect) token will be issued using OIDC settings. By default, this value is "token". +authentication_method = token + +# authenticate_heartbeats specifies whether to include authentication token in heartbeats sent to frps. By default, this value is false. +authenticate_heartbeats = false + +# AuthenticateNewWorkConns specifies whether to include authentication token in new work connections sent to frps. By default, this value is false. +authenticate_new_work_conns = false + +# auth token +token = 12345678 + +# oidc_issuer specifies the issuer to verify OIDC tokens with. +# By default, this value is "". +oidc_issuer = + +# oidc_audience specifies the audience OIDC tokens should contain when validated. +# By default, this value is "". +oidc_audience = + +# oidc_skip_expiry_check specifies whether to skip checking if the OIDC token is expired. +# By default, this value is false. +oidc_skip_expiry_check = false + +# oidc_skip_issuer_check specifies whether to skip checking if the OIDC token's issuer claim matches the issuer specified in OidcIssuer. +# By default, this value is false. +oidc_skip_issuer_check = false + +# heartbeat configure, it's not recommended to modify the default value +# the default value of heartbeat_timeout is 90. Set negative value to disable it. +# heartbeat_timeout = 90 + +# user_conn_timeout configure, it's not recommended to modify the default value +# the default value of user_conn_timeout is 10 +# user_conn_timeout = 10 + +# only allow frpc to bind ports you list, if you set nothing, there won't be any limit +allow_ports = 2000-3000,3001,3003,4000-50000 + +# pool_count in each proxy will change to max_pool_count if they exceed the maximum value +max_pool_count = 5 + +# max ports can be used for each client, default value is 0 means no limit +max_ports_per_client = 0 + +# tls_only specifies whether to only accept TLS-encrypted connections. By default, the value is false. +tls_only = false + +# tls_cert_file = server.crt +# tls_key_file = server.key +# tls_trusted_ca_file = ca.crt + +# if subdomain_host is not empty, you can set subdomain when type is http or https in frpc's configure file +# when subdomain is test, the host used by routing is test.frps.com +subdomain_host = frps.com + +# if tcp stream multiplexing is used, default is true +# tcp_mux = true + +# specify keep alive interval for tcp mux. +# only valid if tcp_mux is true. +# tcp_mux_keepalive_interval = 60 + +# tcp_keepalive specifies the interval between keep-alive probes for an active network connection between frpc and frps. +# If negative, keep-alive probes are disabled. +# tcp_keepalive = 7200 + +# custom 404 page for HTTP requests +# custom_404_page = /path/to/404.html + +# specify udp packet size, unit is byte. If not set, the default value is 1500. +# This parameter should be same between client and server. +# It affects the udp and sudp proxy. +udp_packet_size = 1500 + +# Enable golang pprof handlers in dashboard listener. +# Dashboard port must be set first +pprof_enable = false + +[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 diff --git a/apps/frpc/0.51.2/docker-compose.yml b/apps/frpc/0.51.2/docker-compose.yml new file mode 100644 index 000000000..2537e0248 --- /dev/null +++ b/apps/frpc/0.51.2/docker-compose.yml @@ -0,0 +1,11 @@ +version: "3" +services: + frpc: + container_name: ${CONTAINER_NAME} + restart: always + network_mode: "host" + volumes: + - "${CONFIG_FILE_PATH}:/etc/frp/frpc.ini" + image: "snowdreamtech/frpc:0.51.2" + labels: + createdBy: "Apps" diff --git a/apps/frpc/README.md b/apps/frpc/README.md new file mode 100644 index 000000000..4aeec4f20 --- /dev/null +++ b/apps/frpc/README.md @@ -0,0 +1,1151 @@ +# frp + +[](https://circleci.com/gh/fatedier/frp) +[](https://github.com/fatedier/frp/releases) + +[README](README.md) | [中文文档](README_zh.md) + + Gold Sponsors
+ + + + + +## What is frp? + +frp is a fast reverse proxy that allows you to expose a local server located behind a NAT or firewall to the Internet. It currently supports **TCP** and **UDP**, as well as **HTTP** and **HTTPS** protocols, enabling requests to be forwarded to internal services via domain name. + +frp also offers a P2P connect mode. + +## Table of Contents + + + +- [frp](#frp) + - [What is frp?](#what-is-frp) + - [Table of Contents](#table-of-contents) + - [Development Status](#development-status) + - [Architecture](#architecture) + - [Example Usage](#example-usage) + - [Access your computer in a LAN network via SSH](#access-your-computer-in-a-lan-network-via-ssh) + - [Accessing Internal Web Services with Custom Domains in LAN](#accessing-internal-web-services-with-custom-domains-in-lan) + - [Forward DNS query requests](#forward-dns-query-requests) + - [Forward Unix Domain Socket](#forward-unix-domain-socket) + - [Expose a simple HTTP file server](#expose-a-simple-http-file-server) + - [Enable HTTPS for a local HTTP(S) service](#enable-https-for-a-local-https-service) + - [Expose your service privately](#expose-your-service-privately) + - [P2P Mode](#p2p-mode) + - [Features](#features) + - [Configuration Files](#configuration-files) + - [Using Environment Variables](#using-environment-variables) + - [Split Configures Into Different Files](#split-configures-into-different-files) + - [Dashboard](#dashboard) + - [Admin UI](#admin-ui) + - [Monitor](#monitor) + - [Prometheus](#prometheus) + - [Authenticating the Client](#authenticating-the-client) + - [Token Authentication](#token-authentication) + - [OIDC Authentication](#oidc-authentication) + - [Encryption and Compression](#encryption-and-compression) + - [TLS](#tls) + - [Hot-Reloading frpc configuration](#hot-reloading-frpc-configuration) + - [Get proxy status from client](#get-proxy-status-from-client) + - [Only allowing certain ports on the server](#only-allowing-certain-ports-on-the-server) + - [Port Reuse](#port-reuse) + - [Bandwidth Limit](#bandwidth-limit) + - [For Each Proxy](#for-each-proxy) + - [TCP Stream Multiplexing](#tcp-stream-multiplexing) + - [Support KCP Protocol](#support-kcp-protocol) + - [Support QUIC Protocol](#support-quic-protocol) + - [Connection Pooling](#connection-pooling) + - [Load balancing](#load-balancing) + - [Service Health Check](#service-health-check) + - [Rewriting the HTTP Host Header](#rewriting-the-http-host-header) + - [Setting other HTTP Headers](#setting-other-http-headers) + - [Get Real IP](#get-real-ip) + - [HTTP X-Forwarded-For](#http-x-forwarded-for) + - [Proxy Protocol](#proxy-protocol) + - [Require HTTP Basic Auth (Password) for Web Services](#require-http-basic-auth-password-for-web-services) + - [Custom Subdomain Names](#custom-subdomain-names) + - [URL Routing](#url-routing) + - [TCP Port Multiplexing](#tcp-port-multiplexing) + - [Connecting to frps via HTTP PROXY](#connecting-to-frps-via-http-proxy) + - [Range ports mapping](#range-ports-mapping) + - [Client Plugins](#client-plugins) + - [Server Manage Plugins](#server-manage-plugins) + - [Development Plan](#development-plan) + - [Contributing](#contributing) + - [Donation](#donation) + - [GitHub Sponsors](#github-sponsors) + - [PayPal](#paypal) + + + +## Development Status + +frp is currently under development. You can try the latest release version in the `master` branch, or use the `dev` branch to access the version currently in development. + +We are currently working on version 2 and attempting to perform some code refactoring and improvements. However, please note that it will not be compatible with version 1. + +We will transition from version 0 to version 1 at the appropriate time and will only accept bug fixes and improvements, rather than big feature requests. + +## Architecture + + + +## Example Usage + +To begin, download the latest program for your operating system and architecture from the [Release](https://github.com/fatedier/frp/releases) page. + +Next, place the `frps` binary and `frps.ini` configuration file on Server A, which has a public IP address. + +Finally, place the `frpc` binary and `frpc.ini` configuration file on Server B, which is located on a LAN that cannot be directly accessed from the public internet. + +### Access your computer in a LAN network via SSH + +1. Modify `frps.ini` on server A by setting the `bind_port` for frp clients to connect to: + + ```ini + # frps.ini + [common] + bind_port = 7000 + ``` + +2. Start `frps` on server A: + + `./frps -c ./frps.ini` + +3. Modify `frpc.ini` on server B and set the `server_addr` field to the public IP address of your frps server: + + ```ini + # frpc.ini + [common] + server_addr = x.x.x.x + server_port = 7000 + + [ssh] + type = tcp + local_ip = 127.0.0.1 + local_port = 22 + remote_port = 6000 + ``` + +Note that the `local_port` (listened on the client) and `remote_port` (exposed on the server) are used for traffic going in and out of the frp system, while the `server_port` is used for communication between frps and frpc. + +4. Start `frpc` on server B: + + `./frpc -c ./frpc.ini` + +5. To access server B from another machine through server A via SSH (assuming the username is `test`), use the following command: + + `ssh -oPort=6000 test@x.x.x.x` + +### Accessing Internal Web Services with Custom Domains in LAN + +Sometimes we need to expose a local web service behind a NAT network to others for testing purposes with our own domain name. + +Unfortunately, we cannot resolve a domain name to a local IP. However, we can use frp to expose an HTTP(S) service. + +1. Modify `frps.ini` and set the HTTP port for vhost to 8080: + + ```ini + # frps.ini + [common] + bind_port = 7000 + vhost_http_port = 8080 + ``` + +2. Start `frps`: + + `./frps -c ./frps.ini` + +3. Modify `frpc.ini` and set `server_addr` to the IP address of the remote frps server. Specify the `local_port` of your web service: + + ```ini + # frpc.ini + [common] + server_addr = x.x.x.x + server_port = 7000 + + [web] + type = http + local_port = 80 + custom_domains = www.example.com + ``` + +4. Start `frpc`: + + `./frpc -c ./frpc.ini` + +5. Map the A record of `www.example.com` to either the public IP of the remote frps server or a CNAME record pointing to your original domain. + +6. Visit your local web service using url `http://www.example.com:8080`. + +### Forward DNS query requests + +1. Modify `frps.ini`: + + ```ini + # frps.ini + [common] + bind_port = 7000 + ``` + +2. Start `frps`: + + `./frps -c ./frps.ini` + +3. Modify `frpc.ini` and set `server_addr` to the IP address of the remote frps server. Forward DNS query requests to the Google Public DNS server `8.8.8.8:53`: + + ```ini + # frpc.ini + [common] + server_addr = x.x.x.x + server_port = 7000 + + [dns] + type = udp + local_ip = 8.8.8.8 + local_port = 53 + remote_port = 6000 + ``` + +4. Start frpc: + + `./frpc -c ./frpc.ini` + +5. Test DNS resolution using the `dig` command: + + `dig @x.x.x.x -p 6000 www.google.com` + +### Forward Unix Domain Socket + +Expose a Unix domain socket (e.g. the Docker daemon socket) as TCP. + +Configure `frps` as above. + +1. Start `frpc` with the following configuration: + + ```ini + # frpc.ini + [common] + server_addr = x.x.x.x + server_port = 7000 + + [unix_domain_socket] + type = tcp + remote_port = 6000 + plugin = unix_domain_socket + plugin_unix_path = /var/run/docker.sock + ``` + +2. Test the configuration by getting the docker version using `curl`: + + `curl http://x.x.x.x:6000/version` + +### Expose a simple HTTP file server + +Expose a simple HTTP file server to access files stored in the LAN from the public Internet. + +Configure `frps` as described above, then: + +1. Start `frpc` with the following configuration: + + ```ini + # frpc.ini + [common] + server_addr = x.x.x.x + server_port = 7000 + + [test_static_file] + type = tcp + remote_port = 6000 + plugin = static_file + plugin_local_path = /tmp/files + plugin_strip_prefix = static + plugin_http_user = abc + plugin_http_passwd = abc + ``` + +2. Visit `http://x.x.x.x:6000/static/` from your browser and specify correct username and password to view files in `/tmp/files` on the `frpc` machine. + +### Enable HTTPS for a local HTTP(S) service + +You may substitute `https2https` for the plugin, and point the `plugin_local_addr` to a HTTPS endpoint. + +1. Start `frpc` with the following configuration: + + ```ini + # frpc.ini + [common] + server_addr = x.x.x.x + server_port = 7000 + + [test_https2http] + type = https + custom_domains = test.example.com + + plugin = https2http + plugin_local_addr = 127.0.0.1:80 + plugin_crt_path = ./server.crt + plugin_key_path = ./server.key + plugin_host_header_rewrite = 127.0.0.1 + plugin_header_X-From-Where = frp + ``` + +2. Visit `https://test.example.com`. + +### Expose your service privately + +To mitigate risks associated with exposing certain services directly to the public network, STCP (Secret TCP) mode requires a preshared key to be used for access to the service from other clients. + +Configure `frps` same as above. + +1. Start `frpc` on machine B with the following config. This example is for exposing the SSH service (port 22), and note the `sk` field for the preshared key, and that the `remote_port` field is removed here: + + ```ini + # frpc.ini + [common] + server_addr = x.x.x.x + server_port = 7000 + + [secret_ssh] + type = stcp + sk = abcdefg + local_ip = 127.0.0.1 + local_port = 22 + ``` + +2. Start another `frpc` (typically on another machine C) with the following config to access the SSH service with a security key (`sk` field): + + ```ini + # frpc.ini + [common] + server_addr = x.x.x.x + server_port = 7000 + + [secret_ssh_visitor] + type = stcp + role = visitor + server_name = secret_ssh + sk = abcdefg + bind_addr = 127.0.0.1 + bind_port = 6000 + ``` + +3. On machine C, connect to SSH on machine B, using this command: + + `ssh -oPort=6000 127.0.0.1` + +### P2P Mode + +**xtcp** is designed to transmit large amounts of data directly between clients. A frps server is still needed, as P2P here only refers to the actual data transmission. + +Note that it may not work with all types of NAT devices. You might want to fallback to stcp if xtcp doesn't work. + +1. In `frps.ini` configure a UDP port for xtcp: + + ```ini + # frps.ini + bind_udp_port = 7001 + ``` + +2. Start `frpc` on machine B, and expose the SSH port. Note that the `remote_port` field is removed: + + ```ini + # frpc.ini + [common] + server_addr = x.x.x.x + server_port = 7000 + + [p2p_ssh] + type = xtcp + sk = abcdefg + local_ip = 127.0.0.1 + local_port = 22 + ``` + +3. Start another `frpc` (typically on another machine C) with the configuration to connect to SSH using P2P mode: + + ```ini + # frpc.ini + [common] + server_addr = x.x.x.x + server_port = 7000 + + [p2p_ssh_visitor] + type = xtcp + role = visitor + server_name = p2p_ssh + sk = abcdefg + bind_addr = 127.0.0.1 + bind_port = 6000 + ``` + +4. On machine C, connect to SSH on machine B, using this command: + + `ssh -oPort=6000 127.0.0.1` + +## Features + +### Configuration Files + +Read the full example configuration files to find out even more features not described here. + +[Full configuration file for frps (Server)](./conf/frps_full.ini) + +[Full configuration file for frpc (Client)](./conf/frpc_full.ini) + +### Using Environment Variables + +Environment variables can be referenced in the configuration file, using Go's standard format: + +```ini +# frpc.ini +[common] +server_addr = {{ .Envs.FRP_SERVER_ADDR }} +server_port = 7000 + +[ssh] +type = tcp +local_ip = 127.0.0.1 +local_port = 22 +remote_port = {{ .Envs.FRP_SSH_REMOTE_PORT }} +``` + +With the config above, variables can be passed into `frpc` program like this: + +``` +export FRP_SERVER_ADDR="x.x.x.x" +export FRP_SSH_REMOTE_PORT="6000" +./frpc -c ./frpc.ini +``` + +`frpc` will render configuration file template using OS environment variables. Remember to prefix your reference with `.Envs`. + +### Split Configures Into Different Files + +You can split multiple proxy configs into different files and include them in the main file. + +```ini +# frpc.ini +[common] +server_addr = x.x.x.x +server_port = 7000 +includes=./confd/*.ini +``` + +```ini +# ./confd/test.ini +[ssh] +type = tcp +local_ip = 127.0.0.1 +local_port = 22 +remote_port = 6000 +``` + +### Dashboard + +Check frp's status and proxies' statistics information by Dashboard. + +Configure a port for dashboard to enable this feature: + +```ini +[common] +dashboard_port = 7500 +# dashboard's username and password are both optional +dashboard_user = admin +dashboard_pwd = admin +``` + +Then visit `http://[server_addr]:7500` to see the dashboard, with username and password both being `admin`. + +Additionally, you can use HTTPS port by using your domains wildcard or normal SSL certificate: + +```ini +[common] +dashboard_port = 7500 +# dashboard's username and password are both optional +dashboard_user = admin +dashboard_pwd = admin +dashboard_tls_mode = true +dashboard_tls_cert_file = server.crt +dashboard_tls_key_file = server.key +``` + +Then visit `https://[server_addr]:7500` to see the dashboard in secure HTTPS connection, with username and password both being `admin`. + + + +### Admin UI + +The Admin UI helps you check and manage frpc's configuration. + +Configure an address for admin UI to enable this feature: + +```ini +[common] +admin_addr = 127.0.0.1 +admin_port = 7400 +admin_user = admin +admin_pwd = admin +``` + +Then visit `http://127.0.0.1:7400` to see admin UI, with username and password both being `admin`. + +### Monitor + +When dashboard is enabled, frps will save monitor data in cache. It will be cleared after process restart. + +Prometheus is also supported. + +#### Prometheus + +Enable dashboard first, then configure `enable_prometheus = true` in `frps.ini`. + +`http://{dashboard_addr}/metrics` will provide prometheus monitor data. + +### Authenticating the Client + +There are 2 authentication methods to authenticate frpc with frps. + +You can decide which one to use by configuring `authentication_method` under `[common]` in `frpc.ini` and `frps.ini`. + +Configuring `authenticate_heartbeats = true` under `[common]` will use the configured authentication method to add and validate authentication on every heartbeat between frpc and frps. + +Configuring `authenticate_new_work_conns = true` under `[common]` will do the same for every new work connection between frpc and frps. + +#### Token Authentication + +When specifying `authentication_method = token` under `[common]` in `frpc.ini` and `frps.ini` - token based authentication will be used. + +Make sure to specify the same `token` in the `[common]` section in `frps.ini` and `frpc.ini` for frpc to pass frps validation + +#### OIDC Authentication + +When specifying `authentication_method = oidc` under `[common]` in `frpc.ini` and `frps.ini` - OIDC based authentication will be used. + +OIDC stands for OpenID Connect, and the flow used is called [Client Credentials Grant](https://tools.ietf.org/html/rfc6749#section-4.4). + +To use this authentication type - configure `frpc.ini` and `frps.ini` as follows: + +```ini +# frps.ini +[common] +authentication_method = oidc +oidc_issuer = https://example-oidc-issuer.com/ +oidc_audience = https://oidc-audience.com/.default +``` + +```ini +# frpc.ini +[common] +authentication_method = oidc +oidc_client_id = 98692467-37de-409a-9fac-bb2585826f18 # Replace with OIDC client ID +oidc_client_secret = oidc_secret +oidc_audience = https://oidc-audience.com/.default +oidc_token_endpoint_url = https://example-oidc-endpoint.com/oauth2/v2.0/token +``` + +### Encryption and Compression + +The features are off by default. You can turn on encryption and/or compression: + +```ini +# frpc.ini +[ssh] +type = tcp +local_port = 22 +remote_port = 6000 +use_encryption = true +use_compression = true +``` + +#### TLS + +frp supports the TLS protocol between `frpc` and `frps` since v0.25.0. + +For port multiplexing, frp sends a first byte `0x17` to dial a TLS connection. + +Configure `tls_enable = true` in the `[common]` section to `frpc.ini` to enable this feature. + +To **enforce** `frps` to only accept TLS connections - configure `tls_only = true` in the `[common]` section in `frps.ini`. **This is optional.** + +**`frpc` TLS settings (under the `[common]` section):** +```ini +tls_enable = true +tls_cert_file = certificate.crt +tls_key_file = certificate.key +tls_trusted_ca_file = ca.crt +``` + +**`frps` TLS settings (under the `[common]` section):** +```ini +tls_only = true +tls_enable = true +tls_cert_file = certificate.crt +tls_key_file = certificate.key +tls_trusted_ca_file = ca.crt +``` + +You will need **a root CA cert** and **at least one SSL/TLS certificate**. It **can** be self-signed or regular (such as Let's Encrypt or another SSL/TLS certificate provider). + +If you using `frp` via IP address and not hostname, make sure to set the appropriate IP address in the Subject Alternative Name (SAN) area when generating SSL/TLS Certificates. + +Given an example: + +* Prepare openssl config file. It exists at `/etc/pki/tls/openssl.cnf` in Linux System and `/System/Library/OpenSSL/openssl.cnf` in MacOS, and you can copy it to current path, like `cp /etc/pki/tls/openssl.cnf ./my-openssl.cnf`. If not, you can build it by yourself, like: +``` +cat > my-openssl.cnf << EOF +[ ca ] +default_ca = CA_default +[ CA_default ] +x509_extensions = usr_cert +[ req ] +default_bits = 2048 +default_md = sha256 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca +string_mask = utf8only +[ req_distinguished_name ] +[ req_attributes ] +[ usr_cert ] +basicConstraints = CA:FALSE +nsComment = "OpenSSL Generated Certificate" +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer +[ v3_ca ] +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer +basicConstraints = CA:true +EOF +``` + +* build ca certificates: +``` +openssl genrsa -out ca.key 2048 +openssl req -x509 -new -nodes -key ca.key -subj "/CN=example.ca.com" -days 5000 -out ca.crt +``` + +* build frps certificates: +``` +openssl genrsa -out server.key 2048 + +openssl req -new -sha256 -key server.key \ + -subj "/C=XX/ST=DEFAULT/L=DEFAULT/O=DEFAULT/CN=server.com" \ + -reqexts SAN \ + -config <(cat my-openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:localhost,IP:127.0.0.1,DNS:example.server.com")) \ + -out server.csr + +openssl x509 -req -days 365 -sha256 \ + -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \ + -extfile <(printf "subjectAltName=DNS:localhost,IP:127.0.0.1,DNS:example.server.com") \ + -out server.crt +``` + +* build frpc certificates: +``` +openssl genrsa -out client.key 2048 +openssl req -new -sha256 -key client.key \ + -subj "/C=XX/ST=DEFAULT/L=DEFAULT/O=DEFAULT/CN=client.com" \ + -reqexts SAN \ + -config <(cat my-openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:client.com,DNS:example.client.com")) \ + -out client.csr + +openssl x509 -req -days 365 -sha256 \ + -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial \ + -extfile <(printf "subjectAltName=DNS:client.com,DNS:example.client.com") \ + -out client.crt +``` + +### Hot-Reloading frpc configuration + +The `admin_addr` and `admin_port` fields are required for enabling HTTP API: + +```ini +# frpc.ini +[common] +admin_addr = 127.0.0.1 +admin_port = 7400 +``` + +Then run command `frpc reload -c ./frpc.ini` and wait for about 10 seconds to let `frpc` create or update or remove proxies. + +**Note that parameters in [common] section won't be modified except 'start'.** + +You can run command `frpc verify -c ./frpc.ini` before reloading to check if there are config errors. + +### Get proxy status from client + +Use `frpc status -c ./frpc.ini` to get status of all proxies. The `admin_addr` and `admin_port` fields are required for enabling HTTP API. + +### Only allowing certain ports on the server + +`allow_ports` in `frps.ini` is used to avoid abuse of ports: + +```ini +# frps.ini +[common] +allow_ports = 2000-3000,3001,3003,4000-50000 +``` + +`allow_ports` consists of specific ports or port ranges (lowest port number, dash `-`, highest port number), separated by comma `,`. + +### Port Reuse + +`vhost_http_port` and `vhost_https_port` in frps can use same port with `bind_port`. frps will detect the connection's protocol and handle it correspondingly. + +We would like to try to allow multiple proxies bind a same remote port with different protocols in the future. + +### Bandwidth Limit + +#### For Each Proxy + +```ini +# frpc.ini +[ssh] +type = tcp +local_port = 22 +remote_port = 6000 +bandwidth_limit = 1MB +``` + +Set `bandwidth_limit` in each proxy's configure to enable this feature. Supported units are `MB` and `KB`. + +Set `bandwidth_limit_mode` to `client` or `server` to limit bandwidth on the client or server side. Default is `client`. + +### TCP Stream Multiplexing + +frp supports tcp stream multiplexing since v0.10.0 like HTTP2 Multiplexing, in which case all logic connections to the same frpc are multiplexed into the same TCP connection. + +You can disable this feature by modify `frps.ini` and `frpc.ini`: + +```ini +# frps.ini and frpc.ini, must be same +[common] +tcp_mux = false +``` + +### Support KCP Protocol + +KCP is a fast and reliable protocol that can achieve the transmission effect of a reduction of the average latency by 30% to 40% and reduction of the maximum delay by a factor of three, at the cost of 10% to 20% more bandwidth wasted than TCP. + +KCP mode uses UDP as the underlying transport. Using KCP in frp: + +1. Enable KCP in frps: + + ```ini + # frps.ini + [common] + bind_port = 7000 + # Specify a UDP port for KCP. + kcp_bind_port = 7000 + ``` + + The `kcp_bind_port` number can be the same number as `bind_port`, since `bind_port` field specifies a TCP port. + +2. Configure `frpc.ini` to use KCP to connect to frps: + + ```ini + # frpc.ini + [common] + server_addr = x.x.x.x + # Same as the 'kcp_bind_port' in frps.ini + server_port = 7000 + protocol = kcp + ``` + +### Support QUIC Protocol + +QUIC is a new multiplexed transport built on top of UDP. + +Using QUIC in frp: + +1. Enable QUIC in frps: + + ```ini + # frps.ini + [common] + bind_port = 7000 + # Specify a UDP port for QUIC. + quic_bind_port = 7000 + ``` + + The `quic_bind_port` number can be the same number as `bind_port`, since `bind_port` field specifies a TCP port. + +2. Configure `frpc.ini` to use QUIC to connect to frps: + + ```ini + # frpc.ini + [common] + server_addr = x.x.x.x + # Same as the 'quic_bind_port' in frps.ini + server_port = 7000 + protocol = quic + ``` + +### Connection Pooling + +By default, frps creates a new frpc connection to the backend service upon a user request. With connection pooling, frps keeps a certain number of pre-established connections, reducing the time needed to establish a connection. + +This feature is suitable for a large number of short connections. + +1. Configure the limit of pool count each proxy can use in `frps.ini`: + + ```ini + # frps.ini + [common] + max_pool_count = 5 + ``` + +2. Enable and specify the number of connection pool: + + ```ini + # frpc.ini + [common] + pool_count = 1 + ``` + +### Load balancing + +Load balancing is supported by `group`. + +This feature is only available for types `tcp`, `http`, `tcpmux` now. + +```ini +# frpc.ini +[test1] +type = tcp +local_port = 8080 +remote_port = 80 +group = web +group_key = 123 + +[test2] +type = tcp +local_port = 8081 +remote_port = 80 +group = web +group_key = 123 +``` + +`group_key` is used for authentication. + +Connections to port 80 will be dispatched to proxies in the same group randomly. + +For type `tcp`, `remote_port` in the same group should be the same. + +For type `http`, `custom_domains`, `subdomain`, `locations` should be the same. + +### Service Health Check + +Health check feature can help you achieve high availability with load balancing. + +Add `health_check_type = tcp` or `health_check_type = http` to enable health check. + +With health check type **tcp**, the service port will be pinged (TCPing): + +```ini +# frpc.ini +[test1] +type = tcp +local_port = 22 +remote_port = 6000 +# Enable TCP health check +health_check_type = tcp +# TCPing timeout seconds +health_check_timeout_s = 3 +# If health check failed 3 times in a row, the proxy will be removed from frps +health_check_max_failed = 3 +# A health check every 10 seconds +health_check_interval_s = 10 +``` + +With health check type **http**, an HTTP request will be sent to the service and an HTTP 2xx OK response is expected: + +```ini +# frpc.ini +[web] +type = http +local_ip = 127.0.0.1 +local_port = 80 +custom_domains = test.example.com +# Enable HTTP health check +health_check_type = http +# frpc will send a GET request to '/status' +# and expect an HTTP 2xx OK response +health_check_url = /status +health_check_timeout_s = 3 +health_check_max_failed = 3 +health_check_interval_s = 10 +``` + +### Rewriting the HTTP Host Header + +By default frp does not modify the tunneled HTTP requests at all as it's a byte-for-byte copy. + +However, speaking of web servers and HTTP requests, your web server might rely on the `Host` HTTP header to determine the website to be accessed. frp can rewrite the `Host` header when forwarding the HTTP requests, with the `host_header_rewrite` field: + +```ini +# frpc.ini +[web] +type = http +local_port = 80 +custom_domains = test.example.com +host_header_rewrite = dev.example.com +``` + +The HTTP request will have the `Host` header rewritten to `Host: dev.example.com` when it reaches the actual web server, although the request from the browser probably has `Host: test.example.com`. + +### Setting other HTTP Headers + +Similar to `Host`, You can override other HTTP request headers with proxy type `http`. + +```ini +# frpc.ini +[web] +type = http +local_port = 80 +custom_domains = test.example.com +host_header_rewrite = dev.example.com +header_X-From-Where = frp +``` + +Note that parameter(s) prefixed with `header_` will be added to HTTP request headers. + +In this example, it will set header `X-From-Where: frp` in the HTTP request. + +### Get Real IP + +#### HTTP X-Forwarded-For + +This feature is for http proxy only. + +You can get user's real IP from HTTP request headers `X-Forwarded-For`. + +#### Proxy Protocol + +frp supports Proxy Protocol to send user's real IP to local services. It support all types except UDP. + +Here is an example for https service: + +```ini +# frpc.ini +[web] +type = https +local_port = 443 +custom_domains = test.example.com + +# now v1 and v2 are supported +proxy_protocol_version = v2 +``` + +You can enable Proxy Protocol support in nginx to expose user's real IP in HTTP header `X-Real-IP`, and then read `X-Real-IP` header in your web service for the real IP. + +### Require HTTP Basic Auth (Password) for Web Services + +Anyone who can guess your tunnel URL can access your local web server unless you protect it with a password. + +This enforces HTTP Basic Auth on all requests with the username and password specified in frpc's configure file. + +It can only be enabled when proxy type is http. + +```ini +# frpc.ini +[web] +type = http +local_port = 80 +custom_domains = test.example.com +http_user = abc +http_pwd = abc +``` + +Visit `http://test.example.com` in the browser and now you are prompted to enter the username and password. + +### Custom Subdomain Names + +It is convenient to use `subdomain` configure for http and https types when many people share one frps server. + +```ini +# frps.ini +subdomain_host = frps.com +``` + +Resolve `*.frps.com` to the frps server's IP. This is usually called a Wildcard DNS record. + +```ini +# frpc.ini +[web] +type = http +local_port = 80 +subdomain = test +``` + +Now you can visit your web service on `test.frps.com`. + +Note that if `subdomain_host` is not empty, `custom_domains` should not be the subdomain of `subdomain_host`. + +### URL Routing + +frp supports forwarding HTTP requests to different backend web services by url routing. + +`locations` specifies the prefix of URL used for routing. frps first searches for the most specific prefix location given by literal strings regardless of the listed order. + +```ini +# frpc.ini +[web01] +type = http +local_port = 80 +custom_domains = web.example.com +locations = / + +[web02] +type = http +local_port = 81 +custom_domains = web.example.com +locations = /news,/about +``` + +HTTP requests with URL prefix `/news` or `/about` will be forwarded to **web02** and other requests to **web01**. + +### TCP Port Multiplexing + +frp supports receiving TCP sockets directed to different proxies on a single port on frps, similar to `vhost_http_port` and `vhost_https_port`. + +The only supported TCP port multiplexing method available at the moment is `httpconnect` - HTTP CONNECT tunnel. + +When setting `tcpmux_httpconnect_port` to anything other than 0 in frps under `[common]`, frps will listen on this port for HTTP CONNECT requests. + +The host of the HTTP CONNECT request will be used to match the proxy in frps. Proxy hosts can be configured in frpc by configuring `custom_domain` and / or `subdomain` under `type = tcpmux` proxies, when `multiplexer = httpconnect`. + +For example: + +```ini +# frps.ini +[common] +bind_port = 7000 +tcpmux_httpconnect_port = 1337 +``` + +```ini +# frpc.ini +[common] +server_addr = x.x.x.x +server_port = 7000 + +[proxy1] +type = tcpmux +multiplexer = httpconnect +custom_domains = test1 +local_port = 80 + +[proxy2] +type = tcpmux +multiplexer = httpconnect +custom_domains = test2 +local_port = 8080 +``` + +In the above configuration - frps can be contacted on port 1337 with a HTTP CONNECT header such as: + +``` +CONNECT test1 HTTP/1.1\r\n\r\n +``` +and the connection will be routed to `proxy1`. + +### Connecting to frps via HTTP PROXY + +frpc can connect to frps using HTTP proxy if you set OS environment variable `HTTP_PROXY`, or if `http_proxy` is set in frpc.ini file. + +It only works when protocol is tcp. + +```ini +# frpc.ini +[common] +server_addr = x.x.x.x +server_port = 7000 +http_proxy = http://user:pwd@192.168.1.128:8080 +``` + +### Range ports mapping + +Proxy with names that start with `range:` will support mapping range ports. + +```ini +# frpc.ini +[range:test_tcp] +type = tcp +local_ip = 127.0.0.1 +local_port = 6000-6006,6007 +remote_port = 6000-6006,6007 +``` + +frpc will generate 8 proxies like `test_tcp_0`, `test_tcp_1`, ..., `test_tcp_7`. + +### Client Plugins + +frpc only forwards requests to local TCP or UDP ports by default. + +Plugins are used for providing rich features. There are built-in plugins such as `unix_domain_socket`, `http_proxy`, `socks5`, `static_file`, `http2https`, `https2http`, `https2https` and you can see [example usage](#example-usage). + +Specify which plugin to use with the `plugin` parameter. Configuration parameters of plugin should be started with `plugin_`. `local_ip` and `local_port` are not used for plugin. + +Using plugin **http_proxy**: + +```ini +# frpc.ini +[http_proxy] +type = tcp +remote_port = 6000 +plugin = http_proxy +plugin_http_user = abc +plugin_http_passwd = abc +``` + +`plugin_http_user` and `plugin_http_passwd` are configuration parameters used in `http_proxy` plugin. + +### Server Manage Plugins + +Read the [document](/doc/server_plugin.md). + +Find more plugins in [gofrp/plugin](https://github.com/gofrp/plugin). + +## Development Plan + +* Log HTTP request information in frps. + +## Contributing + +Interested in getting involved? We would like to help you! + +* Take a look at our [issues list](https://github.com/fatedier/frp/issues) and consider sending a Pull Request to **dev branch**. +* If you want to add a new feature, please create an issue first to describe the new feature, as well as the implementation approach. Once a proposal is accepted, create an implementation of the new features and submit it as a pull request. +* Sorry for my poor English. Improvements for this document are welcome, even some typo fixes. +* If you have great ideas, send an email to fatedier@gmail.com. + +**Note: We prefer you to give your advise in [issues](https://github.com/fatedier/frp/issues), so others with a same question can search it quickly and we don't need to answer them repeatedly.** + +## Donation + +If frp helps you a lot, you can support us by: + +### GitHub Sponsors + +Support us by [Github Sponsors](https://github.com/sponsors/fatedier). + +You can have your company's logo placed on README file of this project. + +### PayPal + +Donate money by [PayPal](https://www.paypal.me/fatedier) to my account **fatedier@gmail.com**. + diff --git a/apps/frpc/data.yml b/apps/frpc/data.yml new file mode 100644 index 000000000..ce62167b4 --- /dev/null +++ b/apps/frpc/data.yml @@ -0,0 +1,20 @@ +name: frpc-frp客户端 +tags: + - 工具 +title: frp是一种反向代理工具,常用于内网穿透(客户端) +type: 工具 +description: frp是一种反向代理工具,常用于内网穿透(客户端) +additionalProperties: + key: frpc + name: frpc-frp客户端 + tags: + - Tool + shortDescZh: frp是一种反向代理工具,常用于内网穿透(客户端) + shortDescEn: frp is a reverse proxy tool that is commonly used for intranet penetration(Client) + type: tool + crossVersionUpdate: true + limit: 0 + recommend: 0 + website: https://github.com/fatedier/frp + github: https://github.com/fatedier/frp + document: https://github.com/fatedier/frp/blob/dev/README_zh.md diff --git a/apps/frpc/logo.png b/apps/frpc/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..023fe72df4c2c99878a8f9c803ecbe3f1e4204cf GIT binary patch literal 26073 zcmV;~WhR=5P)dlhd47M)>ANhu zin5D5AC_BAxpU6>&NJVq%rk_&^0}q7jAeN~2$RT(Z%d^r)T&_zXC?Ycp{hS=dGOK+ znKmaVV_A|9s%+=@z0x(I-Q9p5EoCfG3IierfQuh}ug}t^{zo+kb#xPnLr93BjW7eW zp`0X>Y-MihCs8k0tnbCVGF$4!#nkZ1!f)+g<(;ymg4JGNe|Fgm=+7XfWh~2Af{`Kv z07sR5`t?mF>xWxOoZ3jLpp_&*WdFdyfw7MXX5_MN>Id^|fpmWV#`*bAc-!^@`?JYj zKzBt_EHD~`$)o|`$bYOqtJ)-{)**3Biw9zm0Z0?TAObT03ZP8(juQYdK>(0ogKQY& zv3{$V_|7-aANY6g_ew{D%H7}FD?69HfbNVi6DlD+jy!Qe&9Q48adQ>qBv%_70t}eI zEC7%KlfAp{3w!^0cickS5nuwC4L|_PEHDaLFCQ#2(_T9_|8W371uHxc cw($frND_P`I2J-6DZ?`#(mAkxGD7+@v>NJs#E2(3B5TfHPN6X1_N)Usi; NEik&G{9h}-Y_VHerA8POn>gY;x_ ;-lQvKP=X2^)MB z6&32r&10{whMc;Q#6SoF5gdTYQVYml#K;%siG359J6=Am;KkrfOsIft^8 vS>c-yGX}>)Z!VKCm9xYdE$idjai9iUm%D z@aV WU#*&dirjE_lhF#07C@_^$tZ(16vn zCp^9FxV0IXs@3$3W(EYaBVYsrMuU`KgF=|vBBXC#a&EzWMBu%KV^sD6I>wWao4?`s zb)2}ZiW0|V+5xg4Mv*it_f6<&Z=9O9002 Uz0gM5ZV#Z+TcL$5s>93trI3EB|!7BAUOzJCcIDT~j9Ru=7^FJN2MkjBs zCRMs!N`Ror`X&rRC=ie@cvE3AbJIJg=KU7HE_bWN{o98<-SE>5t@5TCMgf?i7!JTf z1BL;W!v;mrmHQ`KZ>Tu4=yd>Jd4Bzs1az2tUiic(1D3R8Pp^Wyrk;d=5Qc~uAnQmb zh<<{(SULAh+NW{O1BVRV5 *bdHSfdd7 zuVa%fGv=S^8lzuPV1K0m9oB%%5aSorT~(#U^g0rQAVfefY;Z*72u87V<`2tlo&M~J zgWm=4 xD zrj2Jfvd^!H8AZ^wh0?ic=~;OXeANucJsZ$*Fg&{cxHUTa)@l|fWWpMmVE|GfpiuI< zVwIk`?DT?%0N4bi5U<^B66=&lKHKn}^{sMFwWi^Q83ODOvtZ9~1f$sKclVJ|!*NfK zIPRH%jsf}9N7o(nk<)8V73jN7B4qF}m_Y(WG)U;}gOzi~w+?Q+BXz(5EdWz#8ANx} zYNcf?%iRpWGA@%hKYhlO>WrLTYtYXcj>cg?XuyD>dcmNGor?W9J+<;%MXv$aqxtn7 z2k0 Bhe`p+eWQ! zRX0~T^sVh0Ah08t1;DHU0cOf$CsWA!?jr{_-1^X@1GWNtmf_g*0UhU-2}mv5=j)OV7{0mk4H0F&uj=pi?OpsSuDSE?9r;8Yg*MHK`NQ?YQ6opiuCJ z;$%9t?6myf1Nht#zHTS6eC@-ZZT#Mb7E09_agb()WaAJZHK3WH5-=zv=ly-)On?2{ zf`0($K1T3ol%5CZ*f4wAqw7b0=p<6rP~Y7yBp|{DpAZ1kK*7z$34Pb;gFn6PSL4TT z2llLCHZG-QEXyau0K^qsp{`tb PTH?BYa>Y7%<5GBbiH#Lg_p-Hn(NwqbKgOE`E+ZUP9M; z!J-X$OE&hMR^y1Pw;B+bjdZPJ4KN5YmkkD+O! fA;H5F1BWe$9r7z$^yB(M8br9EG(vKXl$ f?xfA}X=MLyn7Ae_ZmV+W zYZ O Iw9V8M2lk2LU*`CC_hZNbL#{Bu;WN~P=! zhrQB~FjE-FCG*#gJ)o@ivFv|rV$9#lSWus#1zR;ey4AsgdV>Y^Jm~SQEu){>c*~Wq zec0DOE_99#CB-5PiX%>6bYQ44qO`QEa~ tf2Jr4|BklaynZRRq3|*yz|~F zczbp4Id%2POSWYM009_{ERjKB@75>w9lZI*S1ONtr%P>SCM<@+1j+z5;<&0s-CpI; z*-ZujvzB0DTW&$XFy*n% q8IW%ST%Th?e@f#4UQxTG7^TFjU* 4OI`4W_yw1J5Cw*{+)LZ zIkp+-!mws}G6D9Xj6He9_iLJRZra?M7^aCJg>e9u3` &sng3$cl7gRt?D?H3$I+(yqN{ z=kNidzhEwu`gddcHqMzp(XGtc=?GtxCm(s<+b6EyoO^3+tNNM)0tw>?7s&39dhG-m zVFB%ZZ=($$CT1pWG?X+Nd8*}|!hWq&-+pQQ gy8m_6 zP}gn|A{#=0z#4Ev)qw0RfFh~qAJFHs%;Ad}d>6hpe06pHEt}Kw+f6J$#9l;9xcb xJq`5Mn|w;CKEhA~Wr9jI(}Fes6J=77R2H@@`rF^k;`?lQk_!;_C)b#+Zc zV&>+w8~^}HumiASR~rZDb=wV>Cb{3S-$7vk&uk2nF&S3b$e=Jc{lo$LG~QTQd1TiO z$B<$= mj$a6% z !Gh52mhCC~I*vS!Hiy4K{B zZAM8D8%c&4EE(iJwh;I90UW0s t&pmOhogiSV zGVUDIr7TfyDbXQc|M0BZEy+7Jwy04K07>jncqH+f4Fb7b-?q_fySI-!@PvVF*tS`N zI0MmFW{}^fdEUqa*QB0&^2};`6F;Nj_{_HB*QLeWS}i8FxN{tXR8=UjK_QvVg_ODV z@_pz3=F$n5X249P 3Z$swP*lx~WFUQAW6vQ8}25Dv41j&AY`}&aB0! z6qEz#Qu< bK|St&e?a_D!LpShtv z>$Z()HP(PY!qsjZDml&ph&cl2Fkk=}dt1oIY@o@5bJ_pcyM-*$tVIGDq9M84*N#7= z>VzjAJYlUhOxx?2EC4cNzq|I@k5(t|Y-uJya$0~DU<85=6EaTWfA-#oL2dy{ZpU@s z`}>oBjcfp7W-zql2qm w8nep0r1y2Fkr5=&b2k3b9p#`6eUX{t2Q%myv&}39=h_kIeG*IZK zLTP^ewF5Wa@yAi4tP8Buyei6*kNuCg#;)C(xT7|cJUz`4AUAW2-APw~3y9D#Y+PVQ zv|Lz2QwU6+mUcC{OI18<5r~ Z}QWdL@-gb?|VkcK+HAtH)JU zC8yUmsmV<(2Bg!DAT5}U2)W|G%mJu70JnEdKA#TlL#{U@DF17L%}iQnpptMfD5qsn zQPHLwmcDxIzug~DuwJK~)4tF%{N8Ju`Yzp)bz_Y~Q#KjO0y9gnVSo(CfLZl|K{1?# zL(w{OSC$L@Y=Djdx%8hO7cFbfomm6%vuzg0#xqYm&qY7UC{X6Xk^P%yM<%0o_5wm2 z@6=0PD1Lv_pqVu-$)7fB2?*8#1`J5wfCEDOIOe%v3TZHoYHVLaM=6SbynoAtV~kKj zFa~8~O+i0> `!I+Gzb%CLJIt#Q|OGzrlT zUpt4c)xWDD>J*_a#@oim7&69z%Apn%^l6 !YacRmlrO{cH{0C-UvqK5r`rLs?IZ+%9Akt65e8(LhWvicZ5Mv`jbEiEPfi0Y zN=rfI<(=e&v7D0e-)s44^;XQTZ7})V(gLM3jyr+d=j|S_BSxSPaE?)ppaTS*);$Kn zah|)+8jeKl7?G $r_H<_9C z%Bh220MI4RMcm*U{U2}tu(l~Vd!r+VfZ^tNK*Hw$Ap?nn_u&T@?BhM?U|1#~q_F~8 z;n58OX~Tj5A^Ij9 OA#_RPjf1MGkNl4 z-PKU~&H)|kZAX+>l~yA$r;5Z#(`GU%lq8@~nU(t{Gt=KVrSK5|U7L6rGx!d_XxXV% zP03qoGxBh4Z7GM?jqrsjK}b`PuW6%v*nf!bXA6oD^$2G|y6*|X7#0RhDkou(pJSdF zx=+ir7ath)HUJmM=#uYwhxd6>5G6eMs`}xpH)PMPt>@B)#xz7G?Fe=RGYjiJG%-M< zeSRJ0*kO9&@8i9X2587Iz;GPL29pM5x2!4{us!w8TZjJ5-AlT6d*{k2R#o-zryIXt zoe?vu9U5*7AlSHuBO3rpz@V7TNBhXktT#N5NGC`24gqaLpSEY5P`2) #vX{>Lp^R7 zxZKFqI8mArfR-Z~8VGY{*U!O1vk@vGfV^I2S@EFs4NLws+?GBlVTF<}B3B_A{{Gre znos<+R@_$CV2)|o-U{iY9bzNdFtKX|2AbEuw4hTXOeq4M9oQJI#SsEI1MX Ycw1|1b9_Sy~EonkRo&iRGdk`v020SF@3B zu4~}^o#s|3o%Z>4@aJD_Ogr1o?Y$2SVTA5s_|?5H#`FF#2yC<=V=_>^WEz9|G|xY1 z*rur!|2qDCd%&UuaD>yTkt!5Q|KZXt{a>q6zpQiA)td}@gN;|G&kdzR4Pb-)IX!FX zxASKMQAHb<_5tnw;296E9=crTKDtgM#zP1uVq@(tn>^HCm`q{9`OlF98*Y2-m|->k zv7NP0OUoq6OWjPkd5K@Y_O&V1X*sRlh`z3)$pN$SPvmJHKgi)~T@!V$1^#A49u&dj z&mlKn=oS!!!^W=DHXz|_&(GyM&O9%9=iQTs*u 53?Tp^M2RX zY{Ly38+0x=r=fTUz>WYq?ET<~_TDj|5mFS +Y*p2R;4J)Ja`pMCvnDj{NMW`Gv nxCCJbBztmVU3QH8E$S zqYiMNfCI1_EhEoR3H+=f`ruKGK;r}t!Jdlz=hJ3b^=|>$^aEzuOEL0u^dCkH-8So) zI}YCfp!3%K7bzj5vouv(wDg_6vp3d@pKNW+fLdF%Vh6^$dqZ}DJC24la^R~DQL>O$ zcHgu~(h58x>?sDv$&iB47?|C {P9X97js zbcj8i@B<3Y71r7WG7M|*WeLWhtjxcL4%|NV)!!Yu6aa9 +qY*RoK{D$7Ho`&(-05Lz9H!=fGDT7yN7}9-EZ$WyB)^maSW|B6d8@Y zUg k!&f)SJJ)6C>)J2`ShKCPkQmD5o%7Agqwb!3 zY;!8bB8 H1+=EkAkV^kSQH(WP)D6H=8DDGTJU z|MKMnKiu4JcAb_Nwy*%e4!{ELT4|Bt&wn2_dO|*BgtatWU`LOSYGVK(TbR>GB?Tid zq2DeZ*m~o#d86%|yf4h)+clC(v8`q20{h4xZa=GPQ{tA|1~WF@oQ87J4p>VzAWvh5 zldJp=9dh% (8V=G>^gNcz*@&Y u zbxDN{$cUzfaA1T2fV_mM%InRk_x^OygYJ%Bj={H!B%FE*0OP-(zM{GwGwbSgzG-Sj z!eksatk|a^(GWWO9u7qAn?Le#OtZJ6SUB{Yh+){kXa_1=ILOa!er(9T_0wMIYN{%t zuD g~?>!2F$PJF}BQ%%<7}QUqC9k)>>)6rFxBm5)ZmqlBVDRlKDJfx9 z>1yjA-o2&&Yj5_NR=1h1+1%hLw6wA^j$y;ndU^~z8^bpWLy93vIoJh$R6~11p`|LJ zk VQII-BB72L5zdGhEh zmt0)anwYtX A!Cf7h|%ax5O9q|AVMnw zjUJ^Sh-h^0m~g}qAcm9Cq~I|6CtI5e`ZwKq;pG3jEtN{O0A8V*ozsxfWt?0&nbOBS zQ8#HxOY*s9>t}U9lo(BB+RAVBzs19F#3(E-+xm8uRO5&^%>v2cl)m%Ba|T`4S h#SsQRPxd_*QA**xZ%;FO+ruE{2xx=%5hIWR(lA0L$zYJu zm4gTB8y5d&j9t&~OPsy^ `nE?;)Y-|a~|>E@fq30z8< zVe_~Ab+xAN6DZAsk_F7G?lTKVPM$njgP8=}l1?X-Z5rJOG0ts9vOmytFw8vwkXngO zOiHz2zGU9xy@p-A>`!lR?_E)45=R(84umlvRv;ob?<4d_u~+YpgZCo#8rhfZ_X2=B z!3so<{Vi5`S aU|FE&k1z*HKcTtlMx>H}YQWN+CuiIbMaO*Z-LF(kG86 zPZ+%)E*M;p{jtdHtuiW$NJvKr!9>EnhXi#( zypz6O0sy7u5ag-q!^-QwyWG(KIEq>!C~H6F$JU gi_Zkcj)1GQ%LN8*wVp9GNqKTfkU>^U=MW-y=mRwQ`H58IFAS0L{1I-%J zxSn`z4{r;zhlr+*?L)8{*=iK+8ht8P8XVBO^}(<0Uq9mg-;KRv@?>bFDilEGs|IGk z^VpC<39HoPG3j^yk#+0DL((G-DwgvG49tO(-Al1d8WK|5`JM!LTHC$v C-8JAU{_(IHn}i?%rIO@qPA8KqKF$5xm~kK98i1h#O tk-0)_}+uM6BY?1;5?Jy%@krs0CcpeOjx7Yg~ zzP;CGdwW6vKn6^PnN(63 oUd@1$w~ zKb>@C;{%_p%etkmUY^mg-GR!qIs#fSSglk62MXo_nrwy&jK<(h4Htxq=r2t~GF i{wc zDcbg=#$XFTV6wwV19P@_eFD$hw+R8^jv1r? Mxz4~1dtk-&>KhgX}Pjy-iUF_?>giufMsbZTbE%sjq-H|Nu|i3 zk{qwb^c#Q8UAXp%#9^a`(nZC2$xo2oOF1G*MA9J=@C`@z8H9n&q36af^#~_I#uXD0 z2hUspOhgI6G9v_kQkQl6i6?&gHNb0I`;sk$L*B`WU_#?XP_){Byw(X25`-NCqO?pR zMdrwB-~2{3)H#r>nUH7~h=}*x@CCL5W+3*xs~rS1NEkq ?VrX{y;iCq(j$U=| zm|s3L<*= Q(>D`Odigc+$|k eJMsv4C$q2NwK071?fBdv z=tS+FXGJ*yK(m%(T7hg3Gzc qZQOcWV} zT_;BX4KFVz )i6Kag8IE-#O+XfXOC2k=|?YeF>5x1CVwNM_N{% z^U$T=uO2bHm~I->FWIbBmNKMR2x0vAO6=Ksaj#HhJV?6 J2zFi)d$&JJ8UsY)MnLu`P-m7XxUBAA8@&4MF$4fB{G-VZ?sf&cnwP zw2u7f&V#2tc DH!#ATs=3x(rH8H> }~;4rp2VSnt%4qnbw?P$(YC?Uf{l zq#z>WJ!6kvg!HicoqgbLeqQ@Fo%@=QP|UfB4jaayzmWKfn1%6CPaR_!0MK6{Q5^wo zD2U<@F9>Z5?H3ku_hb_NlTO{R+{}-b%pU*vTEGTwX6+$?krWyCCiG0c9}3Jo^#}SC zz(vPQ-u8zN*YMvrH_%Wi*sy`Hlp_Fw1usV_i2J=KmaPWg>}>ee1_aqY-}JSH6Fv(A z#N6SH&kC|qytao7z?g9u4v@sh8Dc=dBo$-CAY8O$_V~w9x+3WXZuSI&?}&Me5|gfd z>u7ti9Vg**Z;2#6WxZC`_vNDA%~O@o;BcW3k5+_OY}DR~8fb9?kqF4jG95g35mWJz zEq+tG1e}CKh+4#27kA4At!~S!1pq-JTQc%UZ3KYQ($RYcPj=S~Y<*Xrva&w;@_E;O zQ~(h7RQlmdiVR9^2IhOU+{kP|!m3^JfaLLN7pUHM6o39e8%!|39Ru1gan(jX=Z$Sg z+X68lcjnLf3~gm70Crwc&zJI20{|PF q-eE6L8R!~<#b=M0Uu_FnzWjs1%b#o^#a-N z)zkF=_82X#0DqwNo~Z{?&&;ymWq9*Dd 1ygsV%@G`@}E2-L~~mvD!KHr;6-a zlXIh;Lt(7RMC{ZPk{`8*UjW!Mw6s5^kfYDG4Oj_5(8Y}?dXxhQY57k4rr7b0f!nT& z*OBmJoYWS?Z9pF1)|PJAuR8Xn_XsJm+PUntewS?&az6;W#)!LBf*5s-pPccFl|%Og zEv=z_UhDyve9uOZyc7h~!k~`AArwL6rkwseRMUPnBJw}Cr5tS tUTr!S2Swgvv?IWvPnXS}lGFTRc^SQUeHJryiX3enawF0DFd(4n1RbwXg5l z0QumJC3S$%j=#E7vg3fUe=|ii*#m0F*&G0XjK`sOL>=OMx;<(V`6Kjr4ee^@=WF_1 zzEP?oNOllTqp{>sf*2c#fAaOqSNC`=E#YQ(wy~kY9*q#)aQF4-hJUPo4&G_#iDJt) zhNXQD-N{R7dm-(7_Q_FfTcm{mz|gYe=w$a6tDP^t{n0+vT3iD~fL*=~5qBoo< ~mo`{LOR1h`zfmht10rhGE2Cu?a9kHE%&>+xup zhJ=km^7fAdc}KyQm_% =@)zH?n@x9b* zed{=R4WtAB2@2U6Q8y(4aJCUARyVcwXf4gGsjYJIfazU3;N?mO-VcuLA9M%?qp`6o zSO{)x+rWzbN$61F{2g3LTR(K0Jm=W&g^j^*imBUed#p+5YUjmu@`_C)3P9|@D|rTl z=|=e8OOQbw%#S8swQ_jR)zYr5 WRy^} zku2rShV=jISQ|&)$4>2j6k;cxs9TDsouBMmr;}Gh3Ba3@1_T|}q}U<~E#$6)ef9j!{@$@$;w#0SNMP^TgM& OJC|PnOuss# zuCYnyo_2NtE!?rz&b^FwWc&D>Mly13lep2Iv*&5)uu`&mjRIrP+aB3B a}Aphio$kAlSEE4&7ym^*;YQpzWB_UO+`4@_qTru63^6Ca!i~-dJ$?CMokFjN@nE z_~jUgAp}842_ZOgU+jI85Wr@_501Nf^+=?8pqBO|q@}&fXYz{)1R5EDuc?DiQ5<#r zJ28$Mh(PgY(~-?iJ9DYp !D%EGpSGlXoW~>LhmMTc>~mzl@5akl_{Vzw>d*i90}b6pSo`@Q?Sa+*9COk5 ze_jU*{U`xS*e^;)_W&Z|bLXrpHc1h1XCSPd9SFt{mA-HJts|~4PS8^j5+FDM{UE^g zOK%dmsN{ pTZUz7x z(2K9lRe~Xe@*kS7rP*l|z{eWX>~HiOE#2P4jj$QvmoxBYCPi{O&{k{jEQ=_dMij$M z`!}r g^Q?z}$F<<9H?9(RW2hD4ks#^7XT%5Tp&qZO%- zvtLXNUs;ea4?+kKk&Y< A=XPEr8oV9gcXx5M z^UIqCT(L>1{0Mip!T_m0f-$r&Uk3oCD7PhSQx)o|)c8;H6Xw_Mwd aX4>&@ z+V?v^Z%+Yp$nU%viL0z 4cvgu9fa409?;51A2_zK4 z!;}St( UsBLa=?OUF*+jxs|#xLF+=g_67lPU2fA z1n>~zDP(iD!=ZbGxZ3&c=DaI5DYDv`!yTI#AT>~!tw-+HauWcgP!ghe#7I@Bho&61 zwLqGiZSE2UTH5}nY`!!uoOs2maot@@#~gLO7WTw@>y^*-0xq6S>`lRn*X!upx31I3 zh;nGx53T(!(z)|k|6|Or>;c#3)M0)^9fOzv>el(tf!}$fNM416$DP9$M4AZ5mzi7s z=h6uqkGNz}B9$Toc2}ijCQnP>blBU!EhKydB1K;5;$Q%C8l}Nnu#FyecP-tHYc>e1 z*zKOy_OM{*6nYqmod*C=*uf8WV#Z1{F?SZs0DxFIhM1Odzw`bJgPCIcqf0-#+r-t* zOEzcy)b~4wJR5GoLN$PR^#vzCd^Z3resF?KAS5?(;Qf`doIH859w^N;VIMBr5V`*d ztd@qp;P{`f9*@dN9WK$ZTg9#k98*-DxyJ#eh)t4hH^}A*b!-%Jto)(~QIOaq* K!#<)IoZE8}= zDJ!#Oz?ebIDG~lFD=o*oMT-(EZy!~*UlzXzkfgBMvFCLf3HUT)rUF2>ttF*(6p&$i z%AK`hzYmSv?!G~`T?iMRR_{QJZ}EjN<(|>Ut?*mZImsArF=z_F>yInpKnw4 4aK4 lF zbz}RhHg7s9O~#855hCkmct66i9}M@o2;T}eJGz^BIhYAV&b)c^64O3VQ#c_2=wK!{ z5FKp*Fhc~!aEN;C$cq$NMVEphI~cy5?E-3p=I*Pdf#^LzNJ}%v0?D4Hj_mBdwQmd) zwrtTIV8L5#mV=LI^R{b}2q!0n-clT_ZK#E(&AY2g4#`bcJKy`^gdc8}VwlUF17ong zp(UIzDF_f`K*F(q wXS=X8bfym{~ zenB=4E|%a %|udCl7f&5*45{L$V9=65Y?dIy?xQ!1>qB8Gx55wmiE03 z!7IU?^AKBM);}h6Y-hmS_D3V1I;hLhu{3%K{&5XV-gI@uG&K3!t%i!a@46S)fUlkB zEV|(b8 dNFbLcoPjN6WA=kx9qmpcPMEhVlsia; d@DqCK}=KsoHM?zApPJLycGf#_dM zgj$3z0zqm=tao+`vD(=gcm2`}R|+-SYG 2v_83RME25+#^_DOCZOo2vNuu7_X61)I|9@{JiBk#-DVG!q-mARD#v4MqaM z3Iwx}_{<}({P@H-e@oA!lqI@@UplUdIk0iP&p@y!XL#3+{0KV|)4`m=9eOz=IUSz2 z)mtSi=zx9?v=>9J^TYE;do3r=F&Ui9vxj!FHsY5i?z-W%q^{FS0%U}*1_S|s0h4h9 zQ>q`CmH`R#-^IQ4eXssv%+gN*SpRjU^p>To^iG{(kwT?NO*)_jz@Gs8>F`_EomSUM zS8d9O)0;FaXbrpI3`u5h(msK}+#(ICP39&5B^U$l4usk&rVujW4q9zIU4hrfcR^F= z9PYb7v+qRO*`=Kd{+%292Z^@1)ZFHMD6rsjL)Wn$pHoKNq;gWKLIJ>->z90YqZH#I zSp#H^LE##DOoG5_pwzVoCC#lz_e+mhGjr6BUj4 YGTBDRJAo zTgA5_0#}+}I4X4c5qrALJk#KBX9#2y-7D<9_HRZaaDsM9jCUd7t8xJxaZLmMkmK#g zZqx{&a}WR}y8)ASwR4@wx?W2=sf0m}9Y07aFa|1qKQCeKJ8Ve(U;h66W43(+xE-Oy zAVs=UTGImEGQBdEC v>Sr4>>f$Yq9?04Ov~kGZJfw+GXD|!E z6P2lw-A_5<0W|Ns$YQG&%@M5}Kg5-td324~F;bP6;O|GBJLxtFmt69Vm@vBtwcIa! z9ik)=QcqrBWj9lfRE0unk~4Pd^2zTBbtojYFe4ivWD{eMG|vx8>igchZuG-M#4EjH zERa8Y>D0-V2bY$yEME!w_Y_(U;FqO;Sa<6?HS$NBGUC!rX+BUp2GGWU(Yg^d;m}{M zE?ssfm6xPgReqk||6JnsCl9!8+5<&U8wa+B {1-6^eFUo&Rn*rQ8Z_%QA?*I4T@7A@b%QmO^m=?!mr46Bm#q|KncORGm z4H?y_zEcM99RNTZU`PBP97EF1l&XQXWx}U)r5!(X=SF=K{$WoWM<|Bf9`QbrHEkl< zq!d4BH;KocXTN*l7C}e!S6p*YGIRT}eOgAYn>OZqZ%jGlRl8hsh4O+faeln(+Co<2 zGZRv*E}bwT^Vao)|GHsT@z=%;P$v%QotWP{E0L*D;)u~xtA1#Y;V+j<*Hsb#^i!+| z2*rc~ZcOg;Zm+hTm(uJH le z056>SpS1_Qw~4OT8M*+#L!XQCd=AM=l4@kYxScz2U@?3LuJ6$Z10X^fBGNfH2gipK z>q3;nU1fzj=Z6;INwVSbBh+3CYA>0r9Y2kSeAiA?UG18?SV~eA>arV_UpAR0>zJYE z>{jns$bc*@V_9AfEWDgP0`QXy@Bd`LA*mI~^3<60?r2(ef{4QIsTjMo_L8sN;5!cx z`Ytli?HmG9c>2 IKa~xWDEsR;X;fo3TCL`{duo19VKA-IFjwb;Kw|c1i zOl{4Lz%}QAHAq+r8Ho`!YCrFEiOe<?2mnZCtBhX_)HRTN2zWWr9 FaIN1vp3tf4~{d4Z@OI$Xiueeb&8cILM8%Hp&!3`1Rx-5l7ES0+eI z@@z`>y?fh1z2C|t{yg;dx1TEc&0AxAZ$o#;DElf)iUmq4RAr?NK8+|{_Vbt54*qbR zlQ@SZ8zD69(BO+` )$+4%*Yk5fXfimDcrPx6@pXP0UR(KaAfCBWr2+ z8W}!kwxDL$aBw>t6A{1}A@nCmoVK`GEgyc{Tlf6%?xp?xDBfNg@+FI<7f6vo |@iZ@oKCOPed5di?1cA;z~;LsfMcmRItY8!E@ z>krD&?_>*PK#*QT!bez8yR9VHDmkvj=qYZ7TiU}<&9fARnG^vG63#|ac`I4nKlrxg zOOL#B$v03wStCUT^A;uc^6M`^QY-+LsGQ`a7-IMZOQ*fLIq&_oy4QDFg)%}KO{5hI z_Or~$(_SI42Fd*4piAt1jBnebm4K3ZF#w>XvfUBc_}Qu42Jb$I(;)ZYusfu^3nqgU zix++}>f?Uk*I=)~M0qp^yxH%aHc^ET_$NJ|wXK-t7UyLD1`z>@h>a1_*#LFu@=WrX z18#k*?6e1#?vG0+WI)8-V#dZEAxtQ#P)LyhNRR));`8pGyyD#t)4gx5CzVagI6`Ov z!P3*RhyXeGi`Lk1X@^TMnHcPPLx>nGTwn_Z6DTQxzI~m40s!($+6AKJBJE>T;6(c- z10#Kd5Ddc|1vzZJ;z2O?Nvl^A;^iRJx1n>~-^f4)N$k P3=_@_6$P`yZ8iy1ZjZez-;~Q^1qIJ5&%%XgOZEV``*KA zJ8rw6CCnN?J+!pvY)4#v^VZd)$_fZ?z{W)!ug8*S9Ku^1#=G`#^eCj#{Ry@1KJF+% zZnVk$Bn2P@k+T&d=iN;5=9y0?-#hfyMWslQ+3V)(x|EidNq_|^Cpq)x%}X5kAIs(} z-rWDa^_+F4ql6}@4UthGCQqvZ2s{&j8})6gr9I{C*XktpfeqIfgkU#x4j2$;Cma;z zHQ6HXrS81UcBBt;FZ(VC EH54)M$OUfLixCB^m*U{9OGxCp z >y8S)kPb~yms*YH~3&)YYBBpmp8a6rCNgY41m8;9kS zNh4LEUb=L|>jxxo16gx5SRobO1zU~lf!yo4!5g?N#Pdc6h6A}ZKJ2cHpcjCMNeP0< z2&van;^d`H^6lX_FZs=d_rEy68$tHE`Pz|GKrbd<@yfV;|KHmSSGMGoZ=}R9BrLsP z-+SS@RXv*FgEz!8!g)Du__Ld3C%jT%ZUoT>Hi3!KASCzA%`E)zZzC>sTiIcC=j}{= z+%P) BdZg6rM=Su?PedH @7=v1`xxeA$#3?9=#x> zCOMa-%5sPOXvtlRxAlGdQ%;`ZNYW&Y0kMJrfe0+fzwhMv+uT1-IRSA_9XA9$P3; 6q|Ib||y#_EkR{{*!}}`T;3OF%glM9Pix-|0Z}nJ}4CxuBhYlZMWnqhd^!55%z?5 z$B+~tCMleaLgc-x6Za3k>8&@vcFP+l+D=CXmwYwdd?`1|=h6!ved*$h{&&s6AFg(C ze!g8QkTed+NcQOke9cQCuzFUJhi!&e3CXi{!eEB4+2I2jA(|l^h9D`88rm=Yr*(fH zaT*c0w3Mawva}=2gvq2UDk>Bc4skJ007Js81OViNM5zndfkba++wBTqY-cX{#$%iJ z!(`H_jx-z*d)q(y$%xBFCC!vvDZqjh1UbG-k3yb}5D)W|x#zdGxgS9#c>m_W%dz#; zb=1A+Dt#qDMoZ~zkZQtGon1L>_L9G!a@QL}@ZeX_&6lcBDL2Y@)D^E!D86|4i|@7e z`r~GiD1u@Kq?zF^tr1c>zE>(BeDLye{L$9e$mCOth}%vCi`WN1c1sI`RNth*h=DDa zule(+i)~w3bhO+?X}Pu8uHQK3Yg+{!WQjA&1Q`8TKL-FM0Ng1h#HospvmdC 4uQ#}C;s`v!&Wtkc^iy4l8ph_IAF*Sk4KQA z>P8Yl;7HmkyR_MxWb0Aw&_2Gx<>0-y3 !_YEE9>OcEe=DDeIUI>F1Y34LZS!p86eW5ljK6nbXf zG%N3X{u2rYL vrSW)_t7w;Og5;m#H?2u-7Qo#z7$l1Sq^MW-{=a4{# zNhI=Ms!s3y@$kQ%I(|FYOQdjj9$CKmw)c&^UH};bBnA-DUsLIEPoAIuK}iLx%1ND= zW9JrY0e~@oSan%-hURS27zkrP%(mzu5CA&z>T#YZfW0ljk{sT(Q?zrqe1)0Ax5xgb zF(?LqxR1(QyJ+g+kNIu2a|b)VnLR~PEKpe~;3g3reCg85Y8*9ZGbaW@fI-H9V^ubT z+Fa4s@BrxBU!IZ)wv#u$dR{62PWr>J10xgw3{04fMZNU2m46udAON7GLV0cNP|7%o z$&{Y3VAHqXa#VSS$iS8%PK-e2)(_4bIMu_j0D#o<)=E5B(eDO=Glr0m#LgCQa)qPH zm{X#15;;fA *%=IHF;=1v67=sSU61^x9l7pYvqZ=vAy9$_N2riF;xYbp80O*1G`!CGJ|V z{(&yS4=&&I>vvgAAs|CwG6XeL=$9@U`1Z-ENt0SIj}y2Aots1&($*9I^1;FDn&q5o z2j6Pe3>ek~Cg#}C=Y8;;AZ!hgxNQh`81$$d;7;`l4}acygL4^Uca(jNF-1t -{WBykrugJ`r3unz5m{j^ XO9Pl>w>4gXQfKPi*#~TWRArm1QlF!bkMZ&pZ`K%-U4j^2MqkHq~IKBAU zTi0wbSvS{1^aimZ7-od3{6{)_*ycds%JA=XXj^2T9c%{xkO2z=Ln=u?e$qTYq@OeG zwR=Xr48R3)iQXw!PO-p=5FS7ef28L7t0?;q^$=Men88TwC(|#kJ!{ZJ#4_?CZY+-{ zmpoQ`{L)PF#d;7F*cgH_M5;d+#pK*Rsb9^__fHzr2ms;UvD1c*26=@E5C8oK=Woc! zTWT~$+Lf-2Lk!720z(F%|Kd#!@X_v;LvXc4cwNA_mPV+4IQu%rf#HNQ21R5l_Y*DG zy)yHtHvs^bEJ|SB5#6tx0W;y!#R~4S%ZFX{#z`B}Id|7^a-6MQtsTI6s@jfLaX`j2 ztq1z>vHtehx%_j2!9v3Zx{xpVo#H;u^kw&sdK3UUZGbZqDj_{AO?s?q%xayyb3Lik z9TFh0VLP!ZQ6SSBPVBqs(DI4H>uh z*{2&GhkE^5&dU2o z%ySPErKO;qu6!E<@)`f!F!X&Vds;2apEQsF1T--VCUU@(C?LIIbnfQkDkmMVraebR zTR;O5P_Hprf2n6c5NC*?G?50N6c~lj9~5$W&XV&A{{{e-hl2d-J{?FHD3_G2>Q}K9 zH`Zn7nyngHU}j=t*stl&KA1V~)$nLUSWElc!k?p>$UCji5dqB%0X8%cyrmeK*(*|q z-2
!z)&`ar-Cn3+9#5v5!0QVbyUxqU9&zWCbPdM=pIPwK|P zEPZFmA=`iT;H49qfKDob7?3Y`d_&$6lYLzc j0|Nr=z?!cHAeDqcA@t&XMQiHSvx}YpU<-J! z?Bp;L;@4;Vef7|H8!)@pp&x8FY!}l3>|#3JLkjt!i9JIwx{W{);FC*L*qipnfdLeL z^&S>86d8jecHSu#t-oB7I_h5lzI-=dj9wh^^VcSQn(1{<4JQt9y*v&$UUf9ysnI?s z_Fv XvE;r>3o0>bTuh#HonY z&K|$^PUq1O@8O0GL>Jty#SU*jggCi<(O_0t_PQ1fQ<)noW*qrGfG-8uVJ&xh>a~4W zZppf%T4!C*Dg;36fY}XHc@m}&VanmYZ5PDe{_Vjau(b$e*v`a|NdgKJ`jPzxw$6BY z&Y>#+SbO8aBb=QYd}S ;o9e;kx(o$>Tp zgRQHkvmOz*0HIeJcEX=low2?}++5?}Fk=kBY~4@{iU2!e42E2Mp?$*45AcB-Gn(K6 z-QQrNjSSI;wJAdDuO|)OeDi~so?H)nLHs(!0xLjX`sBzdOMh8ylBs%#ULdmG3mbJs z$nVn*#qdrTHw?qx3U7PpJl-)@BOBNSl9U3YKshfIW;-*M-gU?e0IcVtWal2CunP_V z4x3;7-6~3^YDkW>OFw#^E(>H3kS|Pqq0HQVYSN?@FjHwc zL{|;R)QT0!|9iF9HMI_I+?3(|Fzf+aaR|@>6$#vX5s-#7v;96yJ3P%D>J;8>vUt~E zC^8yFWZoH^aBf&U?Jzt4EmfgXDA_r^+R1gEmU?yncbjtWs?zfOG}@sT?NJE-T4OG^ zu(Sbo{Ly=N#R3^%43cI;L6({O?p>qrcMlXOEho>@vO|d}z> K%6^p@`!JkH4R{q$=zB8VA>G)vRC)lQG)5 z`Z!_`h5gt8i?APpK#aSuufZt-e!FAv9oe #LR3s;_8d=$uOYVGZ4MgyEnuGbqL^L<0&YN$=aR8 zA$zky5%KRz28(I`_2V&{5sO~6E1`hE_^FFet#Y#Nt%V!`5Qx}e=C<@AqLqO*phgGp z;qD**hDb9L!H~!m26 `=K^$l7xRPHKOOYumj2VL9lBzRAq8fZHp)W=WB^tc z0Q#Rp%=YP(=k2@9KS!rS>5!h`c-&uBO<3D3XV+%<^j6J)){bBZ1BkGPBS?Wnn-s{X zma{)Wepr!Q+Cpfvel;=3CKVG5M1NzPVQTx7B{Pq_uR~C~X$Gg?`{BOt)U^C*eJ1e@ zBLo1G0aziNX6v>y8o3L97uLw3_i>&a`xtmGAhXG!P+`G7ea(zlQlsAi&}kq?17)B? z7Hqt{n&tF5AqwFee4gjR8ka@VS+;Ld&+ }yvP{)`@xWB$168=tg@xwQ_C(%R-=6GK`r zMHtu~r}n<$K=b-WAwqzNa?;4??JZhwpd=d%VEtY(HQum%)-jKE2GHmH=SM@{t}}O4 zIaJ!h3>agbqV4(JBLEIHE%LgP0EtbfGXNPdlwwAK;FtF4ou2mQT-S5a*<6;GJvCuL z?YGw(HK&^7D0li+1js~;B4Iu$R{EwTrw#g(caF{m;yNq44$z*&WAe|{AHAko-dttG zH(IQ#&k;7+kPYmE8^ormh%>)Fv473&UXDm-E!((9Wc(ji|3_7tX4N`45H7G`AR}?_ z2=!q9YXC6{LQ$?A_5u*B@x(wLne~NA-?ZX}vA=gW@0@bDpay_r?_4={eREyKM+ za^_Y+oalI-3krY?0`kdhDUzAne=>Z_Jy#7M-U@WhbI}#q^?>#y=CV2F>1}7PPs>}X zSd4KDL)d7LG=OG65i<(NR1HRY_R@3mf9IW}(>=J1B_`XM5Azl+O5C$}(3F}C-MHD| z{xBM3TwV$UppF=jzAlbx;~1F9ci{p3NpCMmICqpBoc`5=XW6hX%E}}<>%xoK1xMbs z>ZDJbFt;|tM{CW1F%B`inTXN$?)bIMBekOl3k7E6Nxi-x$IMxI^B6zp;2H=F|xJohA~1AlGvNX1A#B0AX~Ia_&8HVDsF+9KG)*0G&@}`;79%0os+gN953j z4VP_j#LQYvg|JV`A!ca^nn5bT21Rh*DS|Wg&2#e~2Vif)^XObkXUG~qZ~nW3mRDy@ zt#!mz+qAJB5oW{2&3o{H9rkj#5~9j(`33FnCURkrC(XP=@>^#=_M^i$#DDiQ-J{Sb zbJ!iLE?D0}v+5i(lC=R02lOdo>~`R}01$XCfc~T#^A+DdX;{;*y_}0qw>bpD3m$(z zZ%ON*88sv?-zubpASSSZwI~>X>_Y~HQvcrpxz3DdPAvG)KgVbETy#aga6o$!9%8P1 z?Zdtm^~E=A$cSq<8zijZ2;)wJH4Lb1HYhTg=k`~bY2i?M=MBd|^PT$Fj}CgjUfxur zabdGIHb;a(%x)+>tgV5FRwi2;(14+`U{EOZ<3n;YH@ !<-Uh@BG2f zYFjX^F2lvvSs0$1={B^TU$vc&2nHe-jJ$+?VDy0Pv!A@~sOqk?**-I9fcV}gpUiro z>4>XpDKT}Eko|*DH3Zv;qRJvhu{19nkZ7G+aZ2F1_%eX($(IIb0Bwe?Ghf^~?1M%* zyGG0JZ8HS0(bApUZD*E1_Ju}1JO49GH_dwH+e5n6+v6UQKYe`6y6xtcstira_&Fl( zklyA@><-ngA6@7-_RYymee>$^{|4~IP6P;P&TIejR`18E`d(Yt!q;wbIM*)HXWY4& zp)j@;Yw#J{`HG}ouy0Og`pYxB*7@S0>O 1zA>+PS9wE>}0mZhcT z_`;`Z#YUOZKYd)ZWP_Pim%&fB*(q#H%$jZPg8`EUBO%!!U+C8d=kU}eGsZk;ufKDh zFK+N1Ie)`x8#p<)hScFs9LP)x#3&S|c5u?UdC4hx_Yr}=2+u`VWcL8tmG})j_L=%K z*QM3mYD42QcD-9ifF-*TM=+znIGc-L=1kB0^tY2ImuoOnNhP{Gxc~sh-nZ&!)eg #Avu)lHl2M2%DtY+1w@tr2) zc6paJ hEj9;Bmx79$N))E3T7|di1zJbED6iM^zlLl_O z{kO*q-v)efo{O%?ZUwX_aiATxaNCcn9675-(-5|NzyToH^@vCq6te!P5a~Hf&n^55 zfG&m7!?_a|Kl)yuSJx)5s&n|Ntr`Wr*<=O^=b=%3)3cxY$$0A<{~QM2u98%WMGBR| zYsYc-etgWQ+c0CJ=2Np-R~M+vz27;m=HAq#Ni6^qN^MBJ!;{8 }2O_lVtB?{h|i)y3Io7+BN=IgPE9ZCR{HV6e<1m{@MD*=T6FB z0-##~*^_PsXkS9y_&;8*E_i)gpXs$4S8O#zU^Z?{n+(B#p>m8yA)F_N$(9+ Go<8d8U7L4Y7fSOeS`H^NsWOjVK0%vyHZ zpx=AHwL1;I&PewKv@7ukal&((k6YK0yroKuiLGw=1J5I36Z{wh$+Q&f%)Jw{s&0GW zn}=)xx`)BCTO_6!PI!3z;p du9aDR7jDShb@qHf=O zeBD0pWpZX$LtflS(i(hjHBq+py+nUuP?X?@M)%pCnt$BjPvYn33DR=_?Mj=;1y46z zx;`Uj)o2uh0l~&0HwT*mrP!c|^?UnJX8P;r6+R4Lm!>OrM=7abRq4{KOCDd;>xIma z>uZp_b_>Z~5MTlfn8^!_^s-6zPYlmVPha@;LOW5R8yb9_ksb$VPr^gsWh++XR<7Om z7d2Y_a+5}Hz@1#c5T4 6lBcK(mQYA1c>Y1Ir#{wEa8-959OLc?aYskK-)}bG7WdaNv zX^lp5!w<3#8x$h_e+P<|=?l*pV%>8+9oVtV#-kspIc1$ub8ARV&_QmpWVS_u1ObIo zuPK#*)+XY>}X@Oo{8p(z5~WN!%l{aP!y?oy5(xhR)e;Q|2ATESSLBU3Y1K(Yg@n z-yGF<^DTe*#=&1oYU3`Kb|QQqJL;AymS?nj5kBU?-~*5+OygkX-1g()Z~W@2;Wh$V zTGqKq%RNE%3_!aQ_lQhfxb^FwIO>)vO-HBQatm$<*Z84ycD5FB=GJeGdj6i&n91p` z%u3&_66$ fNnbkhi!)`ue_4;WX(ap zs59z@%_Muffe{UxVPybPIm9Ry=BeSmTW|CYzOK~x?qRY=0@@Q>Hp=D~S8#>8>Zv1s zUhRmfb%y!@3~4Jd2?H|h&Pp#L{pLQ{e&eg>?Hd?L-5@F!@1)}%sk@|x<;+?N8GIb% zCMUosQu?i8 wR#o;zeYfZb;}#(46PkJg^H-l$uvArG}P#l6X>@aOOq3bUbDI;mx6xDmc?I@){@ z@|6HIfHuH5?YX* OWXF42;Z)fuMVJHX%k9+ddrEQ zrq$dHS{&EvPcDEk*4-z;2Kg|J#hkhId|mmg)a1$OFFN8F8BzYVZs1!jy;D^zt_%!5 zcc!|1e6k-I6bSRjalN @>f+P$JlbS Vq5pP}ZkqGt`TKqVz~+eLgE|Fn55#p~Pa{uy ztZK~1nXFr?NSxg&WM~dwP;RzZnCjwWde)Lt^B?qn^Q&U;bw>6AIxO)}dPV&~E1Kz+ zYDbiAHw1vSU|a0Y5D75R0Hd9OQvYFpwEp(r=N7MwoX-PzSV92y tSnX|hj2hJdeDw^z&d6Rsw sIL`s9Z3Lg!%8Wxy{oSOe$Uj;45qJbw>6Ax+96_VE=3D |%)35C*`$uMk% zA_+z=o0c5lgCxwm37ED0n3}YJ*qT9aNANxliP23YMr MlFNUE0Mi+l63ds#x7b zTX&4SB6?0N=RzsLD3p42p>$^XnQ(gzzD~ i1Gj!IX`Tylj&}zV>V6 z!4bBSx?2j5BQ+Gg8*XfAQvr7^#w;?(lX~?4W$wB1^i{vRlqO{Mv`n}!L-qo?s}kea zmn_=c?~Urj_clA?``cI?)5M^3c%>=#)hm_m70d%MvWU@(xVeuoFXSbiKizf8+Ye77 zclP;Sp8T0)FQ7lG#DEO|CqG?3yskBQWTT-Ynqdx-grZhZZX e2@00000NkvXXu0mjfCfUSf literal 0 KcmV+b0RR6000031 diff --git a/apps/frps/0.51.2/data.yml b/apps/frps/0.51.2/data.yml new file mode 100644 index 000000000..770f903e1 --- /dev/null +++ b/apps/frps/0.51.2/data.yml @@ -0,0 +1,9 @@ +additionalProperties: + formFields: + - default: ./data/frps.ini + edit: false + envKey: CONFIG_FILE_PATH + labelEn: Configuration file path + labelZh: 配置文件路径 + required: true + type: text diff --git a/apps/frps/0.51.2/data/frpc.ini b/apps/frps/0.51.2/data/frpc.ini new file mode 100644 index 000000000..13a8e5f6f --- /dev/null +++ b/apps/frps/0.51.2/data/frpc.ini @@ -0,0 +1,9 @@ +[common] +server_addr = 127.0.0.1 +server_port = 7000 + +[ssh] +type = tcp +local_ip = 127.0.0.1 +local_port = 22 +remote_port = 6000 diff --git a/apps/frps/0.51.2/data/frpc_full.ini b/apps/frps/0.51.2/data/frpc_full.ini new file mode 100644 index 000000000..29f6bcab5 --- /dev/null +++ b/apps/frps/0.51.2/data/frpc_full.ini @@ -0,0 +1,365 @@ +# [common] is integral section +[common] +# A literal address or host name for IPv6 must be enclosed +# in square brackets, as in "[::1]:80", "[ipv6-host]:http" or "[ipv6-host%zone]:80" +# For single "server_addr" field, no need square brackets, like "server_addr = ::". +server_addr = 0.0.0.0 +server_port = 7000 + +# The maximum amount of time a dial to server will wait for a connect to complete. Default value is 10 seconds. +# dial_server_timeout = 10 + +# dial_server_keepalive specifies the interval between keep-alive probes for an active network connection between frpc and frps. +# If negative, keep-alive probes are disabled. +# dial_server_keepalive = 7200 + +# if you want to connect frps by http proxy or socks5 proxy or ntlm proxy, you can set http_proxy here or in global environment variables +# it only works when protocol is tcp +# http_proxy = http://user:passwd@192.168.1.128:8080 +# http_proxy = socks5://user:passwd@192.168.1.128:1080 +# http_proxy = ntlm://user:passwd@192.168.1.128:2080 + +# console or real logFile path like ./frpc.log +log_file = ./frpc.log + +# trace, debug, info, warn, error +log_level = info + +log_max_days = 3 + +# disable log colors when log_file is console, default is false +disable_log_color = false + +# for authentication, should be same as your frps.ini +# authenticate_heartbeats specifies whether to include authentication token in heartbeats sent to frps. By default, this value is false. +authenticate_heartbeats = false + +# authenticate_new_work_conns specifies whether to include authentication token in new work connections sent to frps. By default, this value is false. +authenticate_new_work_conns = false + +# auth token +token = 12345678 + +authentication_method = + +# oidc_client_id specifies the client ID to use to get a token in OIDC authentication if AuthenticationMethod == "oidc". +# By default, this value is "". +oidc_client_id = + +# oidc_client_secret specifies the client secret to use to get a token in OIDC authentication if AuthenticationMethod == "oidc". +# By default, this value is "". +oidc_client_secret = + +# oidc_audience specifies the audience of the token in OIDC authentication if AuthenticationMethod == "oidc". By default, this value is "". +oidc_audience = + +# oidc_scope specifies the permisssions of the token in OIDC authentication if AuthenticationMethod == "oidc". By default, this value is "". +oidc_scope = + +# oidc_token_endpoint_url specifies the URL which implements OIDC Token Endpoint. +# It will be used to get an OIDC token if AuthenticationMethod == "oidc". By default, this value is "". +oidc_token_endpoint_url = + +# oidc_additional_xxx specifies additional parameters to be sent to the OIDC Token Endpoint. +# For example, if you want to specify the "audience" parameter, you can set as follow. +# frp will add "audience= " "var1= " to the additional parameters. +# oidc_additional_audience = https://dev.auth.com/api/v2/ +# oidc_additional_var1 = foobar + +# set admin address for control frpc's action by http api such as reload +admin_addr = 127.0.0.1 +admin_port = 7400 +admin_user = admin +admin_pwd = admin +# Admin assets directory. By default, these assets are bundled with frpc. +# assets_dir = ./static + +# connections will be established in advance, default value is zero +pool_count = 5 + +# if tcp stream multiplexing is used, default is true, it must be same with frps +# tcp_mux = true + +# specify keep alive interval for tcp mux. +# only valid if tcp_mux is true. +# tcp_mux_keepalive_interval = 60 + +# your proxy name will be changed to {user}.{proxy} +user = your_name + +# decide if exit program when first login failed, otherwise continuous relogin to frps +# default is true +login_fail_exit = true + +# communication protocol used to connect to server +# supports tcp, kcp, quic and websocket now, default is tcp +protocol = tcp + +# set client binding ip when connect server, default is empty. +# only when protocol = tcp or websocket, the value will be used. +connect_server_local_ip = 0.0.0.0 + +# quic protocol options +# quic_keepalive_period = 10 +# quic_max_idle_timeout = 30 +# quic_max_incoming_streams = 100000 + +# if tls_enable is true, frpc will connect frps by tls +tls_enable = true + +# tls_cert_file = client.crt +# tls_key_file = client.key +# tls_trusted_ca_file = ca.crt +# tls_server_name = example.com + +# specify a dns server, so frpc will use this instead of default one +# dns_server = 8.8.8.8 + +# proxy names you want to start separated by ',' +# default is empty, means all proxies +# start = ssh,dns + +# heartbeat configure, it's not recommended to modify the default value +# The default value of heartbeat_interval is 10 and heartbeat_timeout is 90. Set negative value +# to disable it. +# heartbeat_interval = 30 +# heartbeat_timeout = 90 + +# additional meta info for client +meta_var1 = 123 +meta_var2 = 234 + +# specify udp packet size, unit is byte. If not set, the default value is 1500. +# This parameter should be same between client and server. +# It affects the udp and sudp proxy. +udp_packet_size = 1500 + +# include other config files for proxies. +# includes = ./confd/*.ini + +# By default, frpc will connect frps with first custom byte if tls is enabled. +# If DisableCustomTLSFirstByte is true, frpc will not send that custom byte. +disable_custom_tls_first_byte = false + +# Enable golang pprof handlers in admin listener. +# Admin port must be set first. +pprof_enable = false + +# 'ssh' is the unique proxy name +# if user in [common] section is not empty, it will be changed to {user}.{proxy} such as 'your_name.ssh' +[ssh] +# tcp | udp | http | https | stcp | xtcp, default is tcp +type = tcp +local_ip = 127.0.0.1 +local_port = 22 +# limit bandwidth for this proxy, unit is KB and MB +bandwidth_limit = 1MB +# where to limit bandwidth, can be 'client' or 'server', default is 'client' +bandwidth_limit_mode = client +# true or false, if true, messages between frps and frpc will be encrypted, default is false +use_encryption = false +# if true, message will be compressed +use_compression = false +# remote port listen by frps +remote_port = 6001 +# frps will load balancing connections for proxies in same group +group = test_group +# group should have same group key +group_key = 123456 +# enable health check for the backend service, it support 'tcp' and 'http' now +# frpc will connect local service's port to detect it's healthy status +health_check_type = tcp +# health check connection timeout +health_check_timeout_s = 3 +# if continuous failed in 3 times, the proxy will be removed from frps +health_check_max_failed = 3 +# every 10 seconds will do a health check +health_check_interval_s = 10 +# additional meta info for each proxy +meta_var1 = 123 +meta_var2 = 234 + +[ssh_random] +type = tcp +local_ip = 127.0.0.1 +local_port = 22 +# if remote_port is 0, frps will assign a random port for you +remote_port = 0 + +# if you want to expose multiple ports, add 'range:' prefix to the section name +# frpc will generate multiple proxies such as 'tcp_port_6010', 'tcp_port_6011' and so on. +[range:tcp_port] +type = tcp +local_ip = 127.0.0.1 +local_port = 6010-6020,6022,6024-6028 +remote_port = 6010-6020,6022,6024-6028 +use_encryption = false +use_compression = false + +[dns] +type = udp +local_ip = 114.114.114.114 +local_port = 53 +remote_port = 6002 +use_encryption = false +use_compression = false + +[range:udp_port] +type = udp +local_ip = 127.0.0.1 +local_port = 6010-6020 +remote_port = 6010-6020 +use_encryption = false +use_compression = false + +# Resolve your domain names to [server_addr] so you can use http://web01.yourdomain.com to browse web01 and http://web02.yourdomain.com to browse web02 +[web01] +type = http +local_ip = 127.0.0.1 +local_port = 80 +use_encryption = false +use_compression = true +# http username and password are safety certification for http protocol +# if not set, you can access this custom_domains without certification +http_user = admin +http_pwd = admin +# if domain for frps is frps.com, then you can access [web01] proxy by URL http://web01.frps.com +subdomain = web01 +custom_domains = web01.yourdomain.com +# locations is only available for http type +locations = /,/pic +# route requests to this service if http basic auto user is abc +# route_by_http_user = abc +host_header_rewrite = example.com +# params with prefix "header_" will be used to update http request headers +header_X-From-Where = frp +health_check_type = http +# frpc will send a GET http request '/status' to local http service +# http service is alive when it return 2xx http response code +health_check_url = /status +health_check_interval_s = 10 +health_check_max_failed = 3 +health_check_timeout_s = 3 + +[web02] +type = https +local_ip = 127.0.0.1 +local_port = 8000 +use_encryption = false +use_compression = false +subdomain = web01 +custom_domains = web02.yourdomain.com +# if not empty, frpc will use proxy protocol to transfer connection info to your local service +# v1 or v2 or empty +proxy_protocol_version = v2 + +[plugin_unix_domain_socket] +type = tcp +remote_port = 6003 +# if plugin is defined, local_ip and local_port is useless +# plugin will handle connections got from frps +plugin = unix_domain_socket +# params with prefix "plugin_" that plugin needed +plugin_unix_path = /var/run/docker.sock + +[plugin_http_proxy] +type = tcp +remote_port = 6004 +plugin = http_proxy +plugin_http_user = abc +plugin_http_passwd = abc + +[plugin_socks5] +type = tcp +remote_port = 6005 +plugin = socks5 +plugin_user = abc +plugin_passwd = abc + +[plugin_static_file] +type = tcp +remote_port = 6006 +plugin = static_file +plugin_local_path = /var/www/blog +plugin_strip_prefix = static +plugin_http_user = abc +plugin_http_passwd = abc + +[plugin_https2http] +type = https +custom_domains = test.yourdomain.com +plugin = https2http +plugin_local_addr = 127.0.0.1:80 +plugin_crt_path = ./server.crt +plugin_key_path = ./server.key +plugin_host_header_rewrite = 127.0.0.1 +plugin_header_X-From-Where = frp + +[plugin_https2https] +type = https +custom_domains = test.yourdomain.com +plugin = https2https +plugin_local_addr = 127.0.0.1:443 +plugin_crt_path = ./server.crt +plugin_key_path = ./server.key +plugin_host_header_rewrite = 127.0.0.1 +plugin_header_X-From-Where = frp + +[plugin_http2https] +type = http +custom_domains = test.yourdomain.com +plugin = http2https +plugin_local_addr = 127.0.0.1:443 +plugin_host_header_rewrite = 127.0.0.1 +plugin_header_X-From-Where = frp + +[secret_tcp] +# If the type is secret tcp, remote_port is useless +# Who want to connect local port should deploy another frpc with stcp proxy and role is visitor +type = stcp +# sk used for authentication for visitors +sk = abcdefg +local_ip = 127.0.0.1 +local_port = 22 +use_encryption = false +use_compression = false + +# user of frpc should be same in both stcp server and stcp visitor +[secret_tcp_visitor] +# frpc role visitor -> frps -> frpc role server +role = visitor +type = stcp +# the server name you want to visitor +server_name = secret_tcp +sk = abcdefg +# connect this address to visitor stcp server +bind_addr = 127.0.0.1 +bind_port = 9000 +use_encryption = false +use_compression = false + +[p2p_tcp] +type = xtcp +sk = abcdefg +local_ip = 127.0.0.1 +local_port = 22 +use_encryption = false +use_compression = false + +[p2p_tcp_visitor] +role = visitor +type = xtcp +server_name = p2p_tcp +sk = abcdefg +bind_addr = 127.0.0.1 +bind_port = 9001 +use_encryption = false +use_compression = false + +[tcpmuxhttpconnect] +type = tcpmux +multiplexer = httpconnect +local_ip = 127.0.0.1 +local_port = 10701 +custom_domains = tunnel1 +# route_by_http_user = user1 diff --git a/apps/frps/0.51.2/data/frps.ini b/apps/frps/0.51.2/data/frps.ini new file mode 100644 index 000000000..229567a9d --- /dev/null +++ b/apps/frps/0.51.2/data/frps.ini @@ -0,0 +1,2 @@ +[common] +bind_port = 7000 diff --git a/apps/frps/0.51.2/data/frps_full.ini b/apps/frps/0.51.2/data/frps_full.ini new file mode 100644 index 000000000..2d5e08e17 --- /dev/null +++ b/apps/frps/0.51.2/data/frps_full.ini @@ -0,0 +1,168 @@ +# [common] is integral section +[common] +# A literal address or host name for IPv6 must be enclosed +# in square brackets, as in "[::1]:80", "[ipv6-host]:http" or "[ipv6-host%zone]:80" +# For single "bind_addr" field, no need square brackets, like "bind_addr = ::". +bind_addr = 0.0.0.0 +bind_port = 7000 + +# udp port to help make udp hole to penetrate nat +bind_udp_port = 7001 + +# udp port used for kcp protocol, it can be same with 'bind_port'. +# if not set, kcp is disabled in frps. +kcp_bind_port = 7000 + +# udp port used for quic protocol. +# if not set, quic is disabled in frps. +# quic_bind_port = 7002 +# quic protocol options +# quic_keepalive_period = 10 +# quic_max_idle_timeout = 30 +# quic_max_incoming_streams = 100000 + +# specify which address proxy will listen for, default value is same with bind_addr +# proxy_bind_addr = 127.0.0.1 + +# if you want to support virtual host, you must set the http port for listening (optional) +# Note: http port and https port can be same with bind_port +vhost_http_port = 80 +vhost_https_port = 443 + +# response header timeout(seconds) for vhost http server, default is 60s +# vhost_http_timeout = 60 + +# tcpmux_httpconnect_port specifies the port that the server listens for TCP +# HTTP CONNECT requests. If the value is 0, the server will not multiplex TCP +# requests on one single port. If it's not - it will listen on this value for +# HTTP CONNECT requests. By default, this value is 0. +# tcpmux_httpconnect_port = 1337 + +# If tcpmux_passthrough is true, frps won't do any update on traffic. +# tcpmux_passthrough = false + +# set dashboard_addr and dashboard_port to view dashboard of frps +# dashboard_addr's default value is same with bind_addr +# dashboard is available only if dashboard_port is set +dashboard_addr = 0.0.0.0 +dashboard_port = 7500 + +# dashboard user and passwd for basic auth protect +dashboard_user = admin +dashboard_pwd = admin + +# dashboard TLS mode +dashboard_tls_mode = false +# dashboard_tls_cert_file = server.crt +# dashboard_tls_key_file = server.key + +# enable_prometheus will export prometheus metrics on {dashboard_addr}:{dashboard_port} in /metrics api. +enable_prometheus = true + +# dashboard assets directory(only for debug mode) +# assets_dir = ./static + +# console or real logFile path like ./frps.log +log_file = ./frps.log + +# trace, debug, info, warn, error +log_level = info + +log_max_days = 3 + +# disable log colors when log_file is console, default is false +disable_log_color = false + +# DetailedErrorsToClient defines whether to send the specific error (with debug info) to frpc. By default, this value is true. +detailed_errors_to_client = true + +# authentication_method specifies what authentication method to use authenticate frpc with frps. +# If "token" is specified - token will be read into login message. +# If "oidc" is specified - OIDC (Open ID Connect) token will be issued using OIDC settings. By default, this value is "token". +authentication_method = token + +# authenticate_heartbeats specifies whether to include authentication token in heartbeats sent to frps. By default, this value is false. +authenticate_heartbeats = false + +# AuthenticateNewWorkConns specifies whether to include authentication token in new work connections sent to frps. By default, this value is false. +authenticate_new_work_conns = false + +# auth token +token = 12345678 + +# oidc_issuer specifies the issuer to verify OIDC tokens with. +# By default, this value is "". +oidc_issuer = + +# oidc_audience specifies the audience OIDC tokens should contain when validated. +# By default, this value is "". +oidc_audience = + +# oidc_skip_expiry_check specifies whether to skip checking if the OIDC token is expired. +# By default, this value is false. +oidc_skip_expiry_check = false + +# oidc_skip_issuer_check specifies whether to skip checking if the OIDC token's issuer claim matches the issuer specified in OidcIssuer. +# By default, this value is false. +oidc_skip_issuer_check = false + +# heartbeat configure, it's not recommended to modify the default value +# the default value of heartbeat_timeout is 90. Set negative value to disable it. +# heartbeat_timeout = 90 + +# user_conn_timeout configure, it's not recommended to modify the default value +# the default value of user_conn_timeout is 10 +# user_conn_timeout = 10 + +# only allow frpc to bind ports you list, if you set nothing, there won't be any limit +allow_ports = 2000-3000,3001,3003,4000-50000 + +# pool_count in each proxy will change to max_pool_count if they exceed the maximum value +max_pool_count = 5 + +# max ports can be used for each client, default value is 0 means no limit +max_ports_per_client = 0 + +# tls_only specifies whether to only accept TLS-encrypted connections. By default, the value is false. +tls_only = false + +# tls_cert_file = server.crt +# tls_key_file = server.key +# tls_trusted_ca_file = ca.crt + +# if subdomain_host is not empty, you can set subdomain when type is http or https in frpc's configure file +# when subdomain is test, the host used by routing is test.frps.com +subdomain_host = frps.com + +# if tcp stream multiplexing is used, default is true +# tcp_mux = true + +# specify keep alive interval for tcp mux. +# only valid if tcp_mux is true. +# tcp_mux_keepalive_interval = 60 + +# tcp_keepalive specifies the interval between keep-alive probes for an active network connection between frpc and frps. +# If negative, keep-alive probes are disabled. +# tcp_keepalive = 7200 + +# custom 404 page for HTTP requests +# custom_404_page = /path/to/404.html + +# specify udp packet size, unit is byte. If not set, the default value is 1500. +# This parameter should be same between client and server. +# It affects the udp and sudp proxy. +udp_packet_size = 1500 + +# Enable golang pprof handlers in dashboard listener. +# Dashboard port must be set first +pprof_enable = false + +[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 diff --git a/apps/frps/0.51.2/docker-compose.yml b/apps/frps/0.51.2/docker-compose.yml new file mode 100644 index 000000000..9c06326d4 --- /dev/null +++ b/apps/frps/0.51.2/docker-compose.yml @@ -0,0 +1,11 @@ +version: "3" +services: + frps: + container_name: ${CONTAINER_NAME} + restart: always + network_mode: "host" + volumes: + - "${CONFIG_FILE_PATH}:/etc/frp/frps.ini" + image: "snowdreamtech/frps:0.51.2" + labels: + createdBy: "Apps" diff --git a/apps/frps/README.md b/apps/frps/README.md new file mode 100644 index 000000000..4aeec4f20 --- /dev/null +++ b/apps/frps/README.md @@ -0,0 +1,1151 @@ +# frp + +[](https://circleci.com/gh/fatedier/frp) +[](https://github.com/fatedier/frp/releases) + +[README](README.md) | [中文文档](README_zh.md) + + Gold Sponsors
+ + + + + +## What is frp? + +frp is a fast reverse proxy that allows you to expose a local server located behind a NAT or firewall to the Internet. It currently supports **TCP** and **UDP**, as well as **HTTP** and **HTTPS** protocols, enabling requests to be forwarded to internal services via domain name. + +frp also offers a P2P connect mode. + +## Table of Contents + + + +- [frp](#frp) + - [What is frp?](#what-is-frp) + - [Table of Contents](#table-of-contents) + - [Development Status](#development-status) + - [Architecture](#architecture) + - [Example Usage](#example-usage) + - [Access your computer in a LAN network via SSH](#access-your-computer-in-a-lan-network-via-ssh) + - [Accessing Internal Web Services with Custom Domains in LAN](#accessing-internal-web-services-with-custom-domains-in-lan) + - [Forward DNS query requests](#forward-dns-query-requests) + - [Forward Unix Domain Socket](#forward-unix-domain-socket) + - [Expose a simple HTTP file server](#expose-a-simple-http-file-server) + - [Enable HTTPS for a local HTTP(S) service](#enable-https-for-a-local-https-service) + - [Expose your service privately](#expose-your-service-privately) + - [P2P Mode](#p2p-mode) + - [Features](#features) + - [Configuration Files](#configuration-files) + - [Using Environment Variables](#using-environment-variables) + - [Split Configures Into Different Files](#split-configures-into-different-files) + - [Dashboard](#dashboard) + - [Admin UI](#admin-ui) + - [Monitor](#monitor) + - [Prometheus](#prometheus) + - [Authenticating the Client](#authenticating-the-client) + - [Token Authentication](#token-authentication) + - [OIDC Authentication](#oidc-authentication) + - [Encryption and Compression](#encryption-and-compression) + - [TLS](#tls) + - [Hot-Reloading frpc configuration](#hot-reloading-frpc-configuration) + - [Get proxy status from client](#get-proxy-status-from-client) + - [Only allowing certain ports on the server](#only-allowing-certain-ports-on-the-server) + - [Port Reuse](#port-reuse) + - [Bandwidth Limit](#bandwidth-limit) + - [For Each Proxy](#for-each-proxy) + - [TCP Stream Multiplexing](#tcp-stream-multiplexing) + - [Support KCP Protocol](#support-kcp-protocol) + - [Support QUIC Protocol](#support-quic-protocol) + - [Connection Pooling](#connection-pooling) + - [Load balancing](#load-balancing) + - [Service Health Check](#service-health-check) + - [Rewriting the HTTP Host Header](#rewriting-the-http-host-header) + - [Setting other HTTP Headers](#setting-other-http-headers) + - [Get Real IP](#get-real-ip) + - [HTTP X-Forwarded-For](#http-x-forwarded-for) + - [Proxy Protocol](#proxy-protocol) + - [Require HTTP Basic Auth (Password) for Web Services](#require-http-basic-auth-password-for-web-services) + - [Custom Subdomain Names](#custom-subdomain-names) + - [URL Routing](#url-routing) + - [TCP Port Multiplexing](#tcp-port-multiplexing) + - [Connecting to frps via HTTP PROXY](#connecting-to-frps-via-http-proxy) + - [Range ports mapping](#range-ports-mapping) + - [Client Plugins](#client-plugins) + - [Server Manage Plugins](#server-manage-plugins) + - [Development Plan](#development-plan) + - [Contributing](#contributing) + - [Donation](#donation) + - [GitHub Sponsors](#github-sponsors) + - [PayPal](#paypal) + + + +## Development Status + +frp is currently under development. You can try the latest release version in the `master` branch, or use the `dev` branch to access the version currently in development. + +We are currently working on version 2 and attempting to perform some code refactoring and improvements. However, please note that it will not be compatible with version 1. + +We will transition from version 0 to version 1 at the appropriate time and will only accept bug fixes and improvements, rather than big feature requests. + +## Architecture + + + +## Example Usage + +To begin, download the latest program for your operating system and architecture from the [Release](https://github.com/fatedier/frp/releases) page. + +Next, place the `frps` binary and `frps.ini` configuration file on Server A, which has a public IP address. + +Finally, place the `frpc` binary and `frpc.ini` configuration file on Server B, which is located on a LAN that cannot be directly accessed from the public internet. + +### Access your computer in a LAN network via SSH + +1. Modify `frps.ini` on server A by setting the `bind_port` for frp clients to connect to: + + ```ini + # frps.ini + [common] + bind_port = 7000 + ``` + +2. Start `frps` on server A: + + `./frps -c ./frps.ini` + +3. Modify `frpc.ini` on server B and set the `server_addr` field to the public IP address of your frps server: + + ```ini + # frpc.ini + [common] + server_addr = x.x.x.x + server_port = 7000 + + [ssh] + type = tcp + local_ip = 127.0.0.1 + local_port = 22 + remote_port = 6000 + ``` + +Note that the `local_port` (listened on the client) and `remote_port` (exposed on the server) are used for traffic going in and out of the frp system, while the `server_port` is used for communication between frps and frpc. + +4. Start `frpc` on server B: + + `./frpc -c ./frpc.ini` + +5. To access server B from another machine through server A via SSH (assuming the username is `test`), use the following command: + + `ssh -oPort=6000 test@x.x.x.x` + +### Accessing Internal Web Services with Custom Domains in LAN + +Sometimes we need to expose a local web service behind a NAT network to others for testing purposes with our own domain name. + +Unfortunately, we cannot resolve a domain name to a local IP. However, we can use frp to expose an HTTP(S) service. + +1. Modify `frps.ini` and set the HTTP port for vhost to 8080: + + ```ini + # frps.ini + [common] + bind_port = 7000 + vhost_http_port = 8080 + ``` + +2. Start `frps`: + + `./frps -c ./frps.ini` + +3. Modify `frpc.ini` and set `server_addr` to the IP address of the remote frps server. Specify the `local_port` of your web service: + + ```ini + # frpc.ini + [common] + server_addr = x.x.x.x + server_port = 7000 + + [web] + type = http + local_port = 80 + custom_domains = www.example.com + ``` + +4. Start `frpc`: + + `./frpc -c ./frpc.ini` + +5. Map the A record of `www.example.com` to either the public IP of the remote frps server or a CNAME record pointing to your original domain. + +6. Visit your local web service using url `http://www.example.com:8080`. + +### Forward DNS query requests + +1. Modify `frps.ini`: + + ```ini + # frps.ini + [common] + bind_port = 7000 + ``` + +2. Start `frps`: + + `./frps -c ./frps.ini` + +3. Modify `frpc.ini` and set `server_addr` to the IP address of the remote frps server. Forward DNS query requests to the Google Public DNS server `8.8.8.8:53`: + + ```ini + # frpc.ini + [common] + server_addr = x.x.x.x + server_port = 7000 + + [dns] + type = udp + local_ip = 8.8.8.8 + local_port = 53 + remote_port = 6000 + ``` + +4. Start frpc: + + `./frpc -c ./frpc.ini` + +5. Test DNS resolution using the `dig` command: + + `dig @x.x.x.x -p 6000 www.google.com` + +### Forward Unix Domain Socket + +Expose a Unix domain socket (e.g. the Docker daemon socket) as TCP. + +Configure `frps` as above. + +1. Start `frpc` with the following configuration: + + ```ini + # frpc.ini + [common] + server_addr = x.x.x.x + server_port = 7000 + + [unix_domain_socket] + type = tcp + remote_port = 6000 + plugin = unix_domain_socket + plugin_unix_path = /var/run/docker.sock + ``` + +2. Test the configuration by getting the docker version using `curl`: + + `curl http://x.x.x.x:6000/version` + +### Expose a simple HTTP file server + +Expose a simple HTTP file server to access files stored in the LAN from the public Internet. + +Configure `frps` as described above, then: + +1. Start `frpc` with the following configuration: + + ```ini + # frpc.ini + [common] + server_addr = x.x.x.x + server_port = 7000 + + [test_static_file] + type = tcp + remote_port = 6000 + plugin = static_file + plugin_local_path = /tmp/files + plugin_strip_prefix = static + plugin_http_user = abc + plugin_http_passwd = abc + ``` + +2. Visit `http://x.x.x.x:6000/static/` from your browser and specify correct username and password to view files in `/tmp/files` on the `frpc` machine. + +### Enable HTTPS for a local HTTP(S) service + +You may substitute `https2https` for the plugin, and point the `plugin_local_addr` to a HTTPS endpoint. + +1. Start `frpc` with the following configuration: + + ```ini + # frpc.ini + [common] + server_addr = x.x.x.x + server_port = 7000 + + [test_https2http] + type = https + custom_domains = test.example.com + + plugin = https2http + plugin_local_addr = 127.0.0.1:80 + plugin_crt_path = ./server.crt + plugin_key_path = ./server.key + plugin_host_header_rewrite = 127.0.0.1 + plugin_header_X-From-Where = frp + ``` + +2. Visit `https://test.example.com`. + +### Expose your service privately + +To mitigate risks associated with exposing certain services directly to the public network, STCP (Secret TCP) mode requires a preshared key to be used for access to the service from other clients. + +Configure `frps` same as above. + +1. Start `frpc` on machine B with the following config. This example is for exposing the SSH service (port 22), and note the `sk` field for the preshared key, and that the `remote_port` field is removed here: + + ```ini + # frpc.ini + [common] + server_addr = x.x.x.x + server_port = 7000 + + [secret_ssh] + type = stcp + sk = abcdefg + local_ip = 127.0.0.1 + local_port = 22 + ``` + +2. Start another `frpc` (typically on another machine C) with the following config to access the SSH service with a security key (`sk` field): + + ```ini + # frpc.ini + [common] + server_addr = x.x.x.x + server_port = 7000 + + [secret_ssh_visitor] + type = stcp + role = visitor + server_name = secret_ssh + sk = abcdefg + bind_addr = 127.0.0.1 + bind_port = 6000 + ``` + +3. On machine C, connect to SSH on machine B, using this command: + + `ssh -oPort=6000 127.0.0.1` + +### P2P Mode + +**xtcp** is designed to transmit large amounts of data directly between clients. A frps server is still needed, as P2P here only refers to the actual data transmission. + +Note that it may not work with all types of NAT devices. You might want to fallback to stcp if xtcp doesn't work. + +1. In `frps.ini` configure a UDP port for xtcp: + + ```ini + # frps.ini + bind_udp_port = 7001 + ``` + +2. Start `frpc` on machine B, and expose the SSH port. Note that the `remote_port` field is removed: + + ```ini + # frpc.ini + [common] + server_addr = x.x.x.x + server_port = 7000 + + [p2p_ssh] + type = xtcp + sk = abcdefg + local_ip = 127.0.0.1 + local_port = 22 + ``` + +3. Start another `frpc` (typically on another machine C) with the configuration to connect to SSH using P2P mode: + + ```ini + # frpc.ini + [common] + server_addr = x.x.x.x + server_port = 7000 + + [p2p_ssh_visitor] + type = xtcp + role = visitor + server_name = p2p_ssh + sk = abcdefg + bind_addr = 127.0.0.1 + bind_port = 6000 + ``` + +4. On machine C, connect to SSH on machine B, using this command: + + `ssh -oPort=6000 127.0.0.1` + +## Features + +### Configuration Files + +Read the full example configuration files to find out even more features not described here. + +[Full configuration file for frps (Server)](./conf/frps_full.ini) + +[Full configuration file for frpc (Client)](./conf/frpc_full.ini) + +### Using Environment Variables + +Environment variables can be referenced in the configuration file, using Go's standard format: + +```ini +# frpc.ini +[common] +server_addr = {{ .Envs.FRP_SERVER_ADDR }} +server_port = 7000 + +[ssh] +type = tcp +local_ip = 127.0.0.1 +local_port = 22 +remote_port = {{ .Envs.FRP_SSH_REMOTE_PORT }} +``` + +With the config above, variables can be passed into `frpc` program like this: + +``` +export FRP_SERVER_ADDR="x.x.x.x" +export FRP_SSH_REMOTE_PORT="6000" +./frpc -c ./frpc.ini +``` + +`frpc` will render configuration file template using OS environment variables. Remember to prefix your reference with `.Envs`. + +### Split Configures Into Different Files + +You can split multiple proxy configs into different files and include them in the main file. + +```ini +# frpc.ini +[common] +server_addr = x.x.x.x +server_port = 7000 +includes=./confd/*.ini +``` + +```ini +# ./confd/test.ini +[ssh] +type = tcp +local_ip = 127.0.0.1 +local_port = 22 +remote_port = 6000 +``` + +### Dashboard + +Check frp's status and proxies' statistics information by Dashboard. + +Configure a port for dashboard to enable this feature: + +```ini +[common] +dashboard_port = 7500 +# dashboard's username and password are both optional +dashboard_user = admin +dashboard_pwd = admin +``` + +Then visit `http://[server_addr]:7500` to see the dashboard, with username and password both being `admin`. + +Additionally, you can use HTTPS port by using your domains wildcard or normal SSL certificate: + +```ini +[common] +dashboard_port = 7500 +# dashboard's username and password are both optional +dashboard_user = admin +dashboard_pwd = admin +dashboard_tls_mode = true +dashboard_tls_cert_file = server.crt +dashboard_tls_key_file = server.key +``` + +Then visit `https://[server_addr]:7500` to see the dashboard in secure HTTPS connection, with username and password both being `admin`. + + + +### Admin UI + +The Admin UI helps you check and manage frpc's configuration. + +Configure an address for admin UI to enable this feature: + +```ini +[common] +admin_addr = 127.0.0.1 +admin_port = 7400 +admin_user = admin +admin_pwd = admin +``` + +Then visit `http://127.0.0.1:7400` to see admin UI, with username and password both being `admin`. + +### Monitor + +When dashboard is enabled, frps will save monitor data in cache. It will be cleared after process restart. + +Prometheus is also supported. + +#### Prometheus + +Enable dashboard first, then configure `enable_prometheus = true` in `frps.ini`. + +`http://{dashboard_addr}/metrics` will provide prometheus monitor data. + +### Authenticating the Client + +There are 2 authentication methods to authenticate frpc with frps. + +You can decide which one to use by configuring `authentication_method` under `[common]` in `frpc.ini` and `frps.ini`. + +Configuring `authenticate_heartbeats = true` under `[common]` will use the configured authentication method to add and validate authentication on every heartbeat between frpc and frps. + +Configuring `authenticate_new_work_conns = true` under `[common]` will do the same for every new work connection between frpc and frps. + +#### Token Authentication + +When specifying `authentication_method = token` under `[common]` in `frpc.ini` and `frps.ini` - token based authentication will be used. + +Make sure to specify the same `token` in the `[common]` section in `frps.ini` and `frpc.ini` for frpc to pass frps validation + +#### OIDC Authentication + +When specifying `authentication_method = oidc` under `[common]` in `frpc.ini` and `frps.ini` - OIDC based authentication will be used. + +OIDC stands for OpenID Connect, and the flow used is called [Client Credentials Grant](https://tools.ietf.org/html/rfc6749#section-4.4). + +To use this authentication type - configure `frpc.ini` and `frps.ini` as follows: + +```ini +# frps.ini +[common] +authentication_method = oidc +oidc_issuer = https://example-oidc-issuer.com/ +oidc_audience = https://oidc-audience.com/.default +``` + +```ini +# frpc.ini +[common] +authentication_method = oidc +oidc_client_id = 98692467-37de-409a-9fac-bb2585826f18 # Replace with OIDC client ID +oidc_client_secret = oidc_secret +oidc_audience = https://oidc-audience.com/.default +oidc_token_endpoint_url = https://example-oidc-endpoint.com/oauth2/v2.0/token +``` + +### Encryption and Compression + +The features are off by default. You can turn on encryption and/or compression: + +```ini +# frpc.ini +[ssh] +type = tcp +local_port = 22 +remote_port = 6000 +use_encryption = true +use_compression = true +``` + +#### TLS + +frp supports the TLS protocol between `frpc` and `frps` since v0.25.0. + +For port multiplexing, frp sends a first byte `0x17` to dial a TLS connection. + +Configure `tls_enable = true` in the `[common]` section to `frpc.ini` to enable this feature. + +To **enforce** `frps` to only accept TLS connections - configure `tls_only = true` in the `[common]` section in `frps.ini`. **This is optional.** + +**`frpc` TLS settings (under the `[common]` section):** +```ini +tls_enable = true +tls_cert_file = certificate.crt +tls_key_file = certificate.key +tls_trusted_ca_file = ca.crt +``` + +**`frps` TLS settings (under the `[common]` section):** +```ini +tls_only = true +tls_enable = true +tls_cert_file = certificate.crt +tls_key_file = certificate.key +tls_trusted_ca_file = ca.crt +``` + +You will need **a root CA cert** and **at least one SSL/TLS certificate**. It **can** be self-signed or regular (such as Let's Encrypt or another SSL/TLS certificate provider). + +If you using `frp` via IP address and not hostname, make sure to set the appropriate IP address in the Subject Alternative Name (SAN) area when generating SSL/TLS Certificates. + +Given an example: + +* Prepare openssl config file. It exists at `/etc/pki/tls/openssl.cnf` in Linux System and `/System/Library/OpenSSL/openssl.cnf` in MacOS, and you can copy it to current path, like `cp /etc/pki/tls/openssl.cnf ./my-openssl.cnf`. If not, you can build it by yourself, like: +``` +cat > my-openssl.cnf << EOF +[ ca ] +default_ca = CA_default +[ CA_default ] +x509_extensions = usr_cert +[ req ] +default_bits = 2048 +default_md = sha256 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca +string_mask = utf8only +[ req_distinguished_name ] +[ req_attributes ] +[ usr_cert ] +basicConstraints = CA:FALSE +nsComment = "OpenSSL Generated Certificate" +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer +[ v3_ca ] +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer +basicConstraints = CA:true +EOF +``` + +* build ca certificates: +``` +openssl genrsa -out ca.key 2048 +openssl req -x509 -new -nodes -key ca.key -subj "/CN=example.ca.com" -days 5000 -out ca.crt +``` + +* build frps certificates: +``` +openssl genrsa -out server.key 2048 + +openssl req -new -sha256 -key server.key \ + -subj "/C=XX/ST=DEFAULT/L=DEFAULT/O=DEFAULT/CN=server.com" \ + -reqexts SAN \ + -config <(cat my-openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:localhost,IP:127.0.0.1,DNS:example.server.com")) \ + -out server.csr + +openssl x509 -req -days 365 -sha256 \ + -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \ + -extfile <(printf "subjectAltName=DNS:localhost,IP:127.0.0.1,DNS:example.server.com") \ + -out server.crt +``` + +* build frpc certificates: +``` +openssl genrsa -out client.key 2048 +openssl req -new -sha256 -key client.key \ + -subj "/C=XX/ST=DEFAULT/L=DEFAULT/O=DEFAULT/CN=client.com" \ + -reqexts SAN \ + -config <(cat my-openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:client.com,DNS:example.client.com")) \ + -out client.csr + +openssl x509 -req -days 365 -sha256 \ + -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial \ + -extfile <(printf "subjectAltName=DNS:client.com,DNS:example.client.com") \ + -out client.crt +``` + +### Hot-Reloading frpc configuration + +The `admin_addr` and `admin_port` fields are required for enabling HTTP API: + +```ini +# frpc.ini +[common] +admin_addr = 127.0.0.1 +admin_port = 7400 +``` + +Then run command `frpc reload -c ./frpc.ini` and wait for about 10 seconds to let `frpc` create or update or remove proxies. + +**Note that parameters in [common] section won't be modified except 'start'.** + +You can run command `frpc verify -c ./frpc.ini` before reloading to check if there are config errors. + +### Get proxy status from client + +Use `frpc status -c ./frpc.ini` to get status of all proxies. The `admin_addr` and `admin_port` fields are required for enabling HTTP API. + +### Only allowing certain ports on the server + +`allow_ports` in `frps.ini` is used to avoid abuse of ports: + +```ini +# frps.ini +[common] +allow_ports = 2000-3000,3001,3003,4000-50000 +``` + +`allow_ports` consists of specific ports or port ranges (lowest port number, dash `-`, highest port number), separated by comma `,`. + +### Port Reuse + +`vhost_http_port` and `vhost_https_port` in frps can use same port with `bind_port`. frps will detect the connection's protocol and handle it correspondingly. + +We would like to try to allow multiple proxies bind a same remote port with different protocols in the future. + +### Bandwidth Limit + +#### For Each Proxy + +```ini +# frpc.ini +[ssh] +type = tcp +local_port = 22 +remote_port = 6000 +bandwidth_limit = 1MB +``` + +Set `bandwidth_limit` in each proxy's configure to enable this feature. Supported units are `MB` and `KB`. + +Set `bandwidth_limit_mode` to `client` or `server` to limit bandwidth on the client or server side. Default is `client`. + +### TCP Stream Multiplexing + +frp supports tcp stream multiplexing since v0.10.0 like HTTP2 Multiplexing, in which case all logic connections to the same frpc are multiplexed into the same TCP connection. + +You can disable this feature by modify `frps.ini` and `frpc.ini`: + +```ini +# frps.ini and frpc.ini, must be same +[common] +tcp_mux = false +``` + +### Support KCP Protocol + +KCP is a fast and reliable protocol that can achieve the transmission effect of a reduction of the average latency by 30% to 40% and reduction of the maximum delay by a factor of three, at the cost of 10% to 20% more bandwidth wasted than TCP. + +KCP mode uses UDP as the underlying transport. Using KCP in frp: + +1. Enable KCP in frps: + + ```ini + # frps.ini + [common] + bind_port = 7000 + # Specify a UDP port for KCP. + kcp_bind_port = 7000 + ``` + + The `kcp_bind_port` number can be the same number as `bind_port`, since `bind_port` field specifies a TCP port. + +2. Configure `frpc.ini` to use KCP to connect to frps: + + ```ini + # frpc.ini + [common] + server_addr = x.x.x.x + # Same as the 'kcp_bind_port' in frps.ini + server_port = 7000 + protocol = kcp + ``` + +### Support QUIC Protocol + +QUIC is a new multiplexed transport built on top of UDP. + +Using QUIC in frp: + +1. Enable QUIC in frps: + + ```ini + # frps.ini + [common] + bind_port = 7000 + # Specify a UDP port for QUIC. + quic_bind_port = 7000 + ``` + + The `quic_bind_port` number can be the same number as `bind_port`, since `bind_port` field specifies a TCP port. + +2. Configure `frpc.ini` to use QUIC to connect to frps: + + ```ini + # frpc.ini + [common] + server_addr = x.x.x.x + # Same as the 'quic_bind_port' in frps.ini + server_port = 7000 + protocol = quic + ``` + +### Connection Pooling + +By default, frps creates a new frpc connection to the backend service upon a user request. With connection pooling, frps keeps a certain number of pre-established connections, reducing the time needed to establish a connection. + +This feature is suitable for a large number of short connections. + +1. Configure the limit of pool count each proxy can use in `frps.ini`: + + ```ini + # frps.ini + [common] + max_pool_count = 5 + ``` + +2. Enable and specify the number of connection pool: + + ```ini + # frpc.ini + [common] + pool_count = 1 + ``` + +### Load balancing + +Load balancing is supported by `group`. + +This feature is only available for types `tcp`, `http`, `tcpmux` now. + +```ini +# frpc.ini +[test1] +type = tcp +local_port = 8080 +remote_port = 80 +group = web +group_key = 123 + +[test2] +type = tcp +local_port = 8081 +remote_port = 80 +group = web +group_key = 123 +``` + +`group_key` is used for authentication. + +Connections to port 80 will be dispatched to proxies in the same group randomly. + +For type `tcp`, `remote_port` in the same group should be the same. + +For type `http`, `custom_domains`, `subdomain`, `locations` should be the same. + +### Service Health Check + +Health check feature can help you achieve high availability with load balancing. + +Add `health_check_type = tcp` or `health_check_type = http` to enable health check. + +With health check type **tcp**, the service port will be pinged (TCPing): + +```ini +# frpc.ini +[test1] +type = tcp +local_port = 22 +remote_port = 6000 +# Enable TCP health check +health_check_type = tcp +# TCPing timeout seconds +health_check_timeout_s = 3 +# If health check failed 3 times in a row, the proxy will be removed from frps +health_check_max_failed = 3 +# A health check every 10 seconds +health_check_interval_s = 10 +``` + +With health check type **http**, an HTTP request will be sent to the service and an HTTP 2xx OK response is expected: + +```ini +# frpc.ini +[web] +type = http +local_ip = 127.0.0.1 +local_port = 80 +custom_domains = test.example.com +# Enable HTTP health check +health_check_type = http +# frpc will send a GET request to '/status' +# and expect an HTTP 2xx OK response +health_check_url = /status +health_check_timeout_s = 3 +health_check_max_failed = 3 +health_check_interval_s = 10 +``` + +### Rewriting the HTTP Host Header + +By default frp does not modify the tunneled HTTP requests at all as it's a byte-for-byte copy. + +However, speaking of web servers and HTTP requests, your web server might rely on the `Host` HTTP header to determine the website to be accessed. frp can rewrite the `Host` header when forwarding the HTTP requests, with the `host_header_rewrite` field: + +```ini +# frpc.ini +[web] +type = http +local_port = 80 +custom_domains = test.example.com +host_header_rewrite = dev.example.com +``` + +The HTTP request will have the `Host` header rewritten to `Host: dev.example.com` when it reaches the actual web server, although the request from the browser probably has `Host: test.example.com`. + +### Setting other HTTP Headers + +Similar to `Host`, You can override other HTTP request headers with proxy type `http`. + +```ini +# frpc.ini +[web] +type = http +local_port = 80 +custom_domains = test.example.com +host_header_rewrite = dev.example.com +header_X-From-Where = frp +``` + +Note that parameter(s) prefixed with `header_` will be added to HTTP request headers. + +In this example, it will set header `X-From-Where: frp` in the HTTP request. + +### Get Real IP + +#### HTTP X-Forwarded-For + +This feature is for http proxy only. + +You can get user's real IP from HTTP request headers `X-Forwarded-For`. + +#### Proxy Protocol + +frp supports Proxy Protocol to send user's real IP to local services. It support all types except UDP. + +Here is an example for https service: + +```ini +# frpc.ini +[web] +type = https +local_port = 443 +custom_domains = test.example.com + +# now v1 and v2 are supported +proxy_protocol_version = v2 +``` + +You can enable Proxy Protocol support in nginx to expose user's real IP in HTTP header `X-Real-IP`, and then read `X-Real-IP` header in your web service for the real IP. + +### Require HTTP Basic Auth (Password) for Web Services + +Anyone who can guess your tunnel URL can access your local web server unless you protect it with a password. + +This enforces HTTP Basic Auth on all requests with the username and password specified in frpc's configure file. + +It can only be enabled when proxy type is http. + +```ini +# frpc.ini +[web] +type = http +local_port = 80 +custom_domains = test.example.com +http_user = abc +http_pwd = abc +``` + +Visit `http://test.example.com` in the browser and now you are prompted to enter the username and password. + +### Custom Subdomain Names + +It is convenient to use `subdomain` configure for http and https types when many people share one frps server. + +```ini +# frps.ini +subdomain_host = frps.com +``` + +Resolve `*.frps.com` to the frps server's IP. This is usually called a Wildcard DNS record. + +```ini +# frpc.ini +[web] +type = http +local_port = 80 +subdomain = test +``` + +Now you can visit your web service on `test.frps.com`. + +Note that if `subdomain_host` is not empty, `custom_domains` should not be the subdomain of `subdomain_host`. + +### URL Routing + +frp supports forwarding HTTP requests to different backend web services by url routing. + +`locations` specifies the prefix of URL used for routing. frps first searches for the most specific prefix location given by literal strings regardless of the listed order. + +```ini +# frpc.ini +[web01] +type = http +local_port = 80 +custom_domains = web.example.com +locations = / + +[web02] +type = http +local_port = 81 +custom_domains = web.example.com +locations = /news,/about +``` + +HTTP requests with URL prefix `/news` or `/about` will be forwarded to **web02** and other requests to **web01**. + +### TCP Port Multiplexing + +frp supports receiving TCP sockets directed to different proxies on a single port on frps, similar to `vhost_http_port` and `vhost_https_port`. + +The only supported TCP port multiplexing method available at the moment is `httpconnect` - HTTP CONNECT tunnel. + +When setting `tcpmux_httpconnect_port` to anything other than 0 in frps under `[common]`, frps will listen on this port for HTTP CONNECT requests. + +The host of the HTTP CONNECT request will be used to match the proxy in frps. Proxy hosts can be configured in frpc by configuring `custom_domain` and / or `subdomain` under `type = tcpmux` proxies, when `multiplexer = httpconnect`. + +For example: + +```ini +# frps.ini +[common] +bind_port = 7000 +tcpmux_httpconnect_port = 1337 +``` + +```ini +# frpc.ini +[common] +server_addr = x.x.x.x +server_port = 7000 + +[proxy1] +type = tcpmux +multiplexer = httpconnect +custom_domains = test1 +local_port = 80 + +[proxy2] +type = tcpmux +multiplexer = httpconnect +custom_domains = test2 +local_port = 8080 +``` + +In the above configuration - frps can be contacted on port 1337 with a HTTP CONNECT header such as: + +``` +CONNECT test1 HTTP/1.1\r\n\r\n +``` +and the connection will be routed to `proxy1`. + +### Connecting to frps via HTTP PROXY + +frpc can connect to frps using HTTP proxy if you set OS environment variable `HTTP_PROXY`, or if `http_proxy` is set in frpc.ini file. + +It only works when protocol is tcp. + +```ini +# frpc.ini +[common] +server_addr = x.x.x.x +server_port = 7000 +http_proxy = http://user:pwd@192.168.1.128:8080 +``` + +### Range ports mapping + +Proxy with names that start with `range:` will support mapping range ports. + +```ini +# frpc.ini +[range:test_tcp] +type = tcp +local_ip = 127.0.0.1 +local_port = 6000-6006,6007 +remote_port = 6000-6006,6007 +``` + +frpc will generate 8 proxies like `test_tcp_0`, `test_tcp_1`, ..., `test_tcp_7`. + +### Client Plugins + +frpc only forwards requests to local TCP or UDP ports by default. + +Plugins are used for providing rich features. There are built-in plugins such as `unix_domain_socket`, `http_proxy`, `socks5`, `static_file`, `http2https`, `https2http`, `https2https` and you can see [example usage](#example-usage). + +Specify which plugin to use with the `plugin` parameter. Configuration parameters of plugin should be started with `plugin_`. `local_ip` and `local_port` are not used for plugin. + +Using plugin **http_proxy**: + +```ini +# frpc.ini +[http_proxy] +type = tcp +remote_port = 6000 +plugin = http_proxy +plugin_http_user = abc +plugin_http_passwd = abc +``` + +`plugin_http_user` and `plugin_http_passwd` are configuration parameters used in `http_proxy` plugin. + +### Server Manage Plugins + +Read the [document](/doc/server_plugin.md). + +Find more plugins in [gofrp/plugin](https://github.com/gofrp/plugin). + +## Development Plan + +* Log HTTP request information in frps. + +## Contributing + +Interested in getting involved? We would like to help you! + +* Take a look at our [issues list](https://github.com/fatedier/frp/issues) and consider sending a Pull Request to **dev branch**. +* If you want to add a new feature, please create an issue first to describe the new feature, as well as the implementation approach. Once a proposal is accepted, create an implementation of the new features and submit it as a pull request. +* Sorry for my poor English. Improvements for this document are welcome, even some typo fixes. +* If you have great ideas, send an email to fatedier@gmail.com. + +**Note: We prefer you to give your advise in [issues](https://github.com/fatedier/frp/issues), so others with a same question can search it quickly and we don't need to answer them repeatedly.** + +## Donation + +If frp helps you a lot, you can support us by: + +### GitHub Sponsors + +Support us by [Github Sponsors](https://github.com/sponsors/fatedier). + +You can have your company's logo placed on README file of this project. + +### PayPal + +Donate money by [PayPal](https://www.paypal.me/fatedier) to my account **fatedier@gmail.com**. + diff --git a/apps/frps/data.yml b/apps/frps/data.yml new file mode 100644 index 000000000..74c6e0729 --- /dev/null +++ b/apps/frps/data.yml @@ -0,0 +1,20 @@ +name: frps-frp服务端 +tags: + - 工具 +title: frp是一种反向代理工具,常用于内网穿透(服务端) +type: 工具 +description: frp是一种反向代理工具,常用于内网穿透(服务端) +additionalProperties: + key: frps + name: frps-frp服务端 + tags: + - Tool + shortDescZh: frp是一种反向代理工具,常用于内网穿透(服务端) + shortDescEn: frp is a reverse proxy tool that is commonly used for intranet penetration(Server) + type: tool + crossVersionUpdate: true + limit: 0 + recommend: 0 + website: https://github.com/fatedier/frp + github: https://github.com/fatedier/frp + document: https://github.com/fatedier/frp/blob/dev/README_zh.md diff --git a/apps/frps/logo.png b/apps/frps/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..023fe72df4c2c99878a8f9c803ecbe3f1e4204cf GIT binary patch literal 26073 zcmV;~WhR=5P)dlhd47M)>ANhu zin5D5AC_BAxpU6>&NJVq%rk_&^0}q7jAeN~2$RT(Z%d^r)T&_zXC?Ycp{hS=dGOK+ znKmaVV_A|9s%+=@z0x(I-Q9p5EoCfG3IierfQuh}ug}t^{zo+kb#xPnLr93BjW7eW zp`0X>Y-MihCs8k0tnbCVGF$4!#nkZ1!f)+g<(;ymg4JGNe|Fgm=+7XfWh~2Af{`Kv z07sR5`t?mF>xWxOoZ3jLpp_&*WdFdyfw7MXX5_MN>Id^|fpmWV#`*bAc-!^@`?JYj zKzBt_EHD~`$)o|`$bYOqtJ)-{)**3Biw9zm0Z0?TAObT03ZP8(juQYdK>(0ogKQY& zv3{$V_|7-aANY6g_ew{D%H7}FD?69HfbNVi6DlD+jy!Qe&9Q48adQ>qBv%_70t}eI zEC7%KlfAp{3w!^0cickS5nuwC4L|_PEHDaLFCQ#2(_T9_|8W371uHxc cw($frND_P`I2J-6DZ?`#(mAkxGD7+@v>NJs#E2(3B5TfHPN6X1_N)Usi; NEik&G{9h}-Y_VHerA8POn>gY;x_ ;-lQvKP=X2^)MB z6&32r&10{whMc;Q#6SoF5gdTYQVYml#K;%siG359J6=Am;KkrfOsIft^8 vS>c-yGX}>)Z!VKCm9xYdE$idjai9iUm%D z@aV WU#*&dirjE_lhF#07C@_^$tZ(16vn zCp^9FxV0IXs@3$3W(EYaBVYsrMuU`KgF=|vBBXC#a&EzWMBu%KV^sD6I>wWao4?`s zb)2}ZiW0|V+5xg4Mv*it_f6<&Z=9O9002 Uz0gM5ZV#Z+TcL$5s>93trI3EB|!7BAUOzJCcIDT~j9Ru=7^FJN2MkjBs zCRMs!N`Ror`X&rRC=ie@cvE3AbJIJg=KU7HE_bWN{o98<-SE>5t@5TCMgf?i7!JTf z1BL;W!v;mrmHQ`KZ>Tu4=yd>Jd4Bzs1az2tUiic(1D3R8Pp^Wyrk;d=5Qc~uAnQmb zh<<{(SULAh+NW{O1BVRV5 *bdHSfdd7 zuVa%fGv=S^8lzuPV1K0m9oB%%5aSorT~(#U^g0rQAVfefY;Z*72u87V<`2tlo&M~J zgWm=4 xD zrj2Jfvd^!H8AZ^wh0?ic=~;OXeANucJsZ$*Fg&{cxHUTa)@l|fWWpMmVE|GfpiuI< zVwIk`?DT?%0N4bi5U<^B66=&lKHKn}^{sMFwWi^Q83ODOvtZ9~1f$sKclVJ|!*NfK zIPRH%jsf}9N7o(nk<)8V73jN7B4qF}m_Y(WG)U;}gOzi~w+?Q+BXz(5EdWz#8ANx} zYNcf?%iRpWGA@%hKYhlO>WrLTYtYXcj>cg?XuyD>dcmNGor?W9J+<;%MXv$aqxtn7 z2k0 Bhe`p+eWQ! zRX0~T^sVh0Ah08t1;DHU0cOf$CsWA!?jr{_-1^X@1GWNtmf_g*0UhU-2}mv5=j)OV7{0mk4H0F&uj=pi?OpsSuDSE?9r;8Yg*MHK`NQ?YQ6opiuCJ z;$%9t?6myf1Nht#zHTS6eC@-ZZT#Mb7E09_agb()WaAJZHK3WH5-=zv=ly-)On?2{ zf`0($K1T3ol%5CZ*f4wAqw7b0=p<6rP~Y7yBp|{DpAZ1kK*7z$34Pb;gFn6PSL4TT z2llLCHZG-QEXyau0K^qsp{`tb PTH?BYa>Y7%<5GBbiH#Lg_p-Hn(NwqbKgOE`E+ZUP9M; z!J-X$OE&hMR^y1Pw;B+bjdZPJ4KN5YmkkD+O! fA;H5F1BWe$9r7z$^yB(M8br9EG(vKXl$ f?xfA}X=MLyn7Ae_ZmV+W zYZ O Iw9V8M2lk2LU*`CC_hZNbL#{Bu;WN~P=! zhrQB~FjE-FCG*#gJ)o@ivFv|rV$9#lSWus#1zR;ey4AsgdV>Y^Jm~SQEu){>c*~Wq zec0DOE_99#CB-5PiX%>6bYQ44qO`QEa~ tf2Jr4|BklaynZRRq3|*yz|~F zczbp4Id%2POSWYM009_{ERjKB@75>w9lZI*S1ONtr%P>SCM<@+1j+z5;<&0s-CpI; z*-ZujvzB0DTW&$XFy*n% q8IW%ST%Th?e@f#4UQxTG7^TFjU* 4OI`4W_yw1J5Cw*{+)LZ zIkp+-!mws}G6D9Xj6He9_iLJRZra?M7^aCJg>e9u3` &sng3$cl7gRt?D?H3$I+(yqN{ z=kNidzhEwu`gddcHqMzp(XGtc=?GtxCm(s<+b6EyoO^3+tNNM)0tw>?7s&39dhG-m zVFB%ZZ=($$CT1pWG?X+Nd8*}|!hWq&-+pQQ gy8m_6 zP}gn|A{#=0z#4Ev)qw0RfFh~qAJFHs%;Ad}d>6hpe06pHEt}Kw+f6J$#9l;9xcb xJq`5Mn|w;CKEhA~Wr9jI(}Fes6J=77R2H@@`rF^k;`?lQk_!;_C)b#+Zc zV&>+w8~^}HumiASR~rZDb=wV>Cb{3S-$7vk&uk2nF&S3b$e=Jc{lo$LG~QTQd1TiO z$B<$= mj$a6% z !Gh52mhCC~I*vS!Hiy4K{B zZAM8D8%c&4EE(iJwh;I90UW0s t&pmOhogiSV zGVUDIr7TfyDbXQc|M0BZEy+7Jwy04K07>jncqH+f4Fb7b-?q_fySI-!@PvVF*tS`N zI0MmFW{}^fdEUqa*QB0&^2};`6F;Nj_{_HB*QLeWS}i8FxN{tXR8=UjK_QvVg_ODV z@_pz3=F$n5X249P 3Z$swP*lx~WFUQAW6vQ8}25Dv41j&AY`}&aB0! z6qEz#Qu< bK|St&e?a_D!LpShtv z>$Z()HP(PY!qsjZDml&ph&cl2Fkk=}dt1oIY@o@5bJ_pcyM-*$tVIGDq9M84*N#7= z>VzjAJYlUhOxx?2EC4cNzq|I@k5(t|Y-uJya$0~DU<85=6EaTWfA-#oL2dy{ZpU@s z`}>oBjcfp7W-zql2qm w8nep0r1y2Fkr5=&b2k3b9p#`6eUX{t2Q%myv&}39=h_kIeG*IZK zLTP^ewF5Wa@yAi4tP8Buyei6*kNuCg#;)C(xT7|cJUz`4AUAW2-APw~3y9D#Y+PVQ zv|Lz2QwU6+mUcC{OI18<5r~ Z}QWdL@-gb?|VkcK+HAtH)JU zC8yUmsmV<(2Bg!DAT5}U2)W|G%mJu70JnEdKA#TlL#{U@DF17L%}iQnpptMfD5qsn zQPHLwmcDxIzug~DuwJK~)4tF%{N8Ju`Yzp)bz_Y~Q#KjO0y9gnVSo(CfLZl|K{1?# zL(w{OSC$L@Y=Djdx%8hO7cFbfomm6%vuzg0#xqYm&qY7UC{X6Xk^P%yM<%0o_5wm2 z@6=0PD1Lv_pqVu-$)7fB2?*8#1`J5wfCEDOIOe%v3TZHoYHVLaM=6SbynoAtV~kKj zFa~8~O+i0> `!I+Gzb%CLJIt#Q|OGzrlT zUpt4c)xWDD>J*_a#@oim7&69z%Apn%^l6 !YacRmlrO{cH{0C-UvqK5r`rLs?IZ+%9Akt65e8(LhWvicZ5Mv`jbEiEPfi0Y zN=rfI<(=e&v7D0e-)s44^;XQTZ7})V(gLM3jyr+d=j|S_BSxSPaE?)ppaTS*);$Kn zah|)+8jeKl7?G $r_H<_9C z%Bh220MI4RMcm*U{U2}tu(l~Vd!r+VfZ^tNK*Hw$Ap?nn_u&T@?BhM?U|1#~q_F~8 z;n58OX~Tj5A^Ij9 OA#_RPjf1MGkNl4 z-PKU~&H)|kZAX+>l~yA$r;5Z#(`GU%lq8@~nU(t{Gt=KVrSK5|U7L6rGx!d_XxXV% zP03qoGxBh4Z7GM?jqrsjK}b`PuW6%v*nf!bXA6oD^$2G|y6*|X7#0RhDkou(pJSdF zx=+ir7ath)HUJmM=#uYwhxd6>5G6eMs`}xpH)PMPt>@B)#xz7G?Fe=RGYjiJG%-M< zeSRJ0*kO9&@8i9X2587Iz;GPL29pM5x2!4{us!w8TZjJ5-AlT6d*{k2R#o-zryIXt zoe?vu9U5*7AlSHuBO3rpz@V7TNBhXktT#N5NGC`24gqaLpSEY5P`2) #vX{>Lp^R7 zxZKFqI8mArfR-Z~8VGY{*U!O1vk@vGfV^I2S@EFs4NLws+?GBlVTF<}B3B_A{{Gre znos<+R@_$CV2)|o-U{iY9bzNdFtKX|2AbEuw4hTXOeq4M9oQJI#SsEI1MX Ycw1|1b9_Sy~EonkRo&iRGdk`v020SF@3B zu4~}^o#s|3o%Z>4@aJD_Ogr1o?Y$2SVTA5s_|?5H#`FF#2yC<=V=_>^WEz9|G|xY1 z*rur!|2qDCd%&UuaD>yTkt!5Q|KZXt{a>q6zpQiA)td}@gN;|G&kdzR4Pb-)IX!FX zxASKMQAHb<_5tnw;296E9=crTKDtgM#zP1uVq@(tn>^HCm`q{9`OlF98*Y2-m|->k zv7NP0OUoq6OWjPkd5K@Y_O&V1X*sRlh`z3)$pN$SPvmJHKgi)~T@!V$1^#A49u&dj z&mlKn=oS!!!^W=DHXz|_&(GyM&O9%9=iQTs*u 53?Tp^M2RX zY{Ly38+0x=r=fTUz>WYq?ET<~_TDj|5mFS +Y*p2R;4J)Ja`pMCvnDj{NMW`Gv nxCCJbBztmVU3QH8E$S zqYiMNfCI1_EhEoR3H+=f`ruKGK;r}t!Jdlz=hJ3b^=|>$^aEzuOEL0u^dCkH-8So) zI}YCfp!3%K7bzj5vouv(wDg_6vp3d@pKNW+fLdF%Vh6^$dqZ}DJC24la^R~DQL>O$ zcHgu~(h58x>?sDv$&iB47?|C {P9X97js zbcj8i@B<3Y71r7WG7M|*WeLWhtjxcL4%|NV)!!Yu6aa9 +qY*RoK{D$7Ho`&(-05Lz9H!=fGDT7yN7}9-EZ$WyB)^maSW|B6d8@Y zUg k!&f)SJJ)6C>)J2`ShKCPkQmD5o%7Agqwb!3 zY;!8bB8 H1+=EkAkV^kSQH(WP)D6H=8DDGTJU z|MKMnKiu4JcAb_Nwy*%e4!{ELT4|Bt&wn2_dO|*BgtatWU`LOSYGVK(TbR>GB?Tid zq2DeZ*m~o#d86%|yf4h)+clC(v8`q20{h4xZa=GPQ{tA|1~WF@oQ87J4p>VzAWvh5 zldJp=9dh% (8V=G>^gNcz*@&Y u zbxDN{$cUzfaA1T2fV_mM%InRk_x^OygYJ%Bj={H!B%FE*0OP-(zM{GwGwbSgzG-Sj z!eksatk|a^(GWWO9u7qAn?Le#OtZJ6SUB{Yh+){kXa_1=ILOa!er(9T_0wMIYN{%t zuD g~?>!2F$PJF}BQ%%<7}QUqC9k)>>)6rFxBm5)ZmqlBVDRlKDJfx9 z>1yjA-o2&&Yj5_NR=1h1+1%hLw6wA^j$y;ndU^~z8^bpWLy93vIoJh$R6~11p`|LJ zk VQII-BB72L5zdGhEh zmt0)anwYtX A!Cf7h|%ax5O9q|AVMnw zjUJ^Sh-h^0m~g}qAcm9Cq~I|6CtI5e`ZwKq;pG3jEtN{O0A8V*ozsxfWt?0&nbOBS zQ8#HxOY*s9>t}U9lo(BB+RAVBzs19F#3(E-+xm8uRO5&^%>v2cl)m%Ba|T`4S h#SsQRPxd_*QA**xZ%;FO+ruE{2xx=%5hIWR(lA0L$zYJu zm4gTB8y5d&j9t&~OPsy^ `nE?;)Y-|a~|>E@fq30z8< zVe_~Ab+xAN6DZAsk_F7G?lTKVPM$njgP8=}l1?X-Z5rJOG0ts9vOmytFw8vwkXngO zOiHz2zGU9xy@p-A>`!lR?_E)45=R(84umlvRv;ob?<4d_u~+YpgZCo#8rhfZ_X2=B z!3so<{Vi5`S aU|FE&k1z*HKcTtlMx>H}YQWN+CuiIbMaO*Z-LF(kG86 zPZ+%)E*M;p{jtdHtuiW$NJvKr!9>EnhXi#( zypz6O0sy7u5ag-q!^-QwyWG(KIEq>!C~H6F$JU gi_Zkcj)1GQ%LN8*wVp9GNqKTfkU>^U=MW-y=mRwQ`H58IFAS0L{1I-%J zxSn`z4{r;zhlr+*?L)8{*=iK+8ht8P8XVBO^}(<0Uq9mg-;KRv@?>bFDilEGs|IGk z^VpC<39HoPG3j^yk#+0DL((G-DwgvG49tO(-Al1d8WK|5`JM!LTHC$v C-8JAU{_(IHn}i?%rIO@qPA8KqKF$5xm~kK98i1h#O tk-0)_}+uM6BY?1;5?Jy%@krs0CcpeOjx7Yg~ zzP;CGdwW6vKn6^PnN(63 oUd@1$w~ zKb>@C;{%_p%etkmUY^mg-GR!qIs#fSSglk62MXo_nrwy&jK<(h4Htxq=r2t~GF i{wc zDcbg=#$XFTV6wwV19P@_eFD$hw+R8^jv1r? Mxz4~1dtk-&>KhgX}Pjy-iUF_?>giufMsbZTbE%sjq-H|Nu|i3 zk{qwb^c#Q8UAXp%#9^a`(nZC2$xo2oOF1G*MA9J=@C`@z8H9n&q36af^#~_I#uXD0 z2hUspOhgI6G9v_kQkQl6i6?&gHNb0I`;sk$L*B`WU_#?XP_){Byw(X25`-NCqO?pR zMdrwB-~2{3)H#r>nUH7~h=}*x@CCL5W+3*xs~rS1NEkq ?VrX{y;iCq(j$U=| zm|s3L<*= Q(>D`Odigc+$|k eJMsv4C$q2NwK071?fBdv z=tS+FXGJ*yK(m%(T7hg3Gzc qZQOcWV} zT_;BX4KFVz )i6Kag8IE-#O+XfXOC2k=|?YeF>5x1CVwNM_N{% z^U$T=uO2bHm~I->FWIbBmNKMR2x0vAO6=Ksaj#HhJV?6 J2zFi)d$&JJ8UsY)MnLu`P-m7XxUBAA8@&4MF$4fB{G-VZ?sf&cnwP zw2u7f&V#2tc DH!#ATs=3x(rH8H>