知识点编号:033
难度等级:⭐⭐⭐(掌握)
面试频率:🔥🔥🔥🔥🔥
🎯 一句话总结
NAT就像酒店前台,用一个公网地址代表所有私网设备!🏨
🤔 NAT是什么?
NAT:Network Address Translation
网络地址转换
作用:
✅ 节约公网IP地址
✅ 隐藏内网结构(安全)
✅ 允许私网访问公网
为什么需要NAT?
- IPv4地址不够用(只有43亿个)
- 私网IP不能在公网路由
- 需要让私网设备访问互联网
生活比喻:
酒店前台的工作:
- 客人(私网设备)打电话
- 前台(路由器)用酒店电话(公网IP)拨出
- 对方只看到酒店号码,不知道是哪个房间打的
📊 NAT的类型
1. 静态NAT(Static NAT)
一对一映射
一个私网IP固定对应一个公网IP
示例:
私网IP 公网IP
192.168.1.10 ←→ 203.0.113.10
192.168.1.20 ←→ 203.0.113.20
特点:
✅ 映射固定不变
✅ 可以被外网主动访问
✅ 适用于服务器
❌ 不节约IP地址
应用场景:
- 内网服务器需要对外提供服务
- 需要固定公网IP
2. 动态NAT(Dynamic NAT)
多对多映射
从公网IP池中动态分配
示例:
私网IP池:192.168.1.0/24(254个)
公网IP池:203.0.113.10-203.0.113.20(11个)
过程:
1. 192.168.1.10发起连接 → 分配203.0.113.10
2. 192.168.1.20发起连接 → 分配203.0.113.11
3. 192.168.1.10断开 → 203.0.113.10释放
4. 192.168.1.30发起连接 → 分配203.0.113.10
特点:
✅ 比静态NAT灵活
✅ 节约一些IP
❌ 还是需要多个公网IP
❌ 不能被外网主动访问
应用场景:
- 中小型企业
- 需要多个公网IP但不是所有设备同时上网
3. NAPT(端口复用NAT)/ PAT
NAPT:Network Address Port Translation
也叫PAT(Port Address Translation)
多对一映射 + 端口区分
所有私网IP共享一个公网IP
示例:
内网设备 路由器(NAT) 外网服务器
192.168.1.10:5000 -----→ 203.0.113.1:50001 ----→ 8.8.8.8:53
192.168.1.20:5000 -----→ 203.0.113.1:50002 ----→ 8.8.8.8:53
192.168.1.30:6000 -----→ 203.0.113.1:50003 ----→ 1.1.1.1:80
NAT映射表:
内网地址 外网地址 目标地址
192.168.1.10:5000 203.0.113.1:50001 8.8.8.8:53
192.168.1.20:5000 203.0.113.1:50002 8.8.8.8:53
192.168.1.30:6000 203.0.113.1:50003 1.1.1.1:80
特点:
✅ 最节约IP(只需1个公网IP)
✅ 家用路由器都是这种
✅ 支持成千上万个内网设备
❌ 外网无法主动访问内网(需要端口映射)
应用场景:
- 家庭网络(最常见)
- 小型企业
- 移动网络
🎮 NAPT工作过程
详细流程:
步骤1:内网设备发起连接
内网电脑A(192.168.1.10:5000)访问百度(39.156.66.10:80)
步骤2:数据包到达NAT路由器
源地址:192.168.1.10:5000
目标地址:39.156.66.10:80
步骤3:NAT路由器修改源地址
原始包:
源IP:192.168.1.10
源端口:5000
目标IP:39.156.66.10
目标端口:80
NAT转换后:
源IP:203.0.113.1(公网IP)
源端口:50001(分配的外部端口)
目标IP:39.156.66.10
目标端口:80
步骤4:记录映射表
192.168.1.10:5000 ←→ 203.0.113.1:50001 ←→ 39.156.66.10:80
步骤5:发送到公网
百度服务器收到:
源:203.0.113.1:50001
目标:39.156.66.10:80
步骤6:百度回复
回复包:
源:39.156.66.10:80
目标:203.0.113.1:50001
步骤7:NAT路由器查表
查到:203.0.113.1:50001 ←→ 192.168.1.10:5000
步骤8:修改目标地址
转换后:
源:39.156.66.10:80
目标:192.168.1.10:5000
步骤9:转发给内网设备
电脑A收到回复!
🔧 端口映射(Port Forwarding)
问题:
外网无法主动访问内网设备
(因为外网不知道内网IP)
解决:
配置端口映射(静态映射)
示例:
内网有Web服务器:192.168.1.100:80
公网IP:203.0.113.1
配置:
外部端口8080 → 192.168.1.100:80
效果:
访问 203.0.113.1:8080 → 自动转到 192.168.1.100:80
NAT表:
外部地址 内部地址
203.0.113.1:8080 → 192.168.1.100:80
203.0.113.1:3389 → 192.168.1.101:3389(远程桌面)
203.0.113.1:22 → 192.168.1.102:22(SSH)
💻 Java代码示例
import java.net.*;
import java.io.*;
public class NATExample {
/**
* 获取私网IP
*/
public static String getPrivateIP() {
try {
InetAddress ip = InetAddress.getLocalHost();
return ip.getHostAddress();
} catch (Exception e) {
return "未知";
}
}
/**
* 获取公网IP(通过外部服务)
*/
public static String getPublicIP() {
try {
// 方法1:通过外部服务获取
URL url = new URL("https://api.ipify.org");
BufferedReader reader = new BufferedReader(
new InputStreamReader(url.openStream())
);
String publicIP = reader.readLine();
reader.close();
return publicIP;
} catch (Exception e) {
return "获取失败: " + e.getMessage();
}
}
/**
* 判断是否是私网IP
*/
public static boolean isPrivateIP(String ip) {
String[] parts = ip.split("\\.");
if (parts.length != 4) {
return false;
}
int first = Integer.parseInt(parts[0]);
int second = Integer.parseInt(parts[1]);
// 10.0.0.0/8
if (first == 10) {
return true;
}
// 172.16.0.0/12
if (first == 172 && second >= 16 && second <= 31) {
return true;
}
// 192.168.0.0/16
if (first == 192 && second == 168) {
return true;
}
return false;
}
/**
* 检测NAT类型(简化版)
*/
public static String detectNATType() {
String privateIP = getPrivateIP();
String publicIP = getPublicIP();
if (isPrivateIP(privateIP)) {
if (!publicIP.equals("获取失败")) {
return "NAPT/PAT(使用NAT)";
} else {
return "无公网访问";
}
} else {
return "公网IP(无NAT)";
}
}
/**
* 显示网络信息
*/
public static void showNetworkInfo() {
System.out.println("=== 网络信息 ===\n");
// 私网IP
String privateIP = getPrivateIP();
System.out.println("私网IP: " + privateIP);
System.out.println("是否私网: " + isPrivateIP(privateIP));
System.out.println();
// 公网IP
System.out.println("正在获取公网IP...");
String publicIP = getPublicIP();
System.out.println("公网IP: " + publicIP);
System.out.println();
// NAT类型
System.out.println("NAT类型: " + detectNATType());
System.out.println();
// 所有网络接口
try {
System.out.println("=== 所有网络接口 ===\n");
for (NetworkInterface ni :
Collections.list(NetworkInterface.getNetworkInterfaces())) {
if (!ni.isUp()) continue;
System.out.println("接口: " + ni.getName());
System.out.println(" 显示名: " + ni.getDisplayName());
for (InetAddress addr :
Collections.list(ni.getInetAddresses())) {
if (addr instanceof Inet4Address) {
String ip = addr.getHostAddress();
System.out.println(" IPv4: " + ip +
" (私网: " + isPrivateIP(ip) + ")");
}
}
System.out.println();
}
} catch (Exception e) {
System.err.println("获取接口失败: " + e.getMessage());
}
}
/**
* 测试端口映射
*/
public static void testPortMapping(String host, int port) {
System.out.println("=== 测试端口映射 ===\n");
System.out.println("目标: " + host + ":" + port);
try (Socket socket = new Socket()) {
socket.connect(new InetSocketAddress(host, port), 3000);
System.out.println("✓ 端口开放");
System.out.println(" 本地地址: " +
socket.getLocalAddress().getHostAddress() +
":" + socket.getLocalPort());
System.out.println(" 远程地址: " +
socket.getInetAddress().getHostAddress() +
":" + socket.getPort());
} catch (SocketTimeoutException e) {
System.out.println("✗ 连接超时(端口可能关闭或被防火墙阻止)");
} catch (ConnectException e) {
System.out.println("✗ 连接被拒绝(端口未开放)");
} catch (Exception e) {
System.out.println("✗ 错误: " + e.getMessage());
}
}
public static void main(String[] args) {
// 显示网络信息
showNetworkInfo();
// 测试公网连接
System.out.println("\n=== 测试公网连接 ===\n");
testPortMapping("www.baidu.com", 80);
// 测试本地端口(如果有服务)
// testPortMapping("localhost", 8080);
}
}
⚠️ NAT的问题
1. 无法被外网主动访问
问题:
外网主机不知道内网IP
无法主动发起连接
影响:
- P2P应用困难(如视频通话)
- 托管服务器需要端口映射
- 一些在线游戏无法联机
解决:
- 端口映射(Port Forwarding)
- UPnP(自动端口映射)
- NAT穿透技术(STUN/TURN)
- DMZ主机(将一台内网主机完全暴露)
2. 端口耗尽
问题:
一个公网IP只有65535个端口
大量内网设备同时上网可能耗尽端口
示例:
1000台设备,每台100个连接
总共需要100,000个端口 > 65535
解决:
- 使用多个公网IP
- 连接复用
- 限制每个设备的连接数
3. 性能开销
问题:
NAT路由器需要:
- 维护映射表
- 修改每个数据包
- 重新计算校验和
影响:
- 增加延迟(通常<1ms)
- 消耗CPU和内存
- 高并发时性能下降
解决:
- 使用硬件NAT(专用芯片)
- 优化NAT表大小
- 及时清理过期连接
🐛 常见面试题
Q1:NAT的工作原理是什么?
答案:
NAT(网络地址转换)允许私网设备使用公网IP访问互联网。
工作原理(以NAPT为例):
出站(内网→公网):
1. 内网设备发送数据包
源:192.168.1.10:5000
目标:8.8.8.8:53
2. 到达NAT路由器
- 分配外部端口:50001
- 记录映射:192.168.1.10:5000 ←→ 公网IP:50001
- 修改源地址为:公网IP:50001
3. 发送到公网
源:公网IP:50001
目标:8.8.8.8:53
入站(公网→内网):
1. 公网回复
源:8.8.8.8:53
目标:公网IP:50001
2. NAT路由器查表
- 找到映射:50001 ←→ 192.168.1.10:5000
- 修改目标地址为:192.168.1.10:5000
3. 转发给内网设备
关键点:
- 修改IP地址和端口
- 维护映射表
- 重新计算校验和
- 出站时记录,入站时查表
Q2:NAT有哪些类型?各有什么特点?
答案:
NAT的3种类型:
1. 静态NAT(Static NAT)
- 一对一映射
- 私网IP ←→ 公网IP固定
- 不节约IP,但可被外网访问
- 用途:对外提供服务的服务器
2. 动态NAT(Dynamic NAT)
- 多对多映射
- 从公网IP池动态分配
- 节约部分IP
- 用途:中小型企业
3. NAPT/PAT(端口复用NAT)
- 多对一映射
- 所有内网设备共享1个公网IP
- 通过端口区分不同连接
- 最节约IP
- 用途:家庭、小企业(最常用)
比较:
静态NAT 动态NAT NAPT/PAT
映射关系 一对一 多对多 多对一
节约IP 不节约 部分节约 最节约
外网访问 可以 不可以 不可以
应用场景 服务器 企业 家庭/小企业
家用路由器都是NAPT!
🎓 总结
NAT的关键点:
- 作用:节约公网IP,私网访问公网
- 类型:静态、动态、NAPT
- 原理:修改地址+端口,维护映射表
- 问题:无法被动访问、端口耗尽
记忆口诀:
私网共享公网IP 🌐
修改地址加端口 🔄
出站记录映射表 📝
入站查表转发 📤
文档创建时间:2025-10-31