浅谈NAT与代理
NAT原理
最近在做一个关于NAT
的需求,之前对于NAT
只是有个大概的了解,对于一些细节还不够清楚,正好学习一下。
NAT简介
静态 NAT(Static NAT)
- 一对一映射:一个私有 IP 地址固定映射到一个公网 IP 地址。
- 适用于需要从外部访问内部服务器的情况,例如 Web 服务器或邮件服务器。
动态 NAT(Dynamic NAT)
- 多个私有 IP 地址动态映射到一个或多个公网 IP 地址,但每个私有 IP 只能临时获得一个公网 IP。
- 适用于公网 IP 资源有限的情况,但不支持多个私有 IP 同时共享同一个公网 IP 进行外部通信。
端口地址转换(PAT,Port Address Translation,NAPT)
- 也称为 “多对一 NAT” 或 “NAT Overload”,是最常见的 NAT 类型。
- 通过修改 TCP/UDP 端口号,使多个私有 IP 地址共享一个公网 IP 地址访问互联网。
- 典型应用:家庭路由器(路由器使用一个公网 IP,所有内网设备通过该 IP 访问互联网)。
NAT实现
单纯从数据包角度,现在一个请求到达服务器G(网关),但是实际提供服务的是另外的内网服务器S,现在就要进行转发了。对于数据包,现在的请求源IP是客户端1.1.1.1
,请求目的IP是G的IP8.8.8.8
,现在进行NAT转换,G根据自己的NAT规则,重新构造数据包,将数据包的源IP改成自己的IP,也就是8.8.8.8
,对于目的IP改成实际服务器S的IP,比如是2.2.2.2
,现在请求数据包就能成功到达提供服务的S。这其中就包含了NAT了。
但是上面说的是从服务器的角度考虑的,在现在的大内网环境了,内网客户端也会在出口网络进行NAT
,原理也差不多吧。
配置NAT
对于Linux
服务器来说,通过iptables
就能配置简单的NAT
规则了
1 | # SNAT规则,指定1.1.1.1为出站IP |
端口策略
SNAT 端口转换
阶段 | 源 IP:端口 | 目标 IP:端口 | NAT 处理 |
---|---|---|---|
内网请求 | 192.168.1.100:1001 |
8.8.8.8:8080 |
客户端发出请求 |
经过 NAT | 203.0.113.1:1001 (如果可用) 或 203.0.113.1:56789 |
8.8.8.8:8080 |
可能修改端口 |
服务器响应 | 8.8.8.8:8080 |
203.0.113.1:1001 或 203.0.113.1:56789 |
服务器回复 |
NAT 还原 | 192.168.1.100:1001 |
8.8.8.8:8080 |
NAT 设备转换回去 |
- 尝试保持源端口(如
1001
)。 - 如果端口冲突(如多个设备同时使用
1001
),则 分配新的端口(如56789
)。 - NAT 设备建立映射表,确保外部服务器的返回流量能正确转换回去。
DNAT 端口转换
外部请求 | NAT 设备修改 | 内网服务器看到 |
---|---|---|
8.8.8.8:34567 → 203.0.113.1:8080 |
8.8.8.8:34567 → 192.168.1.100:80 |
8.8.8.8:34567 → 192.168.1.100:80 |
- 如果外部端口与内网端口相同(如
8080 → 8080
),则 不修改端口。 - 如果端口不同(如
8080 → 80
),则 修改目标端口。 - NAT 设备建立映射表,确保内网服务器返回数据时,NAT 设备能转换回原始端口。
端口耗尽
有个场景,存在大量内网设备,但是出口只有一个公网IP,在并发的场景下自然会出现端口耗尽的问题:
NAT 设备在 SNAT(源地址转换) 时,需要为每个内部连接分配一个唯一的 (公网 IP, 端口号)
,但是:
- 每个公网 IP 只有 64511 个可用端口(
1024-65535
)。 - 高并发连接可能很快耗尽端口资源,导致新连接失败。
示例
内部 IP | NAT 设备 | 目标服务器 | 端口映射 |
---|---|---|---|
192.168.1.100:5000 | 171.1.1.1:20000 | 8.8.8.8:443 | ✅ |
192.168.1.101:5001 | 171.1.1.1:20001 | 8.8.8.8:443 | ✅ |
192.168.1.102:5002 | 171.1.1.1:20002 | 8.8.8.8:443 | ✅ |
… | … | … | … |
192.168.1.5000:6000 | 171.1.1.1:65535 | 8.8.8.8:443 | ❌ 端口耗尽! |
解决方案
- 使用多个公网 IP(SNAT 轮换 IP) ✅ (最有效)
- 优化 NAT 超时,回收端口更快
- 限制单个 IP 的 NAT 连接数
- 使用代理(HTTP / SOCKS)减少 NAT 连接
- 考虑 CGNAT(运营商级 NAT)
NAT与代理
NAT看着看着感觉似曾相识啊,SNAT
与正向代理,DNAT
与反向代理,感觉很多点都是相似的啊。
稍微了解一下,他们之间还是有很大区别的,总结来说是几点:
NAT
工作在三层,代理工作在七层NAT
是转发流量,不建立实际连接,代理会建立请求实际连接
功能 | NAT | 代理 |
---|---|---|
请求发起 | 不发起实际的请求,只是修改数据包的地址。 | 代理服务器发起实际的请求,作为客户端或服务器与目标建立连接。 |
连接建立 | 不会建立新的连接,只是修改地址并转发数据包。 | 代理服务器与目标服务器建立连接,处理请求并转发响应。 |
应用层交互 | 不涉及应用层的协议处理。 | 代理可以在应用层进行修改,例如缓存、负载均衡、加密解密等。 |
透明性 | 对外部设备透明,仅在数据包层进行地址修改。 | 代理处理所有的请求和响应,客户端和目标服务器都通过代理进行交互。 |
举个最明显的例子,Nginx
负载的时候,可以配置负载策略,比如根据路径进行转发,这就是明显的七层,同时对于数据数据,Http
代理的时候通常会加上X-Forwarded-For: clint IP
这样的请求头,这就更是七层的内容了。
本部落格所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 你所不知道的物語;!
評論