对于没有公网 IP
的内网用户来说,远程管理或在外网访问内网机器上的服务是一个问题。通常解决方案就是用内网穿透工具将内网的服务穿透到公网中,便于远程管理和在外部访问。内网穿透的工具很多, 比如 Ngrok.
推荐一款好用到炸裂的内网穿透的工具frp
, 全名: Fast Reverse Proxy
. frp
是一个可用于内网穿透的高性能的反向代理应用,支持 tcp, udp
协议,为 http
和https
应用协议提供了额外的能力,且尝试性支持了点对点穿透。
FRP
作用
- 利用处于内网或防火墙后的机器,对外网环境提供
HTTP
或HTTPS
服务。 - 对于
HTTP
,HTTPS
服务支持基于域名的虚拟主机,支持自定义域名绑定,使多个域名可以共用一个 80 端口。 - 利用处于内网或防火墙后的机器,对外网环境提供
TCP
和UDP
服务,例如在家里通过SSH
访问处于公司内网环境内的主机。
FRP架构
安装
FRP
采用 Go
语言开发,支持 Windows
、Linux
、MacOS
、ARM
等多平台部署
$ wget https://github.com/fatedier/frp/releases/download/v0.30.0/frp_0.30.0_linux_amd64.tar.gz
$ tar xf frp_0.30.0_linux_amd64.tar.gz
$ mv frp_0.30.0_linux_amd64 frp
$ cd frp/
$ ls
frpc frpc_full.ini frpc.ini frps frps_full.ini frps.ini LICENSE systemd
配置ssh访问公司内网机器
身份验证
服务端和客户端的 common 配置中的 token
参数一致则身份验证通过。
具有公网ip的frps
服务器服务端启动frps服务:
$ vim frps.ini
[common]
bind_addr = 0.0.0.0
bind_port = 7200
token = 123456
$ ./frps -c ./frps.ini
公司内网机器frpc
客户端启动frpc. 假设frps的公网ip为8.12.3.4
:
$ vim frpc.ini
[common]
server_addr = 8.12.3.4
server_port = 7200
token = 123456
[ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = 6000
$ ./frpc -c ./frpc.ini
在家里的user
连接公司b机器内网的ssh服务:
$ ssh -oPort=6000 root@8.12.3.4
通过自定义域名访问公司内网的web服务
具有公网ip的frps
服务器, 修改配置文件并启动frps服务:
$ vim frps.ini
[common]
server_addr = 8.12.3.4
server_port = 7200
token = 123456
vhost_http_port = 80
vhost_https_port = 443
$ ./frps -c ./frps.ini
公司内网机器frpc
客户端启动frpc. 假设frps的公网ip为8.12.3.4
:
$ vim frpc.ini
[common]
server_addr = 8.12.3.4
server_port = 7200
token = 123456
[httpstest]
type = https
local_ip = 192.168.0.65
local_port = 88
remote_port = 443
use_encryption = false
use_compression = true
custom_domains = https.fenghong.tech
[httptest]
type = https
local_ip = 192.168.0.34
local_port = 81
remote_port = 80
use_encryption = false
use_compression = true
custom_domains = http.fenghong.tech
[ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = 6000
$ ./frpc -c ./frpc.ini
配置域名解析, https配置可以是nginx来进行web站点配置. 本地的local_ip
可以是frpc客户端内网任意可达的ip地址.
http.fenghong.tech A 8.12.3.4
https.fenghong.tech A 8.12.3.4
通过浏览器访问https.fenghong.tech和http.fenghong.tech, 即可访问处于内网的web服务器.
转发 Unix 域套接字
通过 tcp 端口访问内网的 unix域套接字(例如和 docker daemon 通信)。
frps 的部署步骤同上。
启动 frpc,启用 unix_domain_socket
插件,配置如下:
# frpc.ini
[common]
server_addr = 8.12.3.4
server_port = 7000
[unix_domain_socket]
type = tcp
remote_port = 6000
plugin = unix_domain_socket
plugin_unix_path = /var/run/docker.sock
通过 curl 命令查看 docker 版本信息
curl http://8.12.3.4:6000/version
安全地暴露内网服务
对于某些服务来说如果直接暴露于公网上将会存在安全隐患。
使用 stcp(secret tcp) 类型的代理可以避免让任何人都能访问到要穿透的服务,但是访问者也需要运行另外一个 frpc。
服务端frps部署同上
公司内网机器frpc
客户端启动frpc. 假设frps的公网ip为8.12.3.4
:
$ vim frpc.ini
[common]
server_addr = 8.12.3.4
server_port = 7200
[secret_ssh]
type = stcp
# 只有 sk 一致的用户才能访问到此服务
sk = abcdefg
local_ip = 127.0.0.1
local_port = 22
在家里的电脑上开启frpc客户端, 配置如下:
$ vim frpc.ini
[common]
server_addr = 8.12.3.4
server_port = 7000
[secret_ssh_visitor]
type = stcp
# stcp 的访问者
role = visitor
# 要访问的 stcp 代理的名字
server_name = secret_ssh
sk = abcdefg
# 绑定本地端口用于访问 ssh 服务
bind_addr = 127.0.0.1
bind_port = 6000
$ ./frpc -c frpc.ini
通过ssh访问处于公司内网机器,
$ ssh -oPort=6000 root@127.0.0.1
开启Dashboard
通过浏览器查看frp的状态及代理统计信息
注:Dashboard 尚未针对大量的 proxy 数据展示做优化,如果出现 Dashboard 访问较慢的情况,请不要启用此功能。
需要在 frps.ini 中指定 dashboard 服务使用的端口,即可开启此功能:
$ vim frps.ini
[common]
dashboard_port = 7500
# dashboard 用户名密码,默认都为 admin
dashboard_user = admin
dashboard_pwd = admin
TLS
从 v0.25.0 版本开始 frpc 和 frps 之间支持通过 TLS 协议加密传输。通过在 frpc.ini
的 common
中配置 tls_enable = true
来启用此功能,安全性更高。
为了端口复用,frp 建立 TLS 连接的第一个字节为 0x17。
注意: 启用此功能后除 xtcp 外,不需要再设置 use_encryption。
端口复用
目前 frps 中的 vhost_http_port
和 vhost_https_port
支持配置成和 bind_port
为同一个端口,frps 会对连接的协议进行分析,之后进行不同的处理。
例如在某些限制较严格的网络环境中,可以将 bind_port
和 vhost_https_port
都设置为 443。
后续会尝试允许多个 proxy 绑定同一个远端端口的不同协议。
TCP 多路复用
从 v0.10.0 版本开始,客户端和服务器端之间的连接支持多路复用,不再需要为每一个用户请求创建一个连接,使连接建立的延迟降低,并且避免了大量文件描述符的占用,使 frp 可以承载更高的并发数。
该功能默认启用,如需关闭,可以在 frps.ini 和 frpc.ini 中配置,该配置项在服务端和客户端必须一致:
# frps.ini 和 frpc.ini 中
[common]
tcp_mux = false
连接池
默认情况下,当用户请求建立连接后,frps 才会请求 frpc 主动与后端服务建立一个连接。当为指定的代理启用连接池后,frp 会预先和后端服务建立起指定数量的连接,每次接收到用户请求后,会从连接池中取出一个连接和用户连接关联起来,避免了等待与后端服务建立连接以及 frpc 和 frps 之间传递控制信息的时间。
这一功能比较适合有大量短连接请求时开启。
首先可以在 frps.ini 中设置每个代理可以创建的连接池上限,避免大量资源占用,客户端设置超过此配置后会被调整到当前值:
$ vim frps.ini
[common]
max_pool_count = 5
在 frpc.ini 中为客户端启用连接池,指定预创建连接的数量:
$ vim frpc.ini
[common]
pool_count = 1
负载均衡
可以将多个相同类型的 proxy 加入到同一个 group 中,从而实现负载均衡的功能。
目前只支持 TCP 和 HTTP 类型的 proxy。
# 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
用户连接 frps 服务器的 80 端口,frps 会将接收到的用户连接随机分发给其中一个存活的 proxy。这样可以在一台 frpc 机器挂掉后仍然有其他节点能够提供服务。
TCP 类型代理要求 group_key
相同,做权限验证,且 remote_port
相同。
HTTP 类型代理要求 group_key, custom_domains 或 subdomain 和 locations
相同。