网络编程—NAT、代理服务与内网穿透
本文围绕计算机网络中NAT、代理服务器、内网穿透三大技术展开,从底层原理到手动部署,逐步拆解。
一、引言
IPv4协议使用32位地址,理论上最多支持约43亿个IP。
但随着互联网设备爆炸式增长,公网IP地址早已入不敷出。为解决这一问题,业界提出了多种方案,其中最主流、部署最广泛的就是NAT(网络地址转换)。
NAT并非孤立存在——它与代理服务器、内网穿透等技术共同构成了现代网络通信的基础设施层。
本文将依次梳理这些技术的工作机制,并通过frp实战演示内网穿透的完整部署流程。
二、NAT
2.1 背景
NAT是当前解决IP地址不足的主要手段,也是路由器的核心功能之一。
其基本思路是:在局域网内部使用私有IP,在路由器或出口服务器上配置少量全局IP,通过地址转换实现内网与外网的通信。
私有IP的特点:
无需全局唯一,不同局域网中可以出现相同的私有IP
常见私有地址段:10.0.0.0/8、172.16.0.0/12、192.168.0.0/16
无法直接在公网上路由,必须经过NAT转换
学校、家庭等采用这种架构:每个终端分配私有IP,路由器持有一个或多个公网IP。
2.2 地址转换
NAT的核心操作是替换IP首部中的源地址和目标地址。
以上图为例,转换流程如下:
内网主机 10.0.0.10 向外部服务器 163.221.120.9 发送数据包,源IP为 10.0.0.10
NAT路由器收到数据包后,将源地址替换为全局IP 202.244.174.37,再转发到互联网
外部服务器返回数据时,目标IP为 202.244.174.37
NAT路由器收到返回数据,将目标IP替换回 10.0.0.10,转发给内网主机
NAT路由器内部维护一张自动生成的地址转换表,当 10.0.0.10 首次向外部发送数据时,表中就会生成对应的映射关系。
2.3 NAPT
基础NAT存在一个明显问题:如果局域网内多台主机同时访问同一台外部服务器,服务器返回的数据包目标IP都是同一个公网IP,NAT路由器如何判断该转发给哪台内网主机?
答案是NAPT——使用IP + 端口号建立关联关系。
从转换表可以看出:
| 内网地址:端口 | 外部目标 | 转换后地址:端口 |
|---|---|---|
| 10.0.0.10:1025 | 163.221.120.9:80 | 202.244.174.37:1025 |
| 10.0.0.11:1025 | 163.221.120.9:80 | 202.244.174.37:1026 |
两台内网主机即使使用相同的源端口 1025,NAPT也会为它们分配不同的公网端口,从而区分不同的会话。
这张映射表由NAT路由器自动维护:TCP建立连接时生成表项,断开连接后删除表项。
日常所说的"NAT",绝大多数场景实际上指的是NAPT。
2.4 NAT技术的缺陷
NAT虽然解决了地址不足的问题,但也带来了一些限制:
无法从外部主动建立连接:NAT 内部的服务器无法被公网客户端直接访问
转换表开销:NAT 路由器需要维护地址映射表,表项的生成与销毁会消耗额外的计算和内存资源
单点故障风险:通信过程中若 NAT 设备发生故障,即使有热备设备接管,所有已建立的 TCP 连接也会中断
三、代理服务器
代理服务器与NAT在表象上有些相似:客户端向代理发请求,代理转发给真正的服务器,服务器返回结果后代理再回传给客户端。
3.1 正向代理
正向代理位于客户端和目标服务器之间,代表客户端向目标服务器发送请求。
(1)工作流程
客户端将请求发送给正向代理服务器
代理服务器根据配置处理请求
代理将处理后的请求转发给目标服务器
目标服务器返回响应给代理
代理将响应返回给客户端
(2)功能
| 功能 | 说明 |
|---|---|
| 缓存加速 | 缓存常用资源,重复请求直接从缓存返回 |
| 内容过滤 | 屏蔽广告、阻止恶意网站 |
| 访问控制 | 限制特定网站的访问时段或权限 |
| 隐藏身份 | 对外只暴露代理服务器IP,保护客户端隐私 |
| 突破限制 | 借助代理访问受地域限制的资源 |
(3)应用场景
企业网络管理、公共WiFi环境、跨境访问、游戏加速器等
3.2 反向代理
反向代理服务器位于客户端和Web服务器之间,代表服务器接收客户端请求。客户端并不知道实际与哪台后端服务器交互,只知道与反向代理通信。
应用场景:
负载均衡:根据策略将请求分发到多台后端服务器,提升并发处理能力
安全防护:隐藏后端服务器真实IP,降低被直接攻击的风险
缓存加速:缓存后端响应内容,减少后端服务器负载
动静分离:静态资源由反向代理直接返回,动态请求转发给后端
内容重写:添加/删除请求头、URL重写、用户认证等
CDN(内容分发网络)本质上就是反向代理原理的大规模应用。
3.3 NAT与代理服务器的区别
| 对比维度 | NAT | 代理服务器 |
|---|---|---|
| 工作层次 | 网络层,直接替换IP地址 | 应用层,理解并转发应用协议 |
| 解决问题 | IP地址不足 | 更贴近具体应用(加速、安全、控制) |
| 部署位置 | 通常集成在路由器、防火墙等硬件 | 软件程序,部署在服务器上 |
| 使用范围 | 一般在局域网出口部署 | 局域网、广域网、跨网均可 |
| 典型代表 | 家用路由器 | Nginx、Squid、游戏加速器 |
用生活例子来解释:
托在日本工作的表姐去超市买花王尿不湿再寄回来——超市看到的买家是表姐,表姐就是正向代理。
后来找表姐代购的人太多,表姐干脆囤了一批货在家,有人要就直接发——此时表姐充当了反向代理(带缓存功能)。
正向代理侧重请求转发,反向代理常作为缓存和负载均衡入口。
四、内网穿透
4.1 需求
前面提到NAT的缺陷之一是"无法从外部主动建立连接"。
这意味着:家里的电脑、公司的开发服务器,虽然能主动访问外网,但外网设备无法主动访问它们。
内网穿透(又称内网打洞)就是为了解决这个问题——让公网用户能够访问位于NAT后面的内网服务。
(1)原理
在内网主机和一台具有公网IP的服务器之间建立一条持久的TCP连接,外部请求先到达公网服务器,再通过这条隧道转发到内网主机。
(2)过程
步骤1:内网主机上运行frp客户端,将本地SSH的22端口映射到公网服务器frps的8888端口,建立NAT映射
步骤2:外部用户直接访问云服务器的8888端口,流量通过隧道转发到家里Linux机器的22端口
公网服务器起到"中转桥梁"的作用,它必须拥有可被直接访问的公网IP。
4.2 frp
frp是一款开源的内网穿透工具,支持TCP、UDP、HTTP、HTTPS等多种协议。
下面以frp v0.58.1为例,演示完整的部署流程。
4.2.1 下载与安装
远程穿透下载地址_frp下载地址-CSDN博客
注意选择与系统架构匹配的版本,如果GitHub下载速度慢,可以借助Watt Toolkit等工具加速。
下载后解压:
tar -zxvf frp_0.58.1_linux_amd64.tar.gz cd frp_0.58.1_linux_amd64解压后目录中包含两个程序:
frps:frp服务端,部署在公网服务器上
frpc:frp客户端,部署在内网主机上
4.2.2 服务端配置
公网服务器上的配置追求简洁,只需指定监听端口即可。创建frps.toml:
# frps.toml - 公网服务器端配置 bindPort = 8888bindPort是frps监听的端口,用于接收frpc的连接请求。
4.2.3 客户端配置
内网主机上创建 frpc.toml:
# frpc.toml - 内网客户端配置 # 公网服务器上frp服务的IP与端口 serverAddr = "x.x.x.x" # 替换为你的公网服务器IP serverPort = 8888 [[proxies]] name = "ssh-service" # 代理名称,自定义 type = "tcp" # 代理类型 localIP = "127.0.0.1" # 本地服务IP localPort = 22 # 内网服务监听的端口(SSH默认22) remotePort = 8081 # 公网服务器上监听的端口配置含义:公网服务器的 8081 端口会被映射到内网主机的 22 端口。
4.2.4 启动服务
服务端和客户端都可以使用nohup在后台启动:
# 公网服务器启动frps nohup ./frps -c ./frps.toml &> /dev/null & # 内网主机启动frpc nohup ./frpc -c ./frpc.toml &> /dev/null &命令说明:
nohup:忽略挂断信号,使进程在终端关闭后继续运行
&> /dev/null:将标准输出和标准错误都重定向到/dev/null
&:放入后台运行
4.2.5 SSH远程登录测试
在任意一台能上网的机器上,通过公网服务器的8081端口连接内网SSH:
ssh -p 8081 用户名@公网服务器IP如果连接成功,说明内网穿透隧道已正常工作。
4.2.6 Nginx远程访问测试
除了SSH,还可以穿透Web服务。先在内网主机上安装Nginx:
# CentOS安装 sudo yum install nginx # Ubuntu安装 sudo apt install nginx # 启动 nginx # 停止 # nginx -s stopapt安装的Nginx默认首页路径为/var/www/html/,默认首页文件为index.nginx-debian.html。
在frpc.toml中追加一个代理配置:
[[proxies]] name = "nginx-service" type = "tcp" localIP = "127.0.0.1" localPort = 80 remotePort = 8082重启frpc后,在浏览器访问http://公网服务器IP:8082,即可看到内网Nginx的默认页面。