一文拿捏内网穿透利器之frp
一、什么是 frp
1.1 内网穿透

如下图所示, 一般情况下, 公网内的设备都能够被任意一台设备访问到!! 而不同局域网内的设备是相互隔离的, 局域网 A 的设备是无法访问到局域网 B 内的设备

而内网穿透技术, 顾名思义就是能让公网、或者当前局域网外的任意设备访问到局域网内某个设备! 如下图, 设备 C 实现了内网穿透技术, 所以局域网内任意设备都能够访问到当前设备

那么有了内网穿透我们可以做啥呢?
远程访问和管理: 内网穿透允许您从任何地方通过互联网连接到位于其他局域网内中的设备或服务器, 举个最简单的例子就是, 当你在家里想远程访问公司的电脑时, 因为你的两个设备是处于不同局域网内, 默认情况下是无法相互访问的, 这时就可以通过内网穿透来实现
游戏娱乐: 比如你在家用电脑开游戏服, 想邀请朋友加入联机, 因为你家里的网络与朋友的网络处于不同的局域网, 当朋友想要联机加入你的游戏服时, 就需要你的电脑使用内网穿透技术将设备访问权暴露出去
共享本地服务: 实现文件共享, 如文件共享、打印机访问或监控摄像头; 通过内网穿透技术, 我们可以随时随地访问家里设备的资源、服务
测试和开发环境: 开发人员可以使用内网穿透将本地开发环境暴露给外部世界; 比如我们要本地测试
github webhooks就可以通过内网穿透来让外部的服务访问到我们本地服务
1.2 frp 简介 & 原理简述
简单地说, frp 就是一个反向代理软件, 它的作用是将内网中的服务器暴露到互联网上, 它体积轻量但功能很强大!!! 通过它我们可以很方便实现内网穿透功能!!!
它其实有两个服务:
-
客户端
frpc, 安装在我们内网中某台物理机上 -
服务端
frps, 安装在一个公网服务器上
如下图:
-
首先公网上先部署了
frps服务, 并设置了连接端口 -
然后在内网中运行
frpc服务, 启动时会连接到公网上的frpc服务, 并保持保持住这个长连接(如果断开了会进行重试) -
当用户公网地址时, 会先在本地看是否有可用的连接, 如果没有, 那么
frps服务就会将请求转发到frpc服务上 -
再由
frpc将请求转发到内网中任意一个服务上

FRP的优点: 它可以隐藏内网中的服务器, 避免因直接暴露内网服务器导致的安全问题。此外, FRP还支持动态端口映射, 可以方便地实现内网的服务器负载均衡
二、公网服务器 frps 部署
上文提到, frp 其实是有两个服务的, 一个存在于公网的 frp 服务端, 也是就 frps; 一个就是部署在局域网物理机上的 frp 客户端, 也就是 frpc
那么本节将介绍下 frps 的一个部署, 这里使用到的 docker 镜像是 snowdreamtech/frps, 需要注意的是本文使用的是最新的版本, 所以配置文件和目前网上大部分教程是有所出入的!!!
如下图, 从 docker 镜像的详细信息可以看出, 该镜像发布时间的一个时间, 以及使用的配置文件路径, 配置文件具体信息可以看 frp 官网

下面开始正式部署 frps 服务...
2.1 添加配置文件
首先找个位置, 添加一个配置文件 frps.toml, 我这里配置文件完整路径为 /home/moyuanjun/frp/frps.toml, 配置文件内容如下, 具体每个配置项参考注释, 更多配置可查阅 frp 官网
bindPort = 7000log.to = "console"vhostHTTPPort = 7100vhostHTTPSPort = 7200auth.method = "token"auth.token = "password"webServer.port = 7300webServer.addr = "0.0.0.0"webServer.user = "admin"webServer.password = "admin"
2.2 Docker 容器部署
配置文件整完, 下面我们开始部署 docker!!!
-
首先先拉取下最新的
docker镜像 snowdreamtech/frps
sudo docker pull snowdreamtech/frps
这里提前拉取了下镜像, 主要目的就是要确认下拉取下来的 snowdreamtech/frps 镜像的版本是否是最新的, 这里我就是简单看下镜像的创建时间(没办法, 不同的 docker 源上最新版本可能存在差异, 我这次就被坑惨了!!!)

-
docker运行: 如下命令, 运行snowdreamtech/frps, 这里唯一要调整的是-v /home/moyuanjun/frp/frps.toml:/etc/frp/frps.toml, 要将前面我本地配置文件路径改成你自己的
sudo docker run -d \--network host \-v /home/moyuanjun/frp/frps.toml:/etc/frp/frps.toml \--name frps \snowdreamtech/frps

2.3 日志查看
上文我们已经完成了 frps docker 容器的部署, 但实际上我们只看到容器起来了!! 但是 frps 具体运行情况我们是无法知道得知的!!
其实我们在 frps.toml 中配置了 log.to = "console", 日志实际上已经输出了, 这里我们直接通过 docker logs frps 就可以查看到日志信息了:

当然如果我们想要查看实时的日志, 可以使用 docker logs -f frps 来开启一个实时的终端进程, 就能够实时监控到日志的输出:

2.4 frps 仪表盘
我自己的服务器是阿里云的, 默认情况下防火墙只开启了几个常用端口, 所以在开始前, 我这边还需要设置下阿里云的防火墙, 为
frp开放了一批端口出来
还记得我们在 frps.toml 中配置了仪表盘信息嘛, 下面我们可以通过 ip/域名:[webServer.port] 来访问仪表盘页面!!!
首次需要登录, 用户名密码就是 frps.toml 设置的内容:

如下图, 就是仪表盘的界面了:

三、内网 frpc 部署
下面我们还需要一个 frpc 客户端, 当我们运行 frpc 服务时将和公网上的 frps 建立一个长连接, 当我们访问公网不存在的服务时会转发到 frpc, 然后 frpc 再做一个二次转发
那么本节将介绍下 frpc 的一个部署, 这里使用到的 docker 镜像是 snowdreamtech/frpc, 需要注意的是本文使用的是最新的版本, 所以配置文件和目前网上大部分教程是有所出入的!!!
如下图, 从 docker 镜像的详细信息可以看到, 该镜像的一个发布时间, 以及使用的配置文件路径, 配置文件具体信息可以看 frp 官网

下面开始正式部署 frpc 服务...
3.1 添加配置文件
还是一样, 我们需要先找个位置, 添加一个配置文件 frpc.toml, 我这里配置文件完整路径为 /Users/qianyin/frp/frpc.toml, 配置文件最简内容如下, 具体每个配置项参考注释, 更多配置可查阅 frp 官网
serverPort = 7000serverAddr = "www.kunlunxu.cc"log.to = "console"auth.token = "password"

3.2 Docker 容器部署
配置文件整完, 下面我们开始部署 docker!!!
-
首先先拉取下最新的
docker镜像 snowdreamtech/frpc
docker pull snowdreamtech/frpc
这里提前拉取了下镜像, 主要目的就是要确认下拉取下来的 snowdreamtech/frpc 镜像的版本是否是最新的, 这里我就是简单看下镜像的创建时间(没办法, 不同的 docker 源上最新版本可能存在差异, 我这次就被坑惨了!!!)

-
docker运行: 如下命令, 运行snowdreamtech/frpc, 这里唯一要调整的是-v /Users/qianyin/frp/frpc.toml:/etc/frp/frpc.toml, 要将前面我本地配置文件路径改成你自己的
docker run -d \--network host \-v /Users/qianyin/frp/frpc.toml:/etc/frp/frpc.toml \--name frpc \snowdreamtech/frpc

-
同样的, 这里我们可以通过
docker logs frpc来查看启动日志

-
当然我们也可以通过查看
frps仪表板中客户端连接数, 来确定frpc的连接情况

3.3 将内网上本地 html 服务暴露到公网(tcp 版本)
-
首先本地我们先起一个服务, 我这里直接使用
vscode插件 Live Server 起了一个静态服务

-
下面我们修改
frpc配置文件, 添加一个代理配置, 我们希望的是, 当访问公网ip/域名:7001能够通过frps转发到内网上的frpc服务上, 然后再通过fprc代理到内网的192.168.0.108:5500上; 配置完整内容如下, 参数介绍看注释, 主要就是加了[[proxies]]配置:
# frpc.tomlserverPort = 7000 # [必选] 要连接的 frps 端口serverAddr = "www.kunlunxu.cc" # [必选] 要连接的 frps 地址log.to = "console" # [可选] 日志配置, 通过打印的方式输出日志auth.token = "password" # [可选] token 设置, frps 设置的 token, 其实就是密码+ [[proxies]]+ name = "web" # 代理名称(随便填)+ type = "tcp" # 代理类型+ localIP = "192.168.0.108" # 代理地址, 要转发到哪个地址+ localPort = 5500 # 代理端口, 要转发到哪个端口+ remotePort = 7001 # 远程端口(和远程 frps 哪个端口绑定在一起, 访问对应端口将使用该代理)
重启 frpc: 其实就是重启 docker 容器
docker stop frpcdocker start frpc
访问 http://www.kunlunxu.cc:7001 将正常展示内网上本地项目:

下面是一个简易流程图:

3.4 将内网上本地 html 服务暴露到公网(html 版本)
下面我们换一种配置方式, 下面是完整配置内容如下, 参数介绍看注释; 因为我们在 frps 上设置了 vhostHTTPPort = 7100 那么当我们访问公网服务器 7100 端口时, 转发到 frpc 后会走 type = "http" 的配置:
# frpc.tomlserverPort = 7000 # [必选] 要连接的 frps 端口serverAddr = "www.kunlunxu.cc" # [必选] 要连接的 frps 地址log.to = "console" # [可选] 日志配置, 通过打印的方式输出日志auth.token = "password" # [可选] token 设置, frps 设置的 token, 其实就是密码[[proxies]]name = "web - tcp" # 代理名称(随便填)type = "tcp" # 代理类型localIP = "192.168.0.108" # 代理地址, 要转发到哪个地址localPort = 5500 # 代理端口, 要转发到哪个端口remotePort = 7001 # 远程端口(和远程 frps 哪个端口绑定在一起, 访问对应端口将使用该代理)+ [[proxies]]+ name = "web - html" # 代理名称(随便填)+ type = "http" # 代理类型+ localIP = "192.168.0.108" # 代理地址, 要转发到哪个地址+ localPort = 5500 # 代理端口, 要转发到哪个端口+ customDomains = ["www.kunlunxu.cc"] # 限制公网地址, 只有对应地址上
frps 转发了 html 才会走到这里
重启 frpc: 其实就是重启 docker 容器
docker stop frpcdocker start frpc
访问 http://www.kunlunxu.cc:7100 将正常展示内网上本地项目:


下面是一个简易流程图:

四、遇到问题
1、版本问题: 目前网上大部分文章的配置文件还是 frps.ini 或 frpc.ini, 写法上也是老的写法, 所以这里如果你安装的是最新版本那么一定请以 frp 官网 为准
2、如何确定 Docker 容器使用的配置文件是哪个? 答案是可直接查看容器的信息来进行确认

如何查看日志? 正如上文可在配置文件中设置 log.to = "console" 并配合 docker logs 来查看服务输出的日志
-
上文中
webServer.addr设置了"0.0.0.0", 是因为默认情况下是该值为127.0.0.1, 在测试过程中发现如果保持默认值无法访问到仪表盘页面了!!! -
在最开始我是跑了一个
React项目, 然后试图在frpc中将项目暴露出去, 最后发现一直无法代理成功!!! 经排查发现原来该项目无法通过内网IP进行访问的, 当然相对的解决办法就是需要调整webpack中的配置!! 后来省方便就直接使用vscode插件 Live Server 起了一个静态服务来进行测试!! 所以这里主要就是想提醒下, 在测试前请确保你的本地服务能够正常通过内网IP进行访问, 同时配置中尽量不要直接写127.0.0.1, 尽量使用具体的内网IP
-
在阿里云上, 拉取 snowdreamtech/frps 镜像时总是发现最新版本和
hub.docker上对不上, 经排查发现问题出在Docker配置的源上, 由于我这边使用了 阿里云加速器, 但是由于Docker Hub的限制, 导致使用镜像加速器后无法获取最新官方镜像, 暂时解决办法就是去掉加速器配置, 直接连接Docker Hub进行获取:
rm /etc/docker/daemon.jsonsudo systemctl daemon-reloadsudo systemctl restart docker
链接:https://juejin.cn/post/7293392480452247562
(版权归原作者所有,侵删)


















