在这之前,你应该在嵌入式设备上和带有公网 IP 的服务器上都已经安装好了 frp ,如果没有的话就翻一下前面几节的内容。
今天把 frp 的官方文档阅读完了,发现这个项目是我们国人主导的,还是比较自豪的;文档写的非常详细,我的建议是全部读一遍吧,花不了你多久时间的,因此也不介绍 frp 了,直接给出几个我自己的配置实例就可以了。
官方文档 : FRP
这里给出的几个配置实例的原因主要是因为我的应用场景比较特殊,是用在 IOT 上,也就是寻找一种有效的方式访问到内网里的嵌入式设备,主要是为了在产品出现问题的时候有一种有效的方式远程解决客户的问题;这里比较特殊的地方就是,很多个人用户是一对一的模型也就是客户端和服务器都是只有一个,而 IOT 那客户端就多了个去了,而且要做的事情跟个人用户也不太一样;不过殊途同归,都是想像局域网一样访问设备。
在这里给出一个通用的配置以及给出几个内网穿透的案例:
frp 使用 ini
格式进行配置,里面可以选择的东西还挺多的,但是我喜欢简洁一点,所以只使用 IP
层的 TCP
与 UDP
进行配置。
服务器 frps
使用 frps.ini
进行配置:
[common]
# 服务端监听地址(一般不需要填写)
# bind_addr = 0.0.0.0
# 服务端监听端口
bind_port = 8012
# 日志文件地址
log_file = ./frps.log
# 鉴权方式
authentication_method = token
# 鉴权使用的 token 值 客户端需要设置一样的值才能鉴权通过
# 建议使用 uuidgen 生成服务器的 UUID
token = 082116ea-1fcd-4737-944e-56e5078fa8fb
# 允许代理绑定的服务端端口
# 1 - 1024 以下的端口保留给服务器自己使用,防止冲突服务器的端口
# allow_ports = 1024-65535
# 2 - 开放全部端口,存在更大与服务器端口端口的冲突的可能性
allow_ports = 0-65535
# 只接受启用了 TLS 的客户端连接
tls_only = true
# 启用 Dashboard 监听的本地端口
dashboard_port = 8013
dashboard_user = root
dashboard_pwd = 123465
# 是否提供 Prometheus 监控接口
enable_prometheus = true
除去注释的版本:
[common]
bind_port = 8012
log_file = ./frps.log
authentication_method = token
token = 082116ea-1fcd-4737-944e-56e5078fa8fb
allow_ports = 0-65535
tls_only = true
dashboard_port = 8013
dashboard_user = root
dashboard_pwd = 123465
enable_prometheus = true
使用命令行 ./frps -c ./frps.ini &
将 frp 服务器运行在后台。
然后可以这样登录服务器端的控制台:
控制界面是长这样的,这个界面是用 vue
写的:
如果解决跨域(CROS)问题的话,那么找到 vue
工程的 js 部门也就可以拿到 http 的接口了,可以自己接入自己的平台。
客户端 fprc
使用 fprc.ini
进行配置:
[common]
# 连接服务端的地址,填写 frps 的公网IP
server_addr = x.x.x.x
# 连接服务端的端口
server_port = 8012
# 日志文件地址
log_file = ./frpc.log
# 第一次登陆失败后是否退出
login_fail_exit = false
# 启用 TLS 协议加密连接
tls_enable = true
# 鉴权方式
authentication_method = token
token = 082116ea-1fcd-4737-944e-56e5078fa8fb
# 启用 AdminUI 监听的本地端口
admin_port = 25000
admin_user = root
admin_pwd = 123456
除去注释的版本:
[common]
server_addr = x.x.x.x
server_port = 8012
log_file = ./frpc.log
login_fail_exit = false
tls_enable = true
authentication_method = token
token = 082116ea-1fcd-4737-944e-56e5078fa8fb
admin_port = 25000
admin_user = root
admin_pwd = 123456
然后登录客户端的控制台,可以看到这些内容:
这说明什么呢,说明 frpc
启动之后并不是非得重启才能重新配置的,然后这个也是 vue
写的,只要把 CROS
就可以把接口扣出来,而不用去修改 frp
的 go 代码,就可以做到热重启。
更多详细的配置读读官方的文档,我这配置估计挺快就会报废,听说 frp 最近在准备 v2 版本,架构发生了改变,可能文档也会修改地比较厉害:参考
有关于 netdata 的相关信息这里不赘叙,只是说一下 netdata 是一个系统检测工具,有兴趣地可以看下:
目前 Netdata 运行在我局域网的机器,我已经将 Netdata 拉起来了:
然后我开始往 fprc.ini
里添加内容,追加以下内容:
[netdata]
type = tcp
local_ip = 127.0.0.1
local_port = 25000
# 映射后可以使用 `public IP address:remote_port` 的形式访问
remote_port = 25000
这样子就能使用公网 IP 访问 Netdata 了,效果如下:
打开服务器和客户端的控制台可以分别看到以下内容:
客户端的控制台不知道为什么连接不上,这个之后再查一查了,可能是因为访问被锁定在 IOT 上了,所以我的宿主机去访问就访问不了;检查了一下,确实是这样,我将
frpc.ini
中的admin_addr
老老实实填成ifconfig
中的 IP 地址后就可以了,不填0.0.0.0
这样会被锁定在本机上。
这样代理就完成了,但是还没完,这里引出另一个问题,线下可不止一台 IOT 设备,这里我的宿主机作为另一台 IOT 测试设备,做同样的操作。
在我的宿主机添加一样的配置:
[netdata]
type = tcp
local_ip = 127.0.0.1
local_port = 19999
remote_port = 25000
然后出现这样的情况:
这个 cpu 飙升的原因暂不知道,而且只在那时候出现过一次,之后尝试复现没有成功。
修改端口使用为 24999 ,出现以下:
这个我是知道的,代理不能取同一个名字,这在文档里说过;但是也太不合理吧,你叫我每台机取什么名字呢,这个我得思考下。
将 netdata
修改为 netdata2
,可以正常运行,如下:
服务器控制面板如下:
通过观察这里,可以发现 IOT 使用 frpc 的两个需要解决的地方:
frp 是有提供获取远程文件的途径的,但是由于之前我已经在我的 IOT 上搭建好了 ftp 服务器,可以下载和上传文件,所以这里也打算穿透一下。这里科普一下,虽然连接 ftp 是 21 端口,但这个端口只是控制端口;还有一个数据端口 20。
客户端追加以下内容:
[range:ftp]
type = tcp
local_ip = 127.0.0.1
local_port = 20-21
remote_port = 20-21
这个失败了,报错原因如下:
弄了半个钟还是没有解决问题,这个问题是来自于 vsftpd
,我在我的 IOT 上移植了 vsftpd
,并且为了解决一些依赖问题,又对 vsftpd
进行了一些定制化的裁剪;后期再去看看 vsftpd
的源码,看看是出了什么问题。
远程 gdb 调试就拿 vsftpd
作为调试的程序吧,刚好 ftp 的穿透出现了问题,vsftpd
就是支撑这个 ftp 服务器的程序,这样 gdb 穿透
这个需求就很明确了,现实中确实有这个需求。
以下是我 vscode
的配置,gdbserver 的端口固定在 10002:
在 IOT 上先把 gdbserver 开起来:
然后在 frpc.ini
中追加以下内容,并重启 frpc
:
[gdb]
type = tcp
local_ip = 127.0.0.1
local_port = 10002
remote_port = 10002
这样就抓到了,说明是可以通过 frp
去远程调试局域网内的设备的。
有关于 vscode 远程调试的内容可以看这里 : 嵌入式 LINUX IDE 环境搭建
在我的 IOT 上是绑定摄像头的,所以自然而言就有画面,有画面就有流媒体,有流媒体就可以拉流;流的种类挺多的,这里就拉一个 rtmp
吧。
在 frpc.ini
中追加以下内容,并重启 frpc
:
[rtmp]
type = tcp
local_ip = 127.0.0.1
local_port = 1935
remote_port = 1935
然后使用 VLC
拉下流,效果如下:
拉流正常,之后播放个 2 分钟,观察一下阿里云的带宽使用:
大概是 40 多 M 的样子吧,好像也不是很多,还是可以接受的。
然后这个画面虽然是 IOT 上面显示,但是 IOT 的这个画面是从摄像头拉过来的,所以 frpc.ini
可以修改成这样子:
[rtsp]
type = tcp
# 摄像头的 IP ,并且 IOT 能够 ping 到
local_ip = 172.20.92.204
local_port = 554
remote_port = 554
然后重启 frpc,也是正常显示的(这里我直接用我的域名去拉流了,写 ip 有点累):
这说明什么呢, frpc 不是只能做自己的代理,只要是 frpc 所在的机器能够碰得到的 ip:port
, frpc 就能做代理;如果你的应用场景中除了 IOT 之外还存在像主机这样性能比较优秀的机器,可以考虑让主机帮助 IOT 进行内网穿透,减轻 IOT 设备的负担。
略
正如在这篇文章里看到的一样,上述的这些场景都是临时需要开启的,而且开启的时间都不会很长;这代表着 frpc.ini
这个文件的内容改动会很频繁,在 frp
中是有一个折中的解决方案的,叫做配置拆分。
以下内容摘自 frp
官网:
通过 includes
参数可以在主配置中包含其他配置文件,从而实现将代理配置拆分到多个文件中管理。
# frpc.ini
[common]
server_addr = x.x.x.x
server_port = 7000
includes = ./confd/*.ini
# ./confd/test.ini
[ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = 6000
上述配置在 frpc.ini 中通过 includes 额外包含了 ./confd
目录下所有的 ini 文件的代理配置内容,效果等价于将这两个文件合并成一个文件。
需要注意的是 includes 指定的文件中只能包含代理配置,common 段落的配置只能放在主配置文件中。
在了解完这篇文章列举出有关于 frp
的使用方式后,应能能满足你大部分的需求。
但是在 IOT 上这两点是逃不掉的:
一个比较好的办法是自己封装一层,手动维护服务器可用的端口,以及使用 UUID 使 IOT 的代理名称不会冲突。