目录
一、为什么需要NAT?
二、NAT的核心:从“一对一”到“多对一”
(1)静态NAT
(2)动态NAT
(3)NAPT
三、NAPT的双刃剑:安全与局
四、内网穿透
(1)为什么需要内网穿透而不是简单的配置端口映射?
(2)第三方公网服务器作为中转站
五、常见的内网穿透成熟方案
(1)开放云服务器的安全组端口
(2)部署FRP服务端到云服务器上
1.下载并解压FRP包
2.编辑服务端配置文件
3.启动FRP服务端
(3)部署FRP客户端到物理机上
1.下载 FRP 客户端
2.解压 FRP 安装包
3.编辑 FRP 客户端配置文件 frpc.ini
4.启动FRP客户端
在之前我们已经简单了解过了NAT的原理,但是还有几个问题没有仔细考虑,本篇文章补充说明了这些,让我们对NAT和内网穿透的理解更加深刻。
一、为什么需要NAT?
在了解NAT之前,我们得先解决一个关键问题:IP地址不够用了。
互联网中的每一台设备(电脑、手机、服务器)要互相通信,都需要一个唯一的“身份证”——公网IP地址(比如你在网上看到的“202.97.xx.xx”)。但公网IP的总量是有限的(IPv4协议下约43亿个),随着手机、智能家电等设备爆发式增长,43亿个IP早就不够分配了。
这时候,NAT(Network Address Translation,网络地址转换) 技术应运而生。它的核心思路是:让一个“公网IP”代表多个“内网设备”。简单说,你家路由器会有一个从运营商那里分到的公网IP(现代家庭路由器可能也是运营商下面的内网IP),而家里的电脑、手机、平板用的是“内网私有IP”(比如“192.168.1.100”“10.0.0.5”)——这些私有IP只在你家内网有效,无法直接被互联网识别。当内网设备要访问外网时,路由器会把“私有IP”转换成“公网IP”,相当于用一个“公共身份证”帮所有内网设备“代办”上网业务,从而节省了大量公网IP资源。
二、NAT的核心:从“一对一”到“多对一”
最古老最基础的NAT是静态NAT,但是现在我们日常使用得更多的是动态NAT,但真正解决多设备共享一个公网IP的关键是NAPT。
(1)静态NAT
静态NAT是最简单的NAT形式,原理是“一个内网私有IP对应一个公网IP”,且这种对应关系是固定不变的。比如企业里有一台需要外网访问的服务器(内网IP:192.168.2.10),管理员会在路由器上配置“192.168.2.10 ↔ 203.0.113.5”的固定映射——外网设备访问203.0.113.5时,路由器会自动转发到192.168.2.10。
静态NAT的问题也很明显:它依然是“一对一”,一个内网只能有一个设备使用该公网IP对外通信,否则会公网冲突。
即全球在同一时刻仍然只能有43亿个设备接入公网,无法解决公网IP不够用的问题,更多用于需要“外网固定访问内网设备”的场景(如服务器),不是家庭或普通企业的首选。
(2)动态NAT
动态NAT会建立一个“公网IP池”(比如运营商分配给企业的10个公网IP),当内网设备访问外网时,路由器会从IP池里“临时借”一个公网IP给它,用完后归还,供其他设备使用。这种方式实现了“多内网设备共享多个公网IP”,比静态NAT更节省资源,但依然需要多个公网IP,对于“家里只有一个公网IP”的场景来说,还是不够用。
动态NAT本质和静态NAT一样,都是仅仅使用IP来区分主机。
家用路由器相当于公网IP池容量为1的场景:
还有可能出现下面这种情况,让本就不充裕的公网IP占有时间进一步减少:
(3)NAPT
NAPT(Network Address and Port Translation,网络地址与端口转换)是NAT的“进阶版”,也是家庭、办公网络的“标配”。它的核心突破是:不仅转换“IP地址”,还会转换“端口号”,从而实现“多个内网设备共享一个公网IP”。
你可能会问:“多个设备用同一个公网IP,外网回复的数据怎么知道该发给谁?”答案就在“端口号”里。
每个网络连接都有一个“端口号”(范围0-65535),比如你用浏览器访问网页用的是80端口(HTTP)或443端口(HTTPS),手机微信发消息也会用一个随机端口。NAPT的工作流程可以拆解为3步,用“小明用电脑上百度”举例:
(1)内网发起请求:小明的电脑(内网IP:192.168.1.100,端口:54321)要访问百度服 务器(公网IP:180.101.49.12,端口:80),请求数据包先发送到家里的路由器。
(2)路由器做“翻译”并记录:路由器收到数据包后,会做两件事:
- 把“内网IP(192.168.1.100)”换成“自己的公网IP(比如220.181.xx.xx)”;
- 把“内网端口(54321)”换成一个随机的“公网端口(比如67890)”;注意:在之前的NAT中,一般是不会记录端口号的,因为他们是用IP进行区分
- 同时在路由器里记录一条“NAT表项”: 内网(192.168.1.100:54321) ↔ 公网(220.181.xx.xx:67890) ,这条记录会暂时保存(比如1-5分钟,没有数据传输就删除)。
(3)外网回复并转发:百度服务器收到请求后,会向“220.181.xx.xx:67890”回复数据。路由器收到回复后,会查刚才记录的“NAT表项”,发现“67890端口”对应小明的电脑(192.168.1.100:54321),就把数据转发给小明的电脑。
通过“IP+端口”的组合,NAPT实现了“多对一”的共享:即使家里10台设备同时上网,路由器只要给每台设备分配不同的“公网端口”,就能通过同一个公网IP区分所有设备的连接,互不干扰。
三、NAPT的双刃剑:安全与局限
NAPT不仅解决了IP短缺问题,还自带“安全buff”,但也有一些无法回避的局限。
(1)自带“防火墙”效果:保护内网安全
由于NAPT只允许“内网主动发起连接”,不允许“外网主动发起连接”,相当于给内网加了一道天然的“门卫”。比如外网有一台陌生设备想访问你家的电脑(192.168.1.100),它只能访问你家路由器的公网IP,但路由器的NAT表项里没有“外网主动连接”的记录,会直接丢弃请求——这就是为什么NAT模式下,外网默认找不到你家的设备,大大降低了被攻击的风险。
当内网主动发起连接后,路由器才会记录该NAPT表项,然后路由器会根据通信的类型(UDP/TCP)以及通信的间隔考虑,要不要移除这个NAPT表项。在没有移除之前,外网可以通过查表访问到该内网进程。一旦长期没有通信,或者内网主动断开,NAPT表项被移除,外网还想通过原来的表项查找就找不到了。
(2)局限:外网无法直接访问内网设备
凡事有利有弊,NAPT的安全特性也带来了局限:如果你想在内网搭建一个服务器(比如个人网站、游戏服务器),让外网的朋友访问,默认是做不到的——因为外网发起的连接会被路由器丢弃。
要解决这个问题,需要手动配置“端口映射”(也叫“端口转发”):在路由器上手动添加一条规则,比如“把公网端口80映射到内网192.168.1.100的80端口”。这样一来,外网设备访问“你的公网IP:80”时,路由器就会按照规则转发到你的服务器,相当于给特定设备“开了一个专属通道”。
手动配置端口映射相当于,在路由器中记录了一个持久的NAPT表项。从而突破了NAPT失活的限制。当外网访问当前路由器的指定Port时,由于有持久的路由器IP+路由器Port<--->内网主机IP+主机Port的映射,所以外网能访问到内网设备。
四、内网穿透
(1)为什么需要内网穿透而不是简单的配置端口映射?
虽然上面我们说使用“手动配置端口映射”能解决外网无法主动访问内网设备的问题。但在实际中往往具有局限性:它需要手动登录路由器管理后台并配置端口转发;然后关闭路由器防火墙;而且路由器永远不能重启(因为路由器的公网IP是运营商通过DHCP动态分配的)。
且不说上述操作的复杂性,安全性就大大降低了,这样一来所有的外网设备都可以通过比如8080这个特定端口访问到内网设备,如果内网设备存在BUG,则及其容易被恶意攻击。
然后对于一些运营商,还会采取特定手段隐藏家庭路由器的公网IP,或者让给一个片区的家庭路由器级联到运营商路由器,所以真正有公网IP的是运营商路由器。它的防护级别更高,你总不能说跑到运营商那里去要求他给你固定绑定一个端口吧!
于是内网穿透技术应运而生。
(2)第三方公网服务器作为中转站
既然NAPT表项在TCP等长连接下固定不变,那么理论上只需要让内网服务器对每一个外网客户端都建立长连接不就好了吗?但是我内网设备作为服务器,一般不可能主动发起连接请求,所以这个是不可行的。
由于NAPT是单向通信的,那么只需要让服务端和一个拥有公网IP的机器建立长久的TCP长连接(服务器到中间服务器的映射路径不会改变)。此时我们就能把这个中间服务器当做原本的内网服务器来看,让其看起来拥有了“公网IP”。
你可以认为路由器做了类似手动配置端口映射的操作,因为在TCP长连接下,表项本身就是持久的。
此后在外网的视角下,它访问的就是一个具有公网IP的服务器。
五、常见的内网穿透成熟方案
常见的内网穿透软件有FRP、Ngrok、花生壳等。在这里我们选择FRP,因为它是一款开源免费软件,用户可以自由使用,不过想要使用它必须得有一台云服务器,刚好我们这里就有一台。
(1)开放云服务器的安全组端口
因为云服务器对于外网访问默认都会有限制,开放对应的端口就是让这个云服务器的端口可以被外网访问到。
登录阿里云控制台,进入 "云服务器 ECS"→"实例"→目标服务器→"安全组"→"配置规则"→"入方向",添加以下端口:
- 服务端监听端口:
7000
(FRP 通信端口) - 穿透服务端口(示例):
3389
(远程桌面)、22
(SSH)、80
(HTTP)、7500
(FRP 仪表盘,可选)
配置时 "授权对象" 填0.0.0.0/0
(允许所有 IP 访问,或限制为指定 IP) - FRP服务器暴露给外网的端口号:8080
添加完成后应该是包含这几个的:
(2)部署FRP服务端到云服务器上
1.下载并解压FRP包
- 打开 FRP 官方 GitHub 发布页面(https://github.com/fatedier/frp/releases),根据云服务器的操作系统(如 Linux 系统选择
frp_版本号_linux_amd64.tar.gz
),下载最新稳定版的 FRP 安装包。- 通过工具(如 Xshell 的文件传输功能、WinSCP 等)将安装包上传到云服务器的合适目录(如
/usr/local/
)。- 进入该目录,执行解压命令(以
frp_0.56.0_linux_amd64.tar.gz
为例):- 解压完成后,将文件夹重命名为
frp
以便后续操作:
2.编辑服务端配置文件
3.启动FRP服务端
./frps -c ./frps.ini
(3)部署FRP客户端到物理机上
因为我们这里物理机是Windows,而虚拟机是在物理机上运行的,通过端口映射让物理机把数据转发给虚拟机的,所以这个FRP服务要部署在Windows上,千万不要错误的放到虚拟机上了,否则一辈子都使用不到FRP客户端。
1.下载 FRP 客户端
- 访问官方下载地址:前往 FRP 的官方 GitHub 发布页面,地址是https://github.com/fatedier/frp/releases 。在这个页面,你可以看到针对不同操作系统和架构的 FRP 安装包。
- 选择合适的安装包:由于我们的物理机是 Windows 系统,找到以
frp_版本号_windows_amd64.zip
格式命名的文件(一般适用于 64 位 Windows 系统,如果是 32 位系统,选择对应的 32 位版本 ,不过现在大部分 Windows 设备都是 64 位),版本号选择最新稳定版本。比如当前最新稳定版本是frp_0.56.0_windows_amd64.zip
,点击文件名进行下载。
在这里我的物理机老是连接不上github,但是我发现可以先用云服务器下载,然后用sz命令传到物理机上。
2.解压 FRP 安装包
下载完成后,得到一个压缩文件(例如frp_0.56.0_windows_amd64.zip
),将它解压到 Windows 物理机上你方便操作的目录,比如D:\frp
。解压方式很简单,右键点击压缩包,选择 “解压到当前文件夹” 或者 “解压到指定文件夹(如 D:\frp)”(如果安装了 WinRAR、360 压缩等解压软件,操作类似)。
3.编辑 FRP 客户端配置文件 frpc.ini
解压完成后,进入解压后的目录(如D:\frp
),找到frpc.toml
文件,这是 FRP 客户端的配置文件,我们需要对它进行编辑以满足内网穿透需求。你可以使用 Windows 系统自带的记事本程序打开它,也可以使用像 Notepad++ (下载地址:https://notepad-plus-plus.org/downloads/ ,功能更强大,对代码格式显示更友好)这样的文本编辑器。
以下是一份配置示例,假设云服务器公网 IP 为120.xxx.xxx.xxx
,云服务器上 FRP 服务端的监听端口为7000
,我们要把物理机本地 8888 端口(已和虚拟机映射)映射到云服务器的 8080 端口供外网访问:
[common]
server_addr = 120.xxx.xxx.xxx # 替换为你实际的云服务器公网IP
server_port = 7000 # 要和云服务器上FRP服务端配置的bind_port一致[physical_machine_8888]
type = tcp
local_ip = 127.0.0.1 # 物理机本地回环地址,用于访问本地映射的8888端口
local_port = 8888 # 物理机上与虚拟机映射的端口
remote_port = 8080 # 云服务器上用于供外网访问物理机8888端口的公网端口
配置项解释
- [common] :这是公共配置段,用于设置客户端连接服务端的通用信息。
- server_addr :指定云服务器的公网 IP 地址,确保填写准确,否则客户端无法连接到服务端。
- server_port :要与云服务器上 FRP 服务端配置文件
frps.ini
中的bind_port
一致,这样客户端才能正确连接到服务端。- [physical_machine_8888] :这是一个自定义的穿透规则段,名字可以自行定义,只要在配置文件中不重复即可。
- type :指定穿透的协议类型,这里是
tcp
,如果是其他协议(如 UDP ),需要相应修改。- local_ip :因为要访问物理机本地映射的端口,所以填写
127.0.0.1
,表示本地回环地址。- local_port :填写物理机上与虚拟机映射的端口,即 8888 端口。
- remote_port :填写云服务器上开放的供外网访问的端口,这里是 8080 端口,要确保云服务器的安全组已经开放该端口。
编辑完成后,保存
frpc.toml
文件。
4.启动FRP客户端
- 以管理员身份打开命令提示符 :在 Windows 搜索栏中输入 “cmd”,右键点击 “命令提示符”,选择 “以管理员身份运行”。
- 进入 FRP 目录:在命令提示符中,使用
cd
命令进入 FRP 解压后的目录,比如cd D:\frp
。- 启动 FRP 客户端:在命令提示符中输入
frpc.exe -c frpc.ini
,然后按下回车键。如果配置正确,命令提示符会显示一些连接相关的信息,同时不会出现报错,这就表示 FRP 客户端已经成功启动并尝试连接云服务器上的 FRP 服务端。
完成以上步骤后,就成功在 Windows 物理机上部署了 FRP 客户端,外网设备就可以通过云服务器公网IP:8080
访问到物理机 8888 端口关联的虚拟机服务了。