From 3fe50df200531ce748534f9bcc864c4b9ecdb9c5 Mon Sep 17 00:00:00 2001 From: fatedier Date: Thu, 18 May 2017 01:51:32 +0800 Subject: [PATCH 1/2] doc: update --- README.md | 14 --- README_zh.md | 202 +++++++++------------------------ conf/frpc_min.ini | 4 +- conf/frps_min.ini | 9 +- models/config/server_common.go | 14 +-- server/service.go | 1 + 6 files changed, 59 insertions(+), 185 deletions(-) diff --git a/README.md b/README.md index f6062cd8..1963fa80 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,6 @@ frp is a fast reverse proxy to help you expose a local server behind a NAT or fi * [Donation](#donation) * [AliPay](#alipay) * [Paypal](#paypal) -* [Contributors](#contributors) @@ -485,16 +484,3 @@ frp QQ group: 606194980 ### Paypal Donate money by [paypal](https://www.paypal.me/fatedier) to my account **fatedier@gmail.com**. - -## Contributors - -* [fatedier](https://github.com/fatedier) -* [Hurricanezwf](https://github.com/Hurricanezwf) -* [Pan Hao](https://github.com/vashstorm) -* [Danping Mao](https://github.com/maodanp) -* [Eric Larssen](https://github.com/ericlarssen) -* [Damon Zhao](https://github.com/se77en) -* [Manfred Touron](https://github.com/moul) -* [xuebing1110](https://github.com/xuebing1110) -* [Anbitioner](https://github.com/bingtianbaihua) -* [LitleCarl](https://github.com/LitleCarl) diff --git a/README_zh.md b/README_zh.md index 95f9381f..c85ef4dc 100644 --- a/README_zh.md +++ b/README_zh.md @@ -4,7 +4,7 @@ [README](README.md) | [中文文档](README_zh.md) -frp 是一个高性能的反向代理应用,可以帮助您轻松地进行内网穿透,对外网提供服务,支持 tcp, udp, http, https 等协议类型,并且 web 服务支持根据域名进行路由转发。 +frp 是一个可用于内网穿透的高性能的反向代理应用,支持 tcp, udp, http, https 协议。 ## 目录 @@ -23,33 +23,34 @@ frp 是一个高性能的反向代理应用,可以帮助您轻松地进行内 * [服务器端热加载配置文件](#服务器端热加载配置文件) * [特权模式](#特权模式) * [端口白名单](#端口白名单) + * [TCP 多路复用](#tcp-多路复用) * [连接池](#连接池) * [修改 Host Header](#修改-host-header) * [通过密码保护你的 web 服务](#通过密码保护你的-web-服务) * [自定义二级域名](#自定义二级域名) * [URL 路由](#url-路由) - * [通过 HTTP PROXY 连接 frps](#通过-http-proxy-连接-frps) + * [通过代理连接 frps](#通过代理连接-frps) * [开发计划](#开发计划) * [为 frp 做贡献](#为-frp-做贡献) * [捐助](#捐助) * [支付宝扫码捐赠](#支付宝扫码捐赠) * [Paypal 捐赠](#paypal-捐赠) -* [贡献者](#贡献者) ## frp 的作用 * 利用处于内网或防火墙后的机器,对外网环境提供 http 或 https 服务。 -* 对于 http 服务支持基于域名的虚拟主机,支持自定义域名绑定,使多个域名可以共用一个80端口。 -* 利用处于内网或防火墙后的机器,对外网环境提供 tcp 服务,例如在家里通过 ssh 访问处于公司内网环境内的主机。 -* 可查看通过代理的所有 http 请求和响应的详细信息。(待开发) +* 对于 http, https 服务支持基于域名的虚拟主机,支持自定义域名绑定,使多个域名可以共用一个80端口。 +* 利用处于内网或防火墙后的机器,对外网环境提供 tcp 和 udp 服务,例如在家里通过 ssh 访问处于公司内网环境内的主机。 ## 开发状态 -frp 目前正在前期开发阶段,master 分支用于发布稳定版本,dev 分支用于开发,您可以尝试下载最新的 release 版本进行测试。 +frp 仍然处于前期开发阶段,未经充分测试与验证,不推荐用于生产环境。 -**目前的交互协议可能随时改变,不能保证向后兼容,升级新版本时需要注意公告说明。** +master 分支用于发布稳定版本,dev 分支用于开发,您可以尝试下载最新的 release 版本进行测试。 + +**目前的交互协议可能随时改变,不保证向后兼容,升级新版本时需要注意公告说明同时升级服务端和客户端。** ## 架构 @@ -59,40 +60,36 @@ frp 目前正在前期开发阶段,master 分支用于发布稳定版本,dev 根据对应的操作系统及架构,从 [Release](https://github.com/fatedier/frp/releases) 页面下载最新版本的程序。 -将 **frps** 及 **frps.ini** 放到有公网 IP 的机器上。 +将 **frps** 及 **frps.ini** 放到具有公网 IP 的机器上。 将 **frpc** 及 **frpc.ini** 放到处于内网环境的机器上。 ### 通过 ssh 访问公司内网机器 -1. 修改 frps.ini 文件,配置一个名为 ssh 的反向代理: +1. 修改 frps.ini 文件,这里使用了最简化的配置: ```ini # frps.ini [common] bind_port = 7000 - - [ssh] - listen_port = 6000 - auth_token = 123 ``` 2. 启动 frps: `./frps -c ./frps.ini` -3. 修改 frpc.ini 文件,设置 frps 所在服务器的 IP 为 x.x.x.x; +3. 修改 frpc.ini 文件,假设 frps 所在服务器的公网 IP 为 x.x.x.x; ```ini # frpc.ini [common] server_addr = x.x.x.x server_port = 7000 - auth_token = 123 [ssh] local_ip = 127.0.0.1 local_port = 22 + remote_port = 6000 ``` 4. 启动 frpc: @@ -107,36 +104,31 @@ frp 目前正在前期开发阶段,master 分支用于发布稳定版本,dev 有时想要让其他人通过域名访问或者测试我们在本地搭建的 web 服务,但是由于本地机器没有公网 IP,无法将域名解析到本地的机器,通过 frp 就可以实现这一功能,以下示例为 http 服务,https 服务配置方法相同, vhost_http_port 替换为 vhost_https_port, type 设置为 https 即可。 -1. 修改 frps.ini 文件,配置一个名为 web 的 http 反向代理,设置 http 访问端口为 8080,绑定自定义域名 `www.yourdomain.com`: +1. 修改 frps.ini 文件,设置 http 访问端口为 8080: ```ini # frps.ini [common] bind_port = 7000 vhost_http_port = 8080 - - [web] - type = http - custom_domains = www.yourdomain.com - auth_token = 123 ``` 2. 启动 frps; `./frps -c ./frps.ini` -3. 修改 frpc.ini 文件,设置 frps 所在的服务器的 IP 为 x.x.x.x,local_port 为本地机器上 web 服务对应的端口: +3. 修改 frpc.ini 文件,假设 frps 所在的服务器的 IP 为 x.x.x.x,local_port 为本地机器上 web 服务对应的端口, 绑定自定义域名 `www.yourdomain.com`: ```ini # frpc.ini [common] server_addr = x.x.x.x server_port = 7000 - auth_token = 123 [web] type = http local_port = 80 + custom_domains = www.yourdomain.com ``` 4. 启动 frpc: @@ -151,17 +143,12 @@ frp 目前正在前期开发阶段,master 分支用于发布稳定版本,dev DNS 查询请求通常使用 UDP 协议,frp 支持对内网 UDP 服务的穿透,配置方式和 TCP 基本一致。 -1. 修改 frps.ini 文件,配置一个名为 dns 的反向代理: +1. 修改 frps.ini 文件: ```ini # frps.ini [common] bind_port = 7000 - - [dns] - type = udp - listen_port = 6000 - auth_token = 123 ``` 2. 启动 frps: @@ -181,6 +168,7 @@ DNS 查询请求通常使用 UDP 协议,frp 支持对内网 UDP 服务的穿 type = udp local_ip = 8.8.8.8 local_port = 53 + remote_port = 6000 ``` 4. 启动 frpc: @@ -202,7 +190,7 @@ DNS 查询请求通常使用 UDP 协议,frp 支持对内网 UDP 服务的穿 ```ini [common] dashboard_port = 7500 -# dashboard 用户名密码可选,默认都为 admin +# dashboard 用户名密码,默认都为 admin dashboard_user = admin dashboard_pwd = admin ``` @@ -213,9 +201,7 @@ dashboard_pwd = admin ### 身份验证 -出于安全性的考虑,服务器端可以在 frps.ini 中为每一个代理设置一个 auth_token 用于对客户端连接进行身份验证,例如上文中的 [ssh] 和 [web] 两个代理的 auth_token 都为 123。 - -客户端需要在 frpc.ini 中配置自己的 auth_token,与服务器中的配置一致才能正常运行。 +从 v0.10.0 版本开始,所有 proxy 配置全部放在客户端(也就是之前版本的特权模式),服务端和客户端的 common 配置中的 `privilege_token` 参数一致则身份验证通过。 需要注意的是 frpc 所在机器和 frps 所在机器的时间相差不能超过 15 分钟,因为时间戳会被用于加密验证中,防止报文被劫持后被其他人利用。 @@ -223,141 +209,76 @@ dashboard_pwd = admin ### 加密与压缩 -这两个功能默认是不开启的,需要在 frpc.ini 中通过配置来为指定的代理启用加密与压缩的功能,无论类型是 tcp, http 还是 https: +这两个功能默认是不开启的,需要在 frpc.ini 中通过配置来为指定的代理启用加密与压缩的功能,压缩算法使用 snappy: ```ini # frpc.ini [ssh] type = tcp -listen_port = 6000 -auth_token = 123 +local_port = 22 +remote_port = 6000 use_encryption = true -use_gzip = true +use_compression = true ``` 如果公司内网防火墙对外网访问进行了流量识别与屏蔽,例如禁止了 ssh 协议等,通过设置 `use_encryption = true`,将 frpc 与 frps 之间的通信内容加密传输,将会有效防止流量被拦截。 -如果传输的报文长度较长,通过设置 `use_gzip = true` 对传输内容进行压缩,可以有效减小 frpc 与 frps 之间的网络流量,加快流量转发速度,但是会额外消耗一些 cpu 资源。 +如果传输的报文长度较长,通过设置 `use_compression = true` 对传输内容进行压缩,可以有效减小 frpc 与 frps 之间的网络流量,加快流量转发速度,但是会额外消耗一些 cpu 资源。 ### 服务器端热加载配置文件 -当需要新增一个 frpc 客户端时,为了避免将 frps 重启,可以使用 reload 命令重新加载配置文件。 - -reload 命令仅能用于修改代理的配置内容,[common] 内的公共配置信息无法修改。 - -1. 首先需要在 frps.ini 中指定 dashboard_port: - - ```ini - # frps.ini - [common] - bind_port = 7000 - dashboard_port = 7500 - ``` - -2. 启动 frps: - - `./frps -c ./frps.ini` - -3. 修改 frps.ini 增加一个新的代理 [new_ssh]: - - ```ini - # frps.ini - [common] - bind_port = 7000 - dashboard_port = 7500 - - [new_ssh] - listen_port = 6001 - auth_token = 123 - ``` - -4. 执行 reload 命令,使 frps 重新加载配置文件,实际上是通过 7500 端口发送了一个 http 请求 - - `./frps -c ./frps.ini --reload` - -5. 之后启动 frpc,[new_ssh] 代理已经可以使用。 +由于从 v0.10.0 版本开始,所有 proxy 都在客户端配置,这个功能暂时移除。 ### 特权模式 -如果想要避免每次增加代理都需要操作服务器端,可以启用特权模式。 - -特权模式被启用后,代理的所有配置信息都可以在 frpc.ini 中配置,无需在服务器端做任何操作。 - -1. 在 frps.ini 中设置启用特权模式并设置 privilege_token,客户端需要配置同样的 privilege_token 才能使用特权模式创建代理: - - ```ini - # frps.ini - [common] - bind_port = 7000 - privilege_mode = true - privilege_token = 1234 - ``` - -2. 启动 frps: - - `./frps -c ./frps.ini` - -3. 在 frpc.ini 配置代理 [ssh],使用特权模式创建,无需事先在服务器端配置: - - ```ini - # frpc.ini - [common] - server_addr = x.x.x.x - server_port = 7000 - privilege_token = 1234 - - [ssh] - privilege_mode = true - local_port = 22 - remote_port = 6000 - ``` - - remote_port 即为原先在 frps.ini 的代理中配置的 listen_port 参数,使用特权模式后需要在 frpc 的配置文件中指定。 - -4. 启动 frpc: - - `./frpc -c ./frpc.ini` - -5. 通过 ssh 访问内网机器,假设用户名为 test: - - `ssh -oPort=6000 test@x.x.x.x` +由于从 v0.10.0 版本开始,所有 proxy 都在客户端配置,原先的特权模式是目前唯一支持的模式。 #### 端口白名单 -启用特权模式后为了防止端口被滥用,可以手动指定允许哪些端口被使用,在 frps.ini 中通过 privilege_allow_ports 来指定: +为了防止端口被滥用,可以手动指定允许哪些端口被使用,在 frps.ini 中通过 privilege_allow_ports 来指定: ```ini # frps.ini [common] -privilege_mode = true -privilege_token = 1234 privilege_allow_ports = 2000-3000,3001,3003,4000-50000 ``` privilege_allow_ports 可以配置允许使用的某个指定端口或者是一个范围内的所有端口,以 `,` 分隔,指定的范围以 `-` 分隔。 +### TCP 多路复用 + +从 v0.10.0 版本开始,客户端和服务器端之间的连接支持多路复用,不再需要为每一个用户请求创建一个连接,使连接建立的延迟降低,并且避免了大量文件描述符的占用,使 frp 可以承载更高的并发数。 + +该功能默认启用,如需关闭,可以在 frps.ini 和 frpc.ini 中配置,该配置项在服务端和客户端必须一致: + +```ini +# frps.ini 和 frpc.ini 中 +[common] +tcp_mux = false +``` + ### 连接池 默认情况下,当用户请求建立连接后,frps 才会请求 frpc 主动与后端服务建立一个连接。当为指定的代理启用连接池后,frp 会预先和后端服务建立起指定数量的连接,每次接收到用户请求后,会从连接池中取出一个连接和用户连接关联起来,避免了等待与后端服务建立连接以及 frpc 和 frps 之间传递控制信息的时间。 这一功能比较适合有大量短连接请求时开启。 -1. 首先可以在 frps.ini 中设置每个代理可以创建的连接池上限,避免大量资源占用,默认为 100,客户端设置超过此配置后会被调整到当前值: +**由于从 v0.10.0 版本开始支持了 tcp 连接的多路复用,如果启用了 tcp 的多路复用功能,则不再需要使用此功能或者连接池数量设置为 1 即可。** + +1. 首先可以在 frps.ini 中设置每个代理可以创建的连接池上限,避免大量资源占用,客户端设置超过此配置后会被调整到当前值: ```ini # frps.ini [common] - max_pool_count = 50 + max_pool_count = 5 ``` -2. 在 frpc.ini 中为指定代理启用连接池,指定预创建连接的数量: +2. 在 frpc.ini 中为客户端启用连接池,指定预创建连接的数量: ```ini # frpc.ini - [ssh] - type = tcp - local_port = 22 - pool_count = 10 + [common] + pool_count = 1 ``` ### 修改 Host Header @@ -367,7 +288,6 @@ privilege_allow_ports 可以配置允许使用的某个指定端口或者是一 ```ini # frpc.ini [web] -privilege_mode = true type = http local_port = 80 custom_domains = test.yourdomain.com @@ -387,7 +307,6 @@ frp 支持通过 HTTP Basic Auth 来保护你的 web 服务,使用户需要通 ```ini # frpc.ini [web] -privilege_mode = true type = http local_port = 80 custom_domains = test.yourdomain.com @@ -395,7 +314,7 @@ http_user = abc http_pwd = abc ``` -通过浏览器访问 `test.yourdomain.com`,需要输入配置的用户名和密码才能访问。 +通过浏览器访问 `http://test.yourdomain.com`,需要输入配置的用户名和密码才能访问。 ### 自定义二级域名 @@ -403,10 +322,11 @@ http_pwd = abc 通过在 frps 的配置文件中配置 `subdomain_host`,就可以启用该特性。之后在 frpc 的 http、https 类型的代理中可以不配置 `custom_domains`,而是配置一个 `subdomain` 参数。 -只需要将 `*.subdomain_host` 解析到 frps 所在服务器。之后用户可以通过 `subdomain` 自行指定自己的 web 服务所需要使用的二级域名,通过 `{subdomain}.{subdomain_host}` 来访问自己的 web 服务。 +只需要将 `*.{subdomain_host}` 解析到 frps 所在服务器。之后用户可以通过 `subdomain` 自行指定自己的 web 服务所需要使用的二级域名,通过 `{subdomain}.{subdomain_host}` 来访问自己的 web 服务。 ```ini # frps.ini +[common] subdomain_host = frps.com ``` @@ -415,7 +335,6 @@ subdomain_host = frps.com ```ini # frpc.ini [web] -privilege_mode = true type = http local_port = 80 subdomain = test @@ -436,14 +355,12 @@ frp 支持根据请求的 URL 路径路由转发到不同的后端服务。 ```ini # frpc.ini [web01] -privilege_mode = true type = http local_port = 80 custom_domains = web.yourdomain.com locations = / [web02] -privilege_mode = true type = http local_port = 81 custom_domains = web.yourdomain.com @@ -452,7 +369,7 @@ locations = /news,/about 按照上述的示例配置后,`web.yourdomain.com` 这个域名下所有以 `/news` 以及 `/about` 作为前缀的 URL 请求都会被转发到 web02,其余的请求会被转发到 web01。 -### 通过 HTTP PROXY 连接 frps +### 通过代理连接 frps 在只能通过代理访问外网的环境内,frpc 支持通过 HTTP PROXY 和 frps 进行通信。 @@ -472,11 +389,11 @@ http_proxy = http://user:pwd@192.168.1.128:8080 * frps 记录 http 请求日志。 * frps 支持直接反向代理,类似 haproxy。 * frpc 支持负载均衡到后端不同服务。 -* frpc debug 模式,控制台显示代理状态,类似 ngrok 启动后的界面。 -* frpc http 请求及响应信息展示。 * frpc 支持直接作为 webserver 访问指定静态页面。 * frpc 完全控制模式,通过 dashboard 对 frpc 进行在线操作。 * 支持 udp 打洞的方式,提供两边内网机器直接通信,流量不经过服务器转发。 +* 支持 plugin,frpc 获取到的连接可以交给指定 plugin 处理,例如 http 代理,简单的 web server。 +* 集成对 k8s 等平台的支持。 ## 为 frp 做贡献 @@ -504,16 +421,3 @@ frp 交流群:606194980 (QQ 群号) ### Paypal 捐赠 海外用户推荐通过 [Paypal](https://www.paypal.me/fatedier) 向我的账户 **fatedier@gmail.com** 进行捐赠。 - -## 贡献者 - -* [fatedier](https://github.com/fatedier) -* [Hurricanezwf](https://github.com/Hurricanezwf) -* [Pan Hao](https://github.com/vashstorm) -* [Danping Mao](https://github.com/maodanp) -* [Eric Larssen](https://github.com/ericlarssen) -* [Damon Zhao](https://github.com/se77en) -* [Manfred Touron](https://github.com/moul) -* [xuebing1110](https://github.com/xuebing1110) -* [Anbitioner](https://github.com/bingtianbaihua) -* [LitleCarl](https://github.com/LitleCarl) diff --git a/conf/frpc_min.ini b/conf/frpc_min.ini index a49901d9..ac6a6883 100644 --- a/conf/frpc_min.ini +++ b/conf/frpc_min.ini @@ -1,10 +1,10 @@ [common] server_addr = 0.0.0.0 server_port = 7000 -auth_token = 123 -privilege_token = 12345678 +#privilege_token = 12345678 [ssh] type = tcp local_ip = 127.0.0.1 local_port = 22 +remote_port = 6000 diff --git a/conf/frps_min.ini b/conf/frps_min.ini index a0df74ad..d6446cc2 100644 --- a/conf/frps_min.ini +++ b/conf/frps_min.ini @@ -4,11 +4,4 @@ bind_port = 7000 vhost_http_port = 80 vhost_https_port = 443 dashboard_port = 7500 -privilege_mode = true -privilege_token = 12345678 - -[ssh] -type = tcp -auth_token = 123 -bind_addr = 0.0.0.0 -listen_port = 6000 +#privilege_token = 12345678 diff --git a/models/config/server_common.go b/models/config/server_common.go index 070de8aa..9cc87c8b 100644 --- a/models/config/server_common.go +++ b/models/config/server_common.go @@ -186,17 +186,7 @@ func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) { // PrivilegeMode configure if cfg.PrivilegeMode == true { - tmpStr, ok = conf.Get("common", "privilege_token") - if ok { - if tmpStr == "" { - err = fmt.Errorf("Parse conf error: privilege_token can not be empty") - return - } - cfg.PrivilegeToken = tmpStr - } else { - err = fmt.Errorf("Parse conf error: privilege_token must be set if privilege_mode is enabled") - return - } + cfg.PrivilegeToken, _ = conf.Get("common", "privilege_token") cfg.PrivilegeAllowPorts = make(map[int64]struct{}) tmpStr, ok = conf.Get("common", "privilege_allow_ports") @@ -215,7 +205,7 @@ func LoadServerCommonConf(conf ini.File) (cfg *ServerCommonConf, err error) { err = fmt.Errorf("Parse conf error: privilege_allow_ports is incorrect, %v", errRet) return } - ServerCommonCfg.PrivilegeAllowPorts[singlePort] = struct{}{} + cfg.PrivilegeAllowPorts[singlePort] = struct{}{} } else if rangeType == 2 { // range ports min, errRet := strconv.ParseInt(portArray[0], 10, 64) diff --git a/server/service.go b/server/service.go index bfc6569a..b9e6cfb2 100644 --- a/server/service.go +++ b/server/service.go @@ -169,6 +169,7 @@ func (svr *Service) Run() { stream, err := session.AcceptStream() if err != nil { log.Warn("Accept new mux stream error: %v", err) + session.Close() return } wrapConn := frpNet.WrapConn(stream) From c67f9d5e76efd93460abc0c8dca684fbff9ba09d Mon Sep 17 00:00:00 2001 From: fatedier Date: Thu, 18 May 2017 19:08:43 +0800 Subject: [PATCH 2/2] doc: update --- .github/ISSUE_TEMPLATE | 19 +++-- README.md | 167 +++++++++++------------------------------ README_zh.md | 4 +- doc/pic/dashboard.png | Bin 25431 -> 31889 bytes 4 files changed, 55 insertions(+), 135 deletions(-) diff --git a/.github/ISSUE_TEMPLATE b/.github/ISSUE_TEMPLATE index 904216f4..c067f85d 100644 --- a/.github/ISSUE_TEMPLATE +++ b/.github/ISSUE_TEMPLATE @@ -1,21 +1,26 @@ Issue is only used for submiting bug report and documents typo. If there are same issues or answers can be found in documents, we will close it directly. -Please answer these questions before submitting your issue. Thanks! +Use the commands below to provide key information from your environment: +You do NOT have to include this information if this is a FEATURE REQUEST -1. What did you do? -If possible, provide a recipe for reproducing the error. +**What version of frp are you using (./frpc -v or ./frps -v)?** -2. What did you expect to see? +**What operating system and processor architecture are you using (`go env`)?** +**Steps to reproduce the issue:** +1. +2. +3. -3. What did you see instead? +**Describe the results you received:** +**Describe the results you expected:** -4. What version of frp are you using (./frpc -v or ./frps -v)? +**Additional information you deem important (e.g. issue happens only occasionally):** -5. Can you point out what caused this issue (optional)? +**Can you point out what caused this issue (optional)** diff --git a/README.md b/README.md index 1963fa80..8b4fe719 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ frp is a fast reverse proxy to help you expose a local server behind a NAT or fi * [Status](#status) * [Architecture](#architecture) * [Example Usage](#example-usage) - * [Communicate with your computer in LAN by SSH](#communicate-with-your-computer-in-lan-by-ssh) + * [Access your computer in LAN by SSH](#access-your-computer-in-lan-by-ssh) * [Visit your web service in LAN by custom domains](#visit-your-web-service-in-lan-by-custom-domains) * [Forward DNS query request](#forward-dns-query-request) * [Features](#features) @@ -25,6 +25,7 @@ frp is a fast reverse proxy to help you expose a local server behind a NAT or fi * [Reload configures without frps stopped](#reload-configures-without-frps-stopped) * [Privilege Mode](#privilege-mode) * [Port White List](#port-white-list) + * [TCP Stream Multiplexing](#tcp-stream-multiplexing) * [Connection Pool](#connection-pool) * [Rewriting the Host Header](#rewriting-the-host-header) * [Password protecting your web service](#password-protecting-your-web-service) @@ -42,8 +43,7 @@ frp is a fast reverse proxy to help you expose a local server behind a NAT or fi ## What can I do with frp? * Expose any http and https service behind a NAT or firewall to the internet by a server with public IP address(Name-based Virtual Host Support). -* Expose any tcp service behind a NAT or firewall to the internet by a server with public IP address. -* Inspect all http requests/responses that are transmitted over the tunnel(future). +* Expose any tcp or udp service behind a NAT or firewall to the internet by a server with public IP address. ## Status @@ -63,37 +63,33 @@ Put **frps** and **frps.ini** to your server with public IP. Put **frpc** and **frpc.ini** to your server in LAN. -### Communicate with your computer in LAN by SSH +### Access your computer in LAN by SSH -1. Modify frps.ini, configure a reverse proxy named [ssh]: +1. Modify frps.ini: ```ini # frps.ini [common] bind_port = 7000 - - [ssh] - listen_port = 6000 - auth_token = 123 ``` 2. Start frps: `./frps -c ./frps.ini` -3. Modify frpc.ini, set remote frps's server IP as x.x.x.x: +3. Modify frpc.ini, `server_addr` is your frps's server IP: ```ini # frpc.ini [common] server_addr = x.x.x.x server_port = 7000 - auth_token = 123 [ssh] type = tcp local_ip = 127.0.0.1 local_port = 22 + remote_port = 6000 ``` 4. Start frpc: @@ -110,18 +106,13 @@ Sometimes we want to expose a local web service behind a NAT network to others f However, we can expose a http or https service using frp. -1. Modify frps.ini, configure a http reverse proxy named [web] and set http port as 8080, custom domain as `www.yourdomain.com`: +1. Modify frps.ini, configure http port 8080: ```ini # frps.ini [common] bind_port = 7000 vhost_http_port = 8080 - - [web] - type = http - custom_domains = www.yourdomain.com - auth_token = 123 ``` 2. Start frps: @@ -135,11 +126,11 @@ However, we can expose a http or https service using frp. [common] server_addr = x.x.x.x server_port = 7000 - auth_token = 123 [web] type = http local_port = 80 + custom_domains = www.yourdomain.com ``` 4. Start frpc: @@ -158,11 +149,6 @@ However, we can expose a http or https service using frp. # frps.ini [common] bind_port = 7000 - - [dns] - type = udp - listen_port = 6000 - auth_token = 123 ``` 2. Start frps: @@ -176,12 +162,12 @@ However, we can expose a http or https service using frp. [common] server_addr = x.x.x.x server_port = 7000 - auth_token = 123 [dns] type = udp local_ip = 8.8.8.8 local_port = 53 + remote_port = 6000 ``` 4. Start frpc: @@ -214,121 +200,58 @@ Then visit `http://[server_addr]:7500` to see dashboard, default username and pa ### Authentication -`auth_token` in frps.ini is configured for each proxy and check for authentication when frpc login in. - -Client that want's to register must set a global `auth_token` equals to frps.ini. +Since v0.10.0, you only need to set `privilege_token` in frps.ini and frpc.ini. -Note that time duration between frpc and frps mustn't exceed 15 minutes because timestamp is used for authentication. +Note that time duration between server of frpc and frps mustn't exceed 15 minutes because timestamp is used for authentication. Howerver, this timeout duration can be modified by setting `authentication_timeout` in frps's configure file. It's defalut value is 900, means 15 minutes. If it is equals 0, then frps will not check authentication timeout. ### Encryption and Compression -Defalut value is false, you could decide if the proxy will use encryption or compression whether the type is: +Defalut value is false, you could decide if the proxy will use encryption or compression: ```ini # frpc.ini [ssh] type = tcp -listen_port = 6000 -auth_token = 123 +local_port = 22 +remote_port = 6000 use_encryption = true -use_gzip = true +use_compression = true ``` ### Reload configures without frps stopped -If you want to add a new reverse proxy and avoid restarting frps, you can use this function: - -1. `dashboard_port` should be set in frps.ini: - - ```ini - # frps.ini - [common] - bind_port = 7000 - dashboard_port = 7500 - ``` - -2. Start frps: - - `./frps -c ./frps.ini` - -3. Modify frps.ini to add a new proxy [new_ssh]: - - ```ini - # frps.ini - [common] - bind_port = 7000 - dashboard_port = 7500 - - [new_ssh] - listen_port = 6001 - auth_token = 123 - ``` - -4. Execute `reload` command: - - `./frps -c ./frps.ini --reload` - -5. Start frpc and [new_ssh] is available now. +This feature is removed since v0.10.0. ### Privilege Mode -Privilege mode is used for who don't want to do operations in frps everytime adding a new proxy. - -All proxies's configurations are set in frpc.ini when privilege mode is enabled. - -1. Enable privilege mode and set `privilege_token`.Client with the same `privilege_token` can create proxy automaticly: - - ```ini - # frps.ini - [common] - bind_port = 7000 - privilege_mode = true - privilege_token = 1234 - ``` - -2. Start frps: - - `./frps -c ./frps.ini` - -3. Enable privilege mode for proxy [ssh]: - - ```ini - # frpc.ini - [common] - server_addr = x.x.x.x - server_port = 7000 - privilege_token = 1234 - - [ssh] - privilege_mode = true - local_port = 22 - remote_port = 6000 - ``` - -4. Start frpc: - - `./frpc -c ./frpc.ini` - -5. Connect to server in LAN by ssh assuming username is test: - - `ssh -oPort=6000 test@x.x.x.x` +Privilege mode is the default and only mode support in frp since v0.10.0. All proxy configurations are set in client. #### Port White List -`privilege_allow_ports` in frps.ini is used for preventing abuse of ports in privilege mode: +`privilege_allow_ports` in frps.ini is used for preventing abuse of ports: ```ini # frps.ini [common] -privilege_mode = true -privilege_token = 1234 privilege_allow_ports = 2000-3000,3001,3003,4000-50000 ``` `privilege_allow_ports` consists of a specific port or a range of ports divided by `,`. +### TCP Stream Multiplexing + +frp support tcp stream multiplexing since v0.10.0 like HTTP2 Multiplexing. All user requests to same frpc can use only one 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 +``` + ### Connection Pool By default, frps send message to frpc for create a new connection to backward service when getting an user request.If a proxy's connection pool is enabled, there will be a specified number of connections pre-established. @@ -337,30 +260,27 @@ This feature is fit for a large number of short connections. 1. Configure the limit of pool count each proxy can use in frps.ini: - ```ini + ```ini # frps.ini [common] - max_pool_count = 50 + max_pool_count = 5 ``` 2. Enable and specify the number of connection pool: ```ini # frpc.ini - [ssh] - type = tcp - local_port = 22 - pool_count = 10 + [common] + pool_count = 1 ``` ### Rewriting the Host Header When forwarding to a local port, frp does not modify the tunneled HTTP requests at all, they are copied to your server byte-for-byte as they are received. Some application servers use the Host header for determining which development site to display. For this reason, frp can rewrite your requests with a modified Host header. Use the `host_header_rewrite` switch to rewrite incoming HTTP requests. -```ini -# frpc.ini +```ini +# frpc.ini [web] -privilege_mode = true type = http local_port = 80 custom_domains = test.yourdomain.com @@ -375,12 +295,11 @@ Anyone who can guess your tunnel URL can access your local web server unless you This enforces HTTP Basic Auth on all requests with the username and password you specify in frpc's configure file. -It can be only enabled when proxy type is http. +It can only be enabled when proxy type is http. ```ini # frpc.ini [web] -privilege_mode = true type = http local_port = 80 custom_domains = test.yourdomain.com @@ -388,7 +307,7 @@ http_user = abc http_pwd = abc ``` -Visit `test.yourdomain.com` and now you need to input username and password. +Visit `http://test.yourdomain.com` and now you need to input username and password. ### Custom subdomain names @@ -404,7 +323,6 @@ Resolve `*.frps.com` to the frps server's IP. ```ini # frpc.ini [web] -privilege_mode = true type = http local_port = 80 subdomain = test @@ -423,14 +341,12 @@ frp support forward http requests to different backward web services by url rout ```ini # frpc.ini [web01] -privilege_mode = true type = http local_port = 80 custom_domains = web.yourdomain.com locations = / [web02] -privilege_mode = true type = http local_port = 81 custom_domains = web.yourdomain.com @@ -454,11 +370,12 @@ http_proxy = http://user:pwd@192.168.1.128:8080 * Log http request information in frps. * Direct reverse proxy, like haproxy. * Load balance to different service in frpc. -* Debug mode for frpc, prestent proxy status in terminal. -* Inspect all http requests/responses that are transmitted over the tunnel. * Frpc can directly be a webserver for static files. * Full control mode, dynamically modify frpc's configure with dashboard in frps. * P2p communicate by make udp hole to penetrate NAT. +* Client Plugin (http proxy). +* kubernetes ingress support. + ## Contributing diff --git a/README_zh.md b/README_zh.md index c85ef4dc..33c1491a 100644 --- a/README_zh.md +++ b/README_zh.md @@ -87,6 +87,7 @@ master 分支用于发布稳定版本,dev 分支用于开发,您可以尝试 server_port = 7000 [ssh] + type = tcp local_ip = 127.0.0.1 local_port = 22 remote_port = 6000 @@ -162,7 +163,6 @@ DNS 查询请求通常使用 UDP 协议,frp 支持对内网 UDP 服务的穿 [common] server_addr = x.x.x.x server_port = 7000 - auth_token = 123 [dns] type = udp @@ -263,8 +263,6 @@ tcp_mux = false 这一功能比较适合有大量短连接请求时开启。 -**由于从 v0.10.0 版本开始支持了 tcp 连接的多路复用,如果启用了 tcp 的多路复用功能,则不再需要使用此功能或者连接池数量设置为 1 即可。** - 1. 首先可以在 frps.ini 中设置每个代理可以创建的连接池上限,避免大量资源占用,客户端设置超过此配置后会被调整到当前值: ```ini diff --git a/doc/pic/dashboard.png b/doc/pic/dashboard.png index 80d7bfff652fe510509c1dbc5b05cd1dd206064b..d6dff6474f9f9da0361b0a31119ea12c5b7739c2 100644 GIT binary patch literal 31889 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 z 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 MqWb;(yHEfAUz5uy8UO$Q literal 25431 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 {aM4(*DOwj8%$M^O_gyGl43w*G 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 G;r{@$KLlt1