共计 4887 个字符,预计需要花费 13 分钟才能阅读完成。
背景
任何一台连接网络的设备都有一个自己的IP地址,平时使用手机和电脑上网访问某些资源时,就需要从公网上的网络资源进行获取。以我们用手机上B站学习为例,当我们进入App时,手机会向公网上的DNS服务器发送一个查询请求,请求DNS服务器将bilibili.com
域名对应的IP地址返回,手机拿到bilibili.com
的IP地址后,就会通过TCP/IP协议进行数据交互,将相关的资源返回并渲染出来。
目前,绝大多数的网站都有一个自己的IPv4地址,而我们现在使用的网络地址IPv4,总共可分配大约43亿个地址(2^32),早在2019年11月25日,全球五大区域互联网注册管理机构之一的欧洲网络协调中心(RIPE NCC)宣布IPv4 地址已全部用完。
在IPv4用完的情况下,我们就急需想到一个办法让之后日益增多的网络设备都有一个自己的IP。目前主流的就两种方法,普及IPv6和NAT技术。
IPv6号称可以为地球上每一粒沙子分配一个IP地址,但目前IPv6仍在发展中,还有许多问题没有解决,因此难以普及。
而NAT技术则是继承原有的IPv4地址,通过NAT地址转换为每一个网络设备提供一个IP。简单来说,就是让一个区共同接入一个IPv4地址,然后通过这接入的唯一IP地址利用NAT技术为这一个区里的每个网络设备再分配一个IP地址。我所连接的网络最终连接的IPv4就是一个区级的。
NAT技术的引入就出现内外网的概念,通过NAT技术将某一IP地址转换为多个可再分配的地址就组成了一个内网,再加上NAT技术在网络层面上是可以无限套娃的,这就很容易导致网络的传输效率低下。同时,这种办法虽然可以让内网用户访问到外网的资源,但无法让外网的用户访问到内网的资源。
比如:宁夏张三同学连接着校园网在自己的电脑上部署了一个Web网站,而远在浙江的李四同学是无法访问的,即使张三同学通过ipconfig
查出了自己的IP地址,李四也是无法访问到张三的资源的。因为张三是在内网,李四是在外网(李四也有可能是在内网下,即两个不同的内网环境下也是无法直接互相访问的)。
为了让外网访问内网资源,或让两个内网之间可以互相访问对方的资源,内网穿透技术就出现了。内网穿透是一种将内网中的网络服务通过映射到公网服务器上,使得公网客户端可以直接访问内网中的网络服务的技术。正常情况下,内网中的计算机和网络设备只能在内网中互相通信,对于外网中的计算机来说,无法直接访问内网中的计算机和网络设备。这就导致了内网与外网之间的信息交换存在着困难和瓶颈。而内网穿透技术则可以打通这个障碍,让内网与外网之间的数据流动变得更加畅通和便利。
Frp介绍
frp 是一个专注于内网穿透的高性能的反向代理应用,支持 TCP、UDP、HTTP、HTTPS 等多种协议,且支持 P2P 点对点通信。可以将内网服务以安全、便捷的方式通过具有公网 IP 节点的中转暴露到公网上。
- Frp开源地址:https://github.com/fatedier/frp/
- Frp中文文档:https://gofrp.org/
- Frp作者博客:https://blog.fatedier.com/
原理介绍
Frp分为两个部分,服务端和应用端。
服务端运行在分配了IPv4的服务器上,并监听一个连接端口,等待客户端的连接。
客户端通过服务端监听的连接端口进行连接,并告诉服务端要去监听的端口和转发类型。
服务端fork一个新进程去监听客户端指定的端口;
外网用户通过连接客户端指定的端口,服务端再通过和客户端的连接将数据转发客户端;
客户端再将数据转发到本地服务,从而实现内网对外暴露服务的能力。
简单来说,就是找一个外网服务器来转发内网的数据。
准备工作
通过原理可以很清楚的知道,使用Frp实现内网穿透需要同时运行服务端和客户端,服务端一般部署在云服务器上,客户端一般部署在内网上,如本地电脑、家庭路由、NAS等。
要部署Frp并实现内网穿透,你需要准备以下东西:
- 云服务器一台:云服务基本都有一个IPv4地址
- 解析至云服务的域名:本篇文章需要实现自定义域名访问内网资源
- 学习求知的心态
本篇文章将介绍以下内容:
- 服务端部署及配置
- 客户端部署及配置
- Nginx反向代理配置
- 四级自定义域名实现内网穿透访问
搭建步骤
服务端Frp下载
Frp的下载可以直接从开源仓库里下:https://github.com/fatedier/frp/releases,注意要根据对应的平台选择对应的压缩包。
为了避免一些朋友下载的时候下载错,我已经把Ubuntu 22.04.3 LTS和Windows 10的压缩包放在一起供朋友们下载:http://share.rjkfteam.top/s/frp。
我们通过下述指令下载Frp压缩包:
wget https://github.com/fatedier/frp/releases/download/v0.51.3/frp_0.51.3_linux_amd64.tar.gz
没有下载wget的可以用apt install wget
进行下载。
下载完成后,通过下述指令解压缩:
tar -vxf frp_0.51.3_linux_amd64.tar.gz
当然,可以再重新命个名
mv frp_0.51.3_linux_amd64/ frp
我们可以看到压缩包里的内容非常少,这是因为Frp是用Go语言编写的,压缩包里的内容是已经编译好的可执行文件,不需要多余的文件。
文件中,frps开头的就是服务端的相关文件,frpc开头的就是客户端相关文件,以ini结尾的,是运行可执行文件的配置文件,带full的是完整配置文件,不带full的就是只给出必要的配置,其余配置可以根据业务自己补充。
服务端搭建
因为我们只需要在这台云服务器上部署服务端,客户端那块的文件就可以不用管。我们编辑frps.ini
,填写服务端的相关配置信息。
[common]
# 连接端口
bind_port = 7000
# 校验Token,为了你的服务端的安全,请设置得复杂些
token = ******
# Dashboard Web监控配置
## Web访问端口
dashboard_port = 7500
## Web访问的账号和密码
dashboard_user = youraccount
dashboard_pwd = yourpassword
## 是否提供 Prometheus 监控接口
enable_prometheus = true
## 最大连接池数量
max_pool_count = 4
# Http 服务端配置
## HTTP 类型代理监听的端口
vhost_http_port = 7001
## 为 HTTPS 类型代理监听的端口
vhost_https_port = 7123
## 解析到你服务端的域名,通过ping frp.yourdomain.com查看是否成功解析
## 这里我们是要实现自定义四级域名访问内网资源,因此这里使用三级域名作为后缀,服务端那块会再设置一个字符串,共同组成 xxx.frp.yourdomain.com
subdomain_host = frp.yourdomain.com
# 服务端日志配置
## 日志文件存放位置
log_file = /var/log/frps.log
## 日志等级
log_level = info
这里主要介绍的是Http的内网穿透,填写的也是一些基本信息,更多服务端配置请参考:https://gofrp.org/docs/reference/server-configures/,至于其它的业务场景,还请学会Http后自行对照文档进行学习。
服务端启动
启动服务端只需要指定服务端配置文件并运行frps
可执行文件即可:
./frps -c ./frps.ini
可以看到,服务端已经运行起来了
当然,我们并不能应用上述的运行方式进行部署,因为当你的终端关闭后,这个程序就会自动退出,需要使用下述方式运行:
# 后台运行
nohup ./frps -c ./frps.ini &
# 查看7000端口是否被监听
lsof -i :7000
服务端运行成功后,就可以不用管它了,后台的流量监控可以通过:服务端IP:7500
进行访问。
客户端Frp下载
本篇文章的客户端环境为Windows10,请从GitHub下载对应的压缩包,并解压。Windows下载和解压较为简单,这里不做介绍了。
本地项目运行
为了体现内网穿透,需要在本地准备一个localhost项目,我这里已经备好了,本地端口为:3000
.
现在就是要通过配置客户端配置文件frpc.ini
,实现一个四级域名的外网映射,让外网的人访问到我本地项目。
客户端配置
[common]
# 服务端信息
## 服务端的IPv4地址
server_addr = 163.***.***.98
## 服务端建立连接的端口
server_port = 7000
## 服务端连接时的校验Token,必须与服务端保持一致,否则无法连接
token = ******
[Web]
# http服务
## 数据类型
type = http
## 本地IP localhost、127.0.0.1或你用ipconfig得到的内网IP都可
local_ip = localhost
## 本地需要暴露在外网的端口,一般为你本地的项目端口
local_port = 3000
## 自定义域名的头部,和服务端配置的subdomain_host进行拼接,下面配置得到:test.frp.mnzdna.xyz
subdomain = test
Nginx 反代配置
我们需要通过对*.frp.mnzdna.xyz
进行泛化解析,将这一类的请求全部转发到服务端的7001
端口,请确保本地nginx正常运行。
创建一个Nginx配置文件:
vim /etc/nginx/conf.d/frps.nginx
填入下述信息:
server {
listen 80;
server_name *.frp.mnzdna.xyz frp.mnzdna.xyz;
location / {
proxy_pass http://localhost:7001;
# 这个Host的header一定要加,不然转发后frp拿不到通过哪个域名访问的,导致转发失败
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
然后重新加载Nginx:nginx -s reload
运行客户端
进入客户端frp文件夹下,上方输入cmd
,调出命名窗口:
然后像运行服务端一样,指定客户端配置文件运行客户端程序:
frpc.exe -c ./frpc.ini
可以看到,已经和服务端建立了连接。
访问与测试
之后,我们通过客户端配置的域名头部信息进行访问:test.frp.yourdomain.com
后台监控端相关信息:
可以看到,我们顺利得通过解析到外网主机上的域名访问到我本地的项目。为了严谨起见,我在一台没有运行frp客户端、IP位于美国的主机curl
下test.frp.yourdomain.com
这台位于美国的机子也能拿到我本地项目运行的数据。或许哪一天,你需要和你国外的朋友对你本地项目进行测试时,就可以通过内网穿透进行实现。
总结
内网穿透技术能够将外网无法访问的内网资源映射到外网上供外网的人访问,我们在自己的电脑上开发时,难免需要进行多人调试,若不通过内网穿透将你本地项目映射到外网上,那么调试的场景就是:一群人围着你的电脑一个一个测试,而有了这一技术,每个人都可以通过公网访问到你本地运行的项目,这极大地提高了开发效率。
在校园生活中,我们需要访问校园网内部机器时,也可以通过内网穿透实现,大学老师就可以通过这一技术随时从公网上获取校园网下的任何资源。