什么是内网穿透,什么是FRP
内网穿透,也即 NAT 穿透,进行 NAT 穿透是因为家庭宽带普遍没有公网ip,家庭设备或搭建的服务,无法像云服务器一样访问便捷,这时候就需要使用到内网穿透技术,内网穿透工具有很多,如: – 花生壳 、nat123 、ngrok 、frp。本文主要讲FRP的搭建和使用。
FRP (Fast Reverse Proxy) 是一个免费开源的用于内网穿透的反向代理应用,它支持 TCP、UDP 协议, 也为 http 和 https 协议提供了额外的支持。可以粗略理解它是一个中转站, 帮助实现 公网 ←→ FRP(服务器) ←→ 内网 的连接服务。实现FRP的前条件是要有一台有公网ip的服务器,比如各大云服务器。
目前 FRP 还推出了“点对点穿透”的试验性功能,连接成功后可以让公网设备直接跟内网设备“点对点”传输,数据流不再经过 VPS 中转, 这样可以不受服务器带宽的限制,传输大文件会更快更稳定。当然,此功能并不能保证在所有网络环境 100% 可用,而且还要求访问端也得运行 FRP 客户端 (因此目前手机是无法实现的,只有电脑可以)。由于实现条件较多,所以有文件传输需求的朋友还是建议VPS 会比较省心点,最好还能尽量买带宽高的。
服务端安装与配置
FRP 使用 Go 语言开发,支持 Windows、Linux、macOS、ARM 等多平台部署。FRP 安装非常容易,只需下载对应系统平台的软件包并解压就可以使用了。 这里以Linux系统Ubuntu 18.04为例:
首先下载对应的安装包。自行选择对应的版本 https://github.com/fatedier/frp/releases,在终端输入
curl -# -LJO https://github.com/fatedier/frp/releases/download/v0.34.3/frp_0.34.3_linux_amd64.tar.gz
没有安装curl要先安装curl当然wget同样也能下载
wget https://github.com/fatedier/frp/releases/download/v0.34.3/frp_0.34.3_linux_amd64.tar.gz
在终端输入使用tar指令解压tar.gz文件
tar -zxvf frp_0.34.3_linux_amd64.tar.gz
进入解压后的文件夹,删除frps.ini\ frps\ LICENSE以外的其他文件,带有full字样的是服务端和客户端全部配置实例文件,- 接下来开始对服务端的frps.ini文件进行配置,在终端输入vim frps.ini命令,添加以下内容,最后不要忘了:wq保存
[common]
bind_port = 7000
bind_addr = 0.0.0.0
token = frp123
dashboard_port = 37500
dashboard_user = admin
dashboard_pwd = admin
[common]部分是必须有的配置,其中bind_port是自己设定的frp服务端端口,bind_addr是绑定的ip地址默认为0.0.0.0即本机的所有ip地址。 token用于验证连接,只有服务端和客户端token相同的时候才能正常访问。如果不使用token,那么所有人都可以直接连接上,所以建议大家在使用的时候还是把token加上。 而下面的[dashboard]仪表盘的配置(可以不配置) 配置了的化可以访问服务器ip:dashboard_port 通过dashboard_user和dashboard_pwd登陆后查看frp服务器状态
服务端这样配置就可以了,其他高级功能请参考官方文档。
- 启动服务端命令
./frps -c frps.ini
- 为避免每次重启系统都要去手动启动,需要用如下命令把frps注册成系统服务:
sudo vim /lib/systemd/system/frps.service
然后在frps.service文件里写入:
[Unit]
Description=frp server
After=network.target
[Service]
Type=simple
ExecStart=/your path/frps -c /your path/frps.ini
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
[Install]
WantedBy=multi-user.target
- 最后就可以启动建立的frps服务了
sudo systemctl start frps
- 打开自启动
sudo systemctl enable frps
- 查看状态和日志信息:
sudo systemctl status frps
frps.service - fraps service
Loaded: loaded (/lib/systemd/system/frps.service; enabled; vendor preset: enabled)
Active: active (running) since Thu 2020-12-17 17:14:06 CST; 49s ago
Main PID: 28974 (frps)
Tasks: 5 (limit: 4465)
CGroup: /system.slice/frps.service
28974 /root/frp/frps -c /root/frp/frps.ini
Dec 17 17:14:06 VM-0-15-ubuntu systemd[1]: Started fraps service.
Dec 17 17:14:06 VM-0-15-ubuntu frps[28974]: 2020/12/17 17:14:06 [I] [service.go:190] frps tcp listen on 0.0.0.0:700
Dec 17 17:14:06 VM-0-15-ubuntu frps[28974]: 2020/12/17 17:14:06 [I] [service.go:289] Dashboard listen on 0.0.0.0:37
Dec 17 17:14:06 VM-0-15-ubuntu frps[28974]: 2020/12/17 17:14:06 [I] [root.go:215] start frps success
- 重启应用服务:
sudo systemctl restart frps
- 停止应用服务:
sudo systemctl stop frps
到这里服务端已经完成配置,现在就可以访问frp仪表盘了。
客户端的配置
首先客户端也要先去下载对应的安装包。自行选择对应的版本 https://github.com/fatedier/frp/releases
然后我们需要对frpc.ini进行配置 这里以windows远程文件共享为例
[common]
# 服务器的公网地址
server_addr = X.X.X.X
# 7000为服务端frp与客户端frp相互通信的端口就是我们服务端配置的监听端口
server_port = 7000
token = frp123
[smb]
# win10文件共享smb协议通过tcp通信
type = tcp
local_ip = 127.0.0.1
# smb协议的本地端口
local_port = 445
# 设定远程端口,当访问服务器的7002端口时,数据会被转发到本地445端口
remote_port = 7002
其他配置类似,请参考官方文档。 – 接着我们就可以启动客户端了。 powershell启动客户端frp ./frpc -c frpc.ini
使用具有访问smb服务器能力的软件进行访问。我是用ios的FileExplorer和nPlayer进行访问的。软件设置主机地址为X.X.X.X,端口为7002。注意,有些软件不能设置smb服务器的端口,比如OPlayer,它只能使用默认的445端口,所以要把remote_port配置成445才可以使用。
当然我们还可以设置客户端的自启动,以Windows电脑为例: 1. 首先编写启动脚本
Set ws = CreateObject("Wscript.Shell")
ws.run "cmd /c c:\frps\frpc.exe -c c:\frps\frpc.ini",vbhide
/c c:\frps
请自行更换成你自己电脑的frp所在路径 2. 然后把vbs放到启动目录即可 C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp
客户端插件
默认情况下,frpc 只会转发请求到本地 TCP 或 UDP 端口,也就是通过 local_ip
和 local_port
指定的本地服务地址。
通过客户端插件的功能将一些简单的本地服务内置在 frpc 中,可以帮助用户在只启动 frpc 的情况下实现原本需要额外启动其他服务才能实现的功能。
在每一个代理的配置中,通过 plugin
指定需要使用的插件,插件的配置参数都以 plugin_
开头。当启用客户端插件后,local_ip
和 local_port
不再需要配置。
客户端插件可以被应用在任意类型的代理中,但是需要插件本身的协议能够支持。例如静态文件访问插件可以通过 TCP 或者 HTTP 的代理暴露出去。
使用 http_proxy
插件的示例:
# frpc.ini
[http_proxy]
type = tcp
remote_port = 6000
plugin = http_proxy
plugin_http_user = abc
plugin_http_passwd = abc
plugin_http_user
和 plugin_http_passwd
即为 http_proxy
插件可选的配置参数。
http_proxy
HTTP 代理插件,用于将内网机器作为 HTTP 代理暴露给其他服务,可以通过此代理访问到此内网机器能够访问到的其他服务。
参数 | 可选 | 描述 |
---|---|---|
plugin_http_user | 是 | HTTP 代理用户名 |
plugin_http_passwd | 是 | HTTP 代理密码 |
socks5
SOCKS5 代理。
参数 | 可选 | 描述 |
---|---|---|
plugin_user | 是 | 连接代理的用户名 |
plugin_passwd | 是 | 连接代理的密码 |
static_file
静态文件浏览服务,通过暴露一个简单的 HTTP 服务查看指定的目录下的文件。
参数 | 可选 | 描述 |
---|---|---|
plugin_local_path | 否 | 要对外暴露的文件目录 |
plugin_strip_prefix | 是 | 用户请求的 URL 路径会被映射到本地文件,如果希望去除用户访问文件的前缀,需要配置此参数 |
plugin_http_user | 是 | HTTP BasicAuth 用户名 |
plugin_http_passwd | 是 | HTTP BasicAuth 密码 |
unix_domain_socket
代理本地 Unix 域套接字的服务。
参数 | 可选 | 描述 |
---|---|---|
plugin_unix_path | 否 | 本地 Unix 域套接字地址 |
http2https
将本地的 HTTPS 服务以 HTTP 的形式暴露出去。
参数 | 可选 | 描述 |
---|---|---|
plugin_local_addr | 否 | 本地服务地址 |
plugin_host_header_rewrite | 是 | 如果配置,发送给本地服务的请求的 Host 字段会被修改 |
plugin_header_{header name} | 是 | 发送给本地服务的请求会被加上指定的 header 字段 |
https2http
将本地的 HTTP 服务以 HTTPS 的形式暴露出去。
参数 | 可选 | 描述 |
---|---|---|
plugin_local_addr | 否 | 本地服务地址 |
plugin_crt_path | 是 | HTTPS 所需的证书文件,如果 crt 和 key 都为空,则使用自动生成的证书 |
plugin_key_path | 是 | HTTPS 所需的密钥文件 |
plugin_host_header_rewrite | 是 | 如果配置,发送给本地服务的请求的 Host 字段会被修改 |
plugin_header_{header name} | 是 | 发送给本地服务的请求会被加上指定的 header 字段 |
https2https
将本地的 HTTPS 服务以 HTTPS 的形式暴露出去。
参数 | 可选 | 描述 |
---|---|---|
plugin_local_addr | 否 | 本地服务地址 |
plugin_crt_path | 是 | HTTPS 所需的证书文件,如果 crt 和 key 都为空,则使用自动生成的证书 |
plugin_key_path | 是 | HTTPS 所需的密钥文件 |
plugin_host_header_rewrite | 是 | 如果配置,发送给本地服务的请求的 Host 字段会被修改 |
plugin_header_{header name} | 是 | 发送给本地服务的请求会被加上指定的 header 字段 |