内网穿透神级工具frp

post thumb
Ops
作者 Louis 发表于 2019年12月4日

对于没有公网 IP 的内网用户来说,远程管理或在外网访问内网机器上的服务是一个问题。通常解决方案就是用内网穿透工具将内网的服务穿透到公网中,便于远程管理和在外部访问。内网穿透的工具很多, 比如 Ngrok.

推荐一款好用到炸裂的内网穿透的工具frp, 全名: Fast Reverse Proxy. frp 是一个可用于内网穿透的高性能的反向代理应用,支持 tcp, udp 协议,为 httphttps应用协议提供了额外的能力,且尝试性支持了点对点穿透。

FRP作用

  • 利用处于内网或防火墙后的机器,对外网环境提供 HTTPHTTPS 服务。
  • 对于 HTTP, HTTPS 服务支持基于域名的虚拟主机,支持自定义域名绑定,使多个域名可以共用一个 80 端口。
  • 利用处于内网或防火墙后的机器,对外网环境提供 TCPUDP 服务,例如在家里通过 SSH 访问处于公司内网环境内的主机。

FRP架构

architecture

安装

FRP 采用 Go 语言开发,支持 WindowsLinuxMacOSARM等多平台部署

$ 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.techhttp.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.inicommon 中配置 tls_enable = true 来启用此功能,安全性更高。

为了端口复用,frp 建立 TLS 连接的第一个字节为 0x17。

注意: 启用此功能后除 xtcp 外,不需要再设置 use_encryption。

端口复用

目前 frps 中的 vhost_http_portvhost_https_port 支持配置成和 bind_port 为同一个端口,frps 会对连接的协议进行分析,之后进行不同的处理。

例如在某些限制较严格的网络环境中,可以将 bind_portvhost_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 相同。

上一篇
使用shell脚本发送钉钉通知