FRP内网穿透详解
我们家中用的宽带一般都是没有外网IP的,这就要访问家中的服务和设备(如NAS、摄像头、数据库)时很不方便;我们今天就来介绍内网穿透,让我们能轻松访问家中的服务和设备。
基础介绍
参考:
是什么?
frp是一个快速反向代理,允许您将位于NAT或防火墙后面的本地服务器暴露给Internet。它目前支持TCP和UDP,以及HTTP和HTTPS协议,使请求能够通过域名转发到内部服务。
为什么使用 frp?
通过在具有公网 IP 的节点上部署 frp 服务端,可以轻松地将内网服务穿透到公网,同时提供诸多专业的功能特性,这包括:
- 客户端服务端通信支持 TCP、KCP 以及 Websocket 等多种协议。
- 采用 TCP 连接流式复用,在单个连接间承载更多请求,节省连接建立时间。
- 代理组间的负载均衡。
- 端口复用,多个服务通过同一个服务端端口暴露。
- 多个原生支持的客户端插件(静态文件查看,HTTP、SOCK5 代理等),便于独立使用 frp 客户端完成某些工作。
- 高度扩展性的服务端插件系统,方便结合自身需求进行功能扩展。
- 服务端和客户端 UI 页面。
原理
看下官方的架构:frp 主要由 客户端(frpc) 和 服务端(frps) 组成,服务端通常部署在具有公网 IP 的机器上,客户端通常部署在需要穿透的内网服务所在的机器上。
通俗理解:frps 服务端有点像接线员【具备公网IP】的角色,frpc客户端就好比家里的座机【只有局域网IP,但可以主动访问互联网】,当我们在外部使用公共电话拨打时,先到接线员这里,要求转接到某某座机【就是端口】,接线员就从座机列表中【管理的客户端连接池】,找到对应的座机,转接过去,这样就完成了从外部互联网访问内部服务器的过程。
1 | 补充一点自己的认识: |
对应到本项目的架构如下:
使用示例
- 通过 SSH 访问内网机器
- 通过自定义域名访问内网的 Web 服务
- 转发 DNS 查询请求
- 转发 Unix 域套接字
- 对外提供简单的文件访问服务
- 为本地 HTTP 服务启用 HTTPS
- 安全地暴露内网服务
- 点对点内网穿透
关于配置文件说明
推荐使用 TOML, YAML, JSON 这3种格式,目前还支持 INI 格式,但未来是会被删除的。
Since v0.52.0, we support TOML, YAML, and JSON for configuration. Please note that INI is deprecated and will be removed in future releases. New features will only be available in TOML, YAML, or JSON. Users wanting these new features should switch their configuration format accordingly.
Read the full example configuration files to find out even more features not described here.
Examples use TOML format, but you can still use YAML or JSON.
frps_full_example.toml
shell 复制代码
1 | # This configuration file is for reference only. Please do not use this configuration directly to run the program as it may have various issues. |
frpc_full_example.toml
shell 复制代码
1 | # This configuration file is for reference only. Please do not use this configuration directly to run the program as it may have various issues. |
内网穿透实施
远程运维本地虚拟机
服务端配置
从官网下载对应版本和操作系统的安装包(frp_0.52.3_linux_amd64.tar.gz)
通过
rz
上传到云服务器中,使用tar
命令解压即可1
2
3
4# 转义控制符,从宿主机读取文件到服务中
rz -e
# 解压软件
tar -xvf frp_0.52.3_linux_amd64.tar.gz使用
vi frps.toml
编辑frps的配置文件frps.toml
,进行配置:1
2
3
4
5
6
7
8
9
10
11# frps的通信端口,提供给客户端找到并发起请求,建立长连接
bindPort = 7070
# 与frpc通信的认证方式和token值
auth.method = "token"
auth.token = "SQl_7233261"
# 面板的端口、账号和密码
webServer.addr = "0.0.0.0" #注意该参数,可以接受任意地址
webServer.port = 7500
webServer.user = "admin"
webServer.password = "gogNmGxwEWOEJlOv"- 特别说明下 0.0.0.0和127.0.0.1的区别:
1
2
3
4
5
6
7
8
9
10
11
12
130.0.0.0:
在网络通信中,0.0.0.0是一个特殊的IP地址,被称为"通配符地址"或"任意地址"。
当一个网络接口绑定到0.0.0.0时,它表示该网络接口将接受来自任何IP地址的所有数据包。
在服务器配置中,将服务绑定到0.0.0.0意味着该服务将监听其所在计算机上的所有可用网络接口,以接受来自任何源IP地址的连接请求。
127.0.0.1:
127.0.0.1是一个保留的IPv4回环地址,通常称为"本地主机"或"回环地址"。
当你的计算机尝试通过网络协议访问127.0.0.1时,数据包不会通过物理网络接口发送,而是在计算机本地内部传输。
127.0.0.1通常用于本地主机上部署的服务之间进行通信,例如本地开发环境中的Web服务器与数据库之间的通信。
总结:
0.0.0.0表示接受来自任何源IP地址的数据包,适用于网络通信和服务器配置。
127.0.0.1是本地主机地址,用于本地主机上的本地通信,适用于回环测试和本地开发环境。运行frp的服务端 :
1
2
3
4# 直接运行
./frps -c frps.toml
# 一般会使用 nohup命令,后台运行
nohup ./frps -c frps.toml &验证下frps启动情况:
1
netstat -nlp | grep frps
服务器的防火墙配置
见文章:虚拟机的初始准备及一般操作
服务端配置(docker-compose方式)
安装docker、docker-compose(略)
在适当文件夹建立 ‘./docker-compose/frps’ 文件夹
准备frps.toml文件(根据版本,该文件格式可能不同)
1
2
3
4
5
6
7
8
9
10
11# frps的通信端口,提供给客户端找到并发起请求,建立长连接
bindPort = 7070
# 与frpc通信的认证方式和token值
auth.method = "token"
auth.token = "SQl_7233261"
# 面板的端口、账号和密码
webServer.addr = "0.0.0.0" #注意该参数,可以接受任意地址
webServer.port = 7500
webServer.user = "admin"
webServer.password = "gogNmGxwEWOEJlOv"准备docker-compose.yml文件
1
2
3
4
5
6
7
8
9
10
11version: '3'
services:
frps:
image: snowdreamtech/frps:0.60
container_name: frps
restart: always
network_mode: host
volumes:
# 注意这里将刚才创建的frps.toml文件映射作为该应用的配置文件使用,要注意文件路径
- ./frps.toml:/etc/frp/frps.toml输入命令安装并启动程序
1
docker-compose up -d
查看程序是否启动成功,端口号是否正确使用
1
2
3docker ps -a
#
netstat -nlp | grep frps配置防火墙
见文章:虚拟机准备及一般操作
客户端配置
和服务端类似,上传并解压软件
1
2
3
4# 转义控制符,从宿主机读取文件到服务中
rz -e
# 解压软件
tar -xvf frp_0.52.3_linux_amd64.tar.gz编辑客户端frpc的配置文件
frpc.toml
:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18user = "fc"
# frps的地址和通信端口
serverAddr = "139.155.229.99"
serverPort = 7070
# 与frps通信的认证方式和token值
auth.method = "token"
auth.token = "SQl_7233261"
[[proxies]]
name = "ssh_local"
type = "tcp"
# 服务的实际ip(比如我们在虚拟机配置了某个服务,就可以将ip和端口修改)
localIP = "127.0.0.1"
# 服务的实际端口
localPort = 80
# If remotePort is 0, frps will assign a random port for you
# 这个接口的意思是 我们希望外部可以通过这个接口访问这个服务(即访问 “http://服务端ip:6060”)
remotePort = 6060启动客户端配置:
1
2
3
4# 直接运行
./frpc -c frpc.toml
# 一般会使用 nohup命令,后台运行:
nohup ./frpc -c frpc.toml &
客户端配置(Windows系统Frpc-Desktop方式)
下载并安装Frpc-Desktop
进入’系统配置‘界面,选择frp版本(没有就下载,要下载与服务端frps一致的版本),服务器地址、服务器端口(bindPort)、验证方式按照frps.toml中的对应项配置
进入’穿透列表‘界面,点击’新增代理‘,’代理类型‘选择开放防火墙时开放的接口类型(一般是tcp),代理名称自己配置,内网地址和接口即服务实际运行的ip和接口(例如’127.0.0.1‘,’80‘),外网接口是从公网通过该接口访问服务(http://服务端ip:remotePort)
进入’连接‘页面,点击’启动‘即可,点击’查看日志‘,可以查看是否代理成功
- 注意:需要去服务端所在的服务器开放配置的外网端口(操作命令见虚拟机的初始准备及一般操作),云服务器还需要去控制台开放端口
systemd 管理 frp 实践
如Linux服务端上没有安装
systemd
,可以使用yum
或apt
等命令安装systemd
1
2
3
4# yum
yum install systemd
# apt
apt install systemd使用文本编辑器,如
vim
创建并编辑frps.service
文件1
vi /etc/systemd/system/frps.service
写入内容:
1
2
3
4
5
6
7
8
9
10
11[Unit]
# 服务名称,可自定义
Description = frp server
After = network.target syslog.target
Wants = network.target
[Service]
Type = simple
# 启动frps的命令,需修改为您的frps的安装路径
ExecStart = /opt/software/frp/frps -c /opt/software/frp/frps.toml
[Install]
WantedBy = multi-user.target使用
systemd
命令,管理 frps。1
2
3
4
5
6
7
8
9
10
11
12# 启动frp
systemctl start frps
# 停止frp
systemctl stop frps
# 重启frp
systemctl restart frps
# 查看frp状态
systemctl status frps
# 配置 frps 开机自启
systemctl enable frps
# 禁止开机启动
systemctl disable frps配置 frpc的开启启动也类似,服务名改为
/etc/systemd/system/frpc.service
,启动命令修改为 frpc的即可1
2
3
4
5
6
7
8
9
10
11[Unit]
# 服务名称,可自定义
Description = frp client
After = network.target syslog.target
Wants = network.target
[Service]
Type = simple
# 启动frpc的命令,需修改为您的frpc的安装路径
ExecStart = /opt/software/frp/frpc -c /opt/software/frp/frpc.toml
[Install]
WantedBy = multi-user.target