这篇文章将教会您如何使用FRP进行内网穿透,且教程将分为两部分
端口映射;内网穿透
理论
前言
众所周知,在这个ipv6还没有普及的时代,并不是所有运营商(没有对移动有任何偏见)都愿意为个人家庭提供ipv4公网ip,这个时候我们可以采取FRP,这是一个简单快捷的方法。
什么是内网穿透
内网穿透,也即 NAT 穿透,进行 NAT 穿透是为了使具有某一个特定源 IP 地址和源端口号的数据包不被 NAT 设备屏蔽而正确路由到内网主机。 说人话就是我们想在不连接家里的wifi的情况下访问我们家里面的电脑和其他设备时,由于家庭宽带没有固定的公网ip使得我们无法向访问云服务器一样 直接访问,这时候我们就需要使用到内网穿透技术,让我们在其他网络下也能访问到处于内网环境的设备。而内网穿透的工具也有很多如: - 花生壳 - nat123 - ngrok - frp -ogfrp -路由侠
什么是FRP
Frp (Fast Reverse Proxy) 是比较流行的一款。FRP 是一个免费开源的用于内网穿透的反向代理应用,它支持 TCP、UDP 协议, 也为 http 和 https 协议提供了额外的支持。你可以粗略理解它是一个中转站, 帮你实现 公网 ←→ FRP(服务器) ←→ 内网 的连接,让内网里的设备也可以被公网访问到。
而目前 FRP 还推出了“点对点穿透”的试验性功能,连接成功后可以让公网设备直接跟内网设备“点对点”传输,数据流不再经过 VPS 中转, 这样可以不受服务器带宽的限制,传输大文件会更快更稳定。当然,此功能并不能保证在你的网络环境 100% 可用,而且还要求访问端也得运行 FRP 客户端 (因此目前手机是无法实现的,只有电脑可以)。由于实现条件较多,所以有文件传输需求的朋友还是建议买带宽稍大一点的 VPS 会比较省心。
部署FRP(适用于自己有服务器且非常简单)
首先我们得要有一台有公网ip的服务器,比如各大云服务器。然后我们就需要去服务器上安装服务端。
服务端安装与配置
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相关文件就行了 - 接下来我们开始对服务端进行配置 vim frps.ini
[common]
bind_port = 7000
bind_addr = 0.0.0.0
token = 123456
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
➜ ~ 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 = 123456
[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
下面是frp github介绍中一些配置示例
ssh
修改frps.ini:
# frps.ini
[common]
bind_port = 7000
启动frps:./frps -c ./frps.ini
修改frpc.ini,server_addr是你的frps的服务器IP:
# frpc.ini
[common]
server_addr = xxxx server_port = 7000
[ssh]
type = tcp local_ip = 127.0.0.1 local_port = 22 remote_port = 6000
启动frpcz:./frpc -c ./frpc.ini
假设用户名为test,则通过ssh连接到LAN中的服务器:ssh -oPort=6000 test@x.x.x.x
通过自定义域访问LAN中的Web服务
有时我们希望将NAT网络后面的本地Web服务公开给其他人以使用您自己的域名进行测试,但是无法将域名解析为本地IP。我们可以使用frp公开http或https服务。
修改frps.ini,配置http端口8080:
# frps.ini
[common]
bind_port = 7000 vhost_http_port = 8080
启动frps:./frps -c ./frps.ini
修改frpc.ini并将远程frps服务器的IP设置为xxxx这local_port是您的Web服务的端口:
# frpc.ini
[common]
server_addr = xxxx server_port = 7000
[web]
type = http local_port = 80 custom_domains = www.yourdomain.com
启动frpc:./frpc -c ./frpc.ini
解析域名到frp的IP地址,然后使用url访问您的本地Web服务
转发DNS查询请求
修改frps.ini:
# frps.ini
[common]
bind_port = 7000
修改frpc.ini,将远程frps的服务器IP设置为xxxx,将dns查询请求转发到google dns服务器8.8.8.8:53:
# frpc.ini
[common]
server_addr = xxxx server_port = 7000
[dns]
type = udp local_ip = 8.8.8.8 local_port = 53 remote_port = 6000
通过dig发送dns查询请求:
dig @x.x.x.x -p 6000 www.google.com
转发unix域套接字,使用tcp端口连接unix域套接字,如docker守护进程。
配置与上面相同的frps。 配置frpc.ini
# frpc.ini
[common]
server_addr = xxxx 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://x.x.x.x:6000/version
公开一个简单的http文件服务器
配置与上面相同的frps 配置启动frpc:
# frpc.ini
[common]
server_addr = xxxx server_port = 7000
[test_static_file]
type = tcp remote_port = 6000 plugin = static_file plugin_local_path = /tmp/file plugin_strip_prefix = static plugin_http_user = abc plugin_http_passwd = abc
访问http://x.x.x.x:6000/static/
,输入正确的用户和密码,就可以查看文件/tmp/file
。
在安全性中公开您的服务
对于某些服务,如果直接将它们暴露给公共网络将存在安全风险。stcp(secret tcp)帮助您创建代理,避免任何人可以访问它。 配置与上面相同的frps。 启动frpc,转发ssh端口并且remote_port没用:
# frpc.ini
[common]
server_addr = xxxx server_port = 7000
[secret_ssh]
type = stcp sk = abcdefg local_ip = 127.0.0.1 local_port = 22
启动另一个要连接此ssh服务器的frpc:
# frpc.ini
[common]
server_addr = xxxx server_port = 7000
[secret_ssh_visitor]
type = stcp role = visitor server_name = secret_ssh sk = abcdefg bind_addr = 127.0.0.1 bind_port = 6000
假设用户名为test,则通过ssh连接到LAN中的服务器: ssh -oPort=6000 test@127.0.0.1
P2P模式
xtcp旨在直接在两个客户端之间传输大量数据。现在它无法穿透所有类型的NAT设备。如果xtcp不起作用,您可以尝试使用stcp。
配置xtcp的udp端口:
bind_udp_port = 7001
启动frpc,转发ssh端口并且remote_port没用:
# frpc.ini
[common]
server_addr = xxxx server_port = 7000
[p2p_ssh]
type = xtcp sk = abcdefg local_ip = 127.0.0.1 local_port = 22
启动另一个要连接此ssh服务器的frpc:
# frpc.ini
[common]
server_addr = xxxx server_port = 7000
[p2p_ssh_visitor]
type = xtcp role = visitor server_name = p2p_ssh sk = abcdefg bind_addr = 127.0.0.1 bind_port = 6000
假设用户名为test,则通过ssh连接到LAN中的服务器: ssh -oPort=6000 test@127.0.0.1
认证
- 从v0.10.0开始,您只需要token在frps.ini和frpc.ini中进行设置。
- 请注意,frpc和frps服务器之间的持续时间不得超过15分钟,因为时间戳用于身份验证。然后,可以通过设置authentication_timeoutfrps的配置文件来修改此超时持续时间。它的defalut值是900,意味着15分钟。如果它等于0,则frps将不检查身份验证超时。
端口重用
现在vhost_http_port和vhost_https_portfrps可以使用相同的端口bind_port。frps将检测连接的协议并相应地处理它。 我们希望尝试允许多个代理在将来使用不同的协议绑定相同的远程端口。
支持KCP协议
frp支持kcp协议,自v0.12.0起。 KCP是一种快速可靠的协议,可以实现将平均延迟降低30%至40%并将最大延迟降低三倍的传输效果,其代价是浪费10%至20%的带宽浪费比TCP。 在frp中使用kcp:
#frps.ini
[command]
bind_port = 7000 kcp_bind_port = 7000 # KCP需要绑定一个UDP端口
配置frpc中使用的协议连接frps:
# frpc.ini
[command]
SERVER_ADDR = XXXX SERVER_PORT = 7000 protocol = KCP
负载均衡
支持负载均衡group。此功能仅适用于tcp现在的类型。
# 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
同一组中的代理将随机接受来自端口80的连接。
重写主机标头
转发到本地端口时,frp根本不会修改隧道HTTP请求,它们会在收到时逐字节地复制到服务器。某些应用程序服务器使用Host标头来确定要显示的开发站点。因此,frp可以使用修改后的主机头重写您的请求。使用该host_header_rewrite开关重写传入的HTTP请求。
# frpc.ini
[web]
type = http local_port = 80 custom_domains = test.yourdomain.com host_header_rewrite = dev.yourdomain.com
如果host_header_rewrite指定,则将重写主机头以匹配转发地址的主机名部分。
在HTTP请求中设置标头
您可以为代理类型设置标头http。
# frpc.ini
[web]
type = http local_port = 80 custom_domains = test.yourdomain.com host_header_rewrite = dev.yourdomain.com header_X-From-Where = frp
请注意,具有前缀的参数header_将添加到http请求标头中。在此示例中,它将标头设置X-From-Where: frp为http请求。
获取客户端真正的IP
仅限http代理的功能。 你可以从HTTP请求头获取用户的真实IP X-Forwarded-For和X-Real-IP。请注意,现在您只能在每个用户连接的第一个请求中获取这两个标头。
URL路由
frp支持通过url路由将http请求转发到不同的后向Web服务。 locations指定用于路由的URL前缀。frps首先搜索由文字字符串给出的最具体的前缀位置,而不管列出的顺序如何。
# frpc.ini
[web01]
type = http local_port = 80 custom_domains = web.yourdomain.com locations = /
[web02]
type = http local_port = 81 custom_domains = web.yourdomain.com locations = / news,/ about
HTTP与URL前缀请求/news和/about将被转发到web02和他人WEB01。
范围端口映射
代理名称前缀range:将支持映射范围端口。
# frpc.ini
[range:test_tcp]
type = tcp local_ip = 127.0.0.1 local_port = 6000-6006,6007 remote_port = 6000-6006,6007
frpc将生成8个代理test_tcp_0, test_tcp_1 … test_tcp_7。
插件
frpc默认只向本地tcp或udp端口转发请求。而插件提供了丰富的功能。内置的插件有unix_domain_socket,http_proxy,socks5,static_file。
指定plugin参数使用的插件。插件的配置参数应该以plugin_。local_ip并且local_port对插件没用。
使用FRP代理商(适用于完全没有动手能力或懒者)
演示中使用的FRP:https://ogfrp.cn/
进入官网,注册账号
进入主界面点击侧边栏中的创建隧道
按照个人需求选择合适的服务器,填写映射信息
隧道类型介绍
提示:XTCP 映射成功率并不高,具体取决于 NAT 设备的复杂度。
TCP 映射
基础的 TCP 映射,适用于大多数服务,例如远程桌面、SSH、Minecraft、泰拉瑞亚等
UDP 映射
基础的 UDP 映射,适用于域名解析、部分基于 UDP 协议的游戏等
HTTP 映射
搭建网站专用映射,并通过 80 端口访问。
HTTPS 映射
带有 SSL 加密的网站映射,通过 443 端口访问,服务器需要支持 SSL。
XTCP 映射
客户端之间点对点 (P2P) 连接协议,流量不经过服务器,适合大流量传输的场景,需要两台设备之间都运行一个客户端。
STCP 映射
安全交换 TCP 连接协议,基于 TCP,访问此服务的用户也需要运行一个客户端,才能建立连接,流量由服务器转发。
创建完后点击左侧栏每日签到可免费获得流量,每天都能领取一次
领取后可点击隧道列表可核对隧道信息、设置隧道启动状态、管理和删除隧道
最后在部署客户端时我们建议您使用原生的FRP客户端,点击配置文件,选择节点服务器,复制全部内容(如图)
配置文件说明
每次创建完映射或删除了映射之后配置文件都会发生变化,请在变更后及时更新您的配置文件。
请勿泄露配置文件中 user 字段的内容,否则他人可以登录您的账号,截图注意打码。
不过,如果真的泄露了,可以通过修改密码来解决,User 字段的内容也会随之更新。
前往代码仓库下载原生的FRP软件并解压到一个空文件夹中(https://github.com/fatedier/frp)
随后,请使用有权威的编辑器编辑frpc.int(有权威的编辑器:例如VSCODE、Notepad++、Sublime Text等,点击可跳转)
使用复制到的内容替换文件内的内容并保存
运行根目录下的frpc.exe这样就成功启动了(注意:关闭批处理窗口将会关闭端口映射)