第8章 - NAT 与网关
嗨,朋友!
你有没有想过,家里的路由器只有一个公网 IP,但是你的手机、电脑、平板、智能电视都能同时上网,**这是怎么做到的?**答案就是:NAT!
而 网关就像是家里的“大门”,所有进出的数据都要经过它。这一章,我会用最通俗的语言,带你搞懂 NAT 和网关的原理!
🤔 什么是 NAT?
生活中的类比 🏢
想象一下,你住在一个公寓楼:
外面的人给你寄快递:
地址:阳光大道 100 号(公寓地址)
↓
快递到了公寓前台
↓
前台:“这是给 201 室的快递”
↓
送到 201 室(你的房间)
NAT 就是这个“公寓前台”:
- 外面看到的是公寓地址(公网 IP)
- 里面每个房间有自己的房号(私网 IP)
- 前台负责转发(NAT 转换)
定义
NAT(Network Address Translation,网络地址转换)是一种在 IP 数据包通过路由器或防火墙时重新映射 IP 地址的方法。
为什么需要 NAT?
原因1:IPv4 地址不够用 🚫
IPv4 总数:约 43 亿个
全球人口:80 亿
联网设备:更多!
→ 完全不够用!
解决方案:NAT
- 一个公网 IP
- 多个私网 IP
- 节省 IP 地址
原因2:安全隔离 🔒
没有 NAT:
- 你的电脑直接暴露在互联网
- 黑客可以直接攻击你的电脑
有了 NAT:
- 你的电脑在私网内
- 黑客只能看到路由器的 IP
- 多了一层保护
原因3:灵活组网 🌐
你换了 ISP(运营商):
- 公网 IP 变了
- 但家里的私网 IP 不用变
- 设备不用重新配置
🔄 NAT 的工作原理
基本 NAT 转换
外网访问流程
情景:你在家里用电脑访问百度
步骤1:你的电脑发送请求
-------------------------------------
源 IP:192.168.1.100(你的电脑)
源端口:12345
目标 IP:220.181.38.148(百度)
目标端口:80
↓
步骤2:路由器(NAT)转换
-------------------------------------
源 IP:123.45.67.89(你家的公网 IP)
源端口:54321(路由器分配)
目标 IP:220.181.38.148(百度)
目标端口:80
路由器记录:
192.168.1.100:12345 ↔ 123.45.67.89:54321
↓
步骤3:百度响应
-------------------------------------
百度看到的源 IP:123.45.67.89
(不知道你的真实 IP)
↓
步骤4:路由器反向转换
-------------------------------------
目标 IP:123.45.67.89:54321 → 192.168.1.100:12345
↓
步骤5:你的电脑收到响应
NAT 转换表
路由器的 NAT 表:
内部地址: 外部地址: 目标地址:
192.168.1.100:12345 ↔ 123.45.67.89:54321 → 220.181.38.148:80
192.168.1.101:23456 ↔ 123.45.67.89:54322 → 140.82.112.3:443
192.168.1.102:34567 ↔ 123.45.67.89:54323 → 104.16.132.229:443
通过不同的端口号,区分不同的内部设备
📊 NAT 的类型
1. 静态 NAT(Static NAT)
一对一映射:
私网 IP 公网 IP
192.168.1.10 ↔ 123.45.67.10
192.168.1.11 ↔ 123.45.67.11
192.168.1.12 ↔ 123.45.67.12
特点:
- 固定映射
- 需要多个公网 IP
- 适合服务器
2. 动态 NAT(Dynamic NAT)
动态分配:
公网 IP 池:123.45.67.10 - 123.45.67.20
设备 A 上网 → 分配 123.45.67.10
设备 B 上网 → 分配 123.45.67.11
设备 A 下线 → 释放 123.45.67.10
设备 C 上网 → 分配 123.45.67.10
特点:
- 自动分配
- 需要公网 IP 池
- 灵活
3. PAT / NAPT(端口多路复用)
最常用的方式!
多个私网 IP → 1个公网 IP(不同端口)
192.168.1.100:12345 → 123.45.67.89:50001
192.168.1.101:23456 → 123.45.67.89:50002
192.168.1.102:34567 → 123.45.67.89:50003
特点:
- 只需要 1 个公网 IP
- 通过端口号区分
- 家庭路由器使用
🚪 什么是网关?
生活中的类比 🚪
你住在小区里:
小区内部:可以随便走动
要出小区:必须经过大门
↑
这就是“网关”
定义
网关(Gateway)是连接两个不同网络的设备,是局域网通往互联网的“大门”。
网关的作用
1. 路由转发 🛑️
你的电脑:192.168.1.100
网关:192.168.1.1
访问局域网内的设备:
192.168.1.100 → 192.168.1.200
→ 直接通信,不经过网关
访问互联网:
192.168.1.100 → www.baidu.com
→ 必须经过网关 192.168.1.1
2. 协议转换 🔄
连接不同类型的网络:
- 以太网 ↔ WiFi
- IPv4 ↔ IPv6
- 局域网 ↔ 互联网
3. 安全防护 🔒
网关可以:
- 过滤恶意流量
- 防火墙功能
- 访问控制
🏘️ 家庭网络拓扑
典型家庭网络结构
互联网
│
│ (公网 IP: 123.45.67.89)
│
[光猫/路由器]
│ (网关: 192.168.1.1)
│
─────┼─────
│ │ │
电脑 手机 电视
.100 .101 .102
设备信息:
- 电脑:IP 192.168.1.100,网关 192.168.1.1
- 手机:IP 192.168.1.101,网关 192.168.1.1
- 电视:IP 192.168.1.102,网关 192.168.1.1
数据流向
局域网内通信:
电脑 192.168.1.100 → 电视 192.168.1.102
→ 直接通信,速度快
访问互联网:
电脑 192.168.1.100 → 网关 192.168.1.1 → 互联网
↑
NAT 转换
🔧 端口映射(Port Forwarding)
什么是端口映射?
问题:外网无法主动访问内网设备
场景:
- 你在家里搭建了一个网站服务器
- IP:192.168.1.100,端口:8080
- 朋友想从外网访问
解决:端口映射
配置端口映射
路由器配置:
外部端口:80 → 内部 IP:192.168.1.100,端口:8080
外部端口:22 → 内部 IP:192.168.1.100,端口:22
外部端口:3389 → 内部 IP:192.168.1.101,端口:3389
访问方式:
朋友访问:http://123.45.67.89:80
→ 路由器转发到:192.168.1.100:8080
应用场景
1. 远程桌面:
公网IP:3389 → 内网电脑:3389
2. Web 服务器:
公网IP:80 → 内网服务器:8080
3. FTP 服务器:
公网IP:21 → 内网服务器:21
4. 游戏服务器:
公网IP:25565 → 内网服务器:25565
💻 实际应用案例
前端开发
获取网关信息
// 使用 JavaScript 获取客户端 IP
// 注意:这里获取的是经过 NAT 后的公网 IP
fetch('https://api.ipify.org?format=json')
.then(response => response.json())
.then(data => {
console.log('你的公网 IP:', data.ip);
});
// 使用第三方 API 获取详细信息
fetch('https://ipapi.co/json/')
.then(response => response.json())
.then(data => {
console.log('IP 地址:', data.ip);
console.log('城市:', data.city);
console.log('国家:', data.country_name);
console.log('ISP:', data.org);
});
后端开发
Node.js 获取网关和内网 IP
const os = require('os');
// 获取网络接口信息
function getNetworkInfo() {
const interfaces = os.networkInterfaces();
const info = [];
Object.keys(interfaces).forEach(name => {
interfaces[name].forEach(iface => {
if (iface.family === 'IPv4' && !iface.internal) {
info.push({
接口: name,
'IP地址': iface.address,
'子网掩码': iface.netmask,
'MAC地址': iface.mac
});
}
});
});
return info;
}
console.log('网络接口信息:');
console.table(getNetworkInfo());
// Express 获取客户端真实 IP
const express = require('express');
const app = express();
app.get('/ip', (req, res) => {
// 获取真实 IP(考虑代理)
const ip = req.headers['x-forwarded-for'] ||
req.headers['x-real-ip'] ||
req.connection.remoteAddress ||
req.socket.remoteAddress;
res.json({
'客户端IP': ip,
'是否私网IP': isPrivateIP(ip)
});
});
// 判断是否为私网 IP
function isPrivateIP(ip) {
const parts = ip.split('.');
return (
parts[0] === '10' ||
(parts[0] === '172' && parts[1] >= 16 && parts[1] <= 31) ||
(parts[0] === '192' && parts[1] === '168')
);
}
app.listen(3000, () => {
console.log('服务器运行在 3000 端口');
});
运维配置
Linux 查看网关
# 查看默认网关
route -n
# 或
ip route show
# 输出示例:
# default via 192.168.1.1 dev eth0
# ↑
# 这是网关 IP
# 查看详细路由表
netstat -rn
# 输出:
# Destination Gateway Genmask Flags MSS Window irtt Iface
# 0.0.0.0 192.168.1.1 0.0.0.0 UG 0 0 0 eth0
# 192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
设置静态网关
# Ubuntu/Debian - 编辑 /etc/netplan/01-netcfg.yaml
network:
version: 2
ethernets:
eth0:
addresses:
- 192.168.1.100/24
gateway4: 192.168.1.1 # 设置网关
nameservers:
addresses:
- 8.8.8.8
- 8.8.4.4
# 应用配置
sudo netplan apply
# CentOS/RHEL - 编辑 /etc/sysconfig/network-scripts/ifcfg-eth0
BOOTPROTO=static
IPADDR=192.168.1.100
NETMASK=255.255.255.0
GATEWAY=192.168.1.1 # 设置网关
DNS1=8.8.8.8
# 重启网络
sudo systemctl restart network
配置 NAT(Linux 路由器)
# 启用 IP 转发
echo 1 > /proc/sys/net/ipv4/ip_forward
# 永久生效
sudo vim /etc/sysctl.conf
# 添加:net.ipv4.ip_forward=1
sudo sysctl -p
# 配置 iptables NAT
# 假设:
# - 外网接口:eth0
# - 内网接口:eth1
# - 内网网段:192.168.1.0/24
# SNAT - 内网访问外网
sudo iptables -t nat -A POSTROUTING -o eth0 -s 192.168.1.0/24 -j MASQUERADE
# 端口映射 - 外网访问内网服务器
# 外网:80 → 内网 192.168.1.100:8080
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 192.168.1.100:8080
# 保存规则
sudo iptables-save > /etc/iptables/rules.v4
测试工程师
测试网关连通性
# 测试网关是否可达
ping 192.168.1.1
# 跟踪到达目标的路由
traceroute www.baidu.com
# Windows: tracert www.baidu.com
# 输出示例:
# 1 192.168.1.1 1.234 ms (网关)
# 2 10.0.0.1 5.678 ms (ISP)
# 3 220.181.38.148 10.123 ms (目标)
# 查看 NAT 连接
netstat -nat | grep ESTABLISHED
# 测试端口映射
# 外部测试:
telnet 公网IP 80
🔒 NAT 穿透 / 内网穿透
什么是 NAT 穿透?
问题:
- 你在家里搭建了服务器
- 没有公网 IP或无法配置端口映射
- 怎么让外网访问?
解决:NAT 穿透
常见解决方案
1. 花生壳内网穿透
# 安装花生壳
wget https://www.nsloop.com/downloads/frp_client.sh
sudo bash frp_client.sh
# 配置
server_addr = frp.example.com
server_port = 7000
[web]
type = http
local_ip = 127.0.0.1
local_port = 8080
custom_domains = yourdomain.com
# 启动
./frpc -c frpc.ini
2. ngrok
# 使用 ngrok
ngrok http 8080
# 输出:
# Forwarding https://abc123.ngrok.io -> localhost:8080
# ↑
# 外网可访问地址
3. SSH 反向代理
# 在内网机器上执行
ssh -R 8080:localhost:80 user@公网服务器
# 访问公网服务器的 8080 端口
# 就相当于访问内网机器的 80 端口
📝 常见问题
1. 为什么有时候获取不到公网 IP?
原因:
- ISP 分配的是私网 IP
- 多层 NAT(运营商 NAT + 路由器 NAT)
解决:
- 联系 ISP 申请公网 IP
- 使用内网穿透服务
2. 端口映射不生效怎么办?
排查步骤:
1. 检查路由器配置是否正确
2. 检查防火墙是否开放端口
3. 检查服务是否正常运行
4. 使用 telnet 测试端口
3. NAT 类型对游戏和 P2P 的影响?
NAT 类型(从宽松到严格):
1. Full Cone NAT(全锥型)
- 最宽松,P2P 最好
2. Restricted Cone NAT(受限锥型)
- 较宽松
3. Port Restricted Cone NAT(端口受限锥型)
- 一般
4. Symmetric NAT(对称型)
- 最严格,P2P 困难
💡 长安的学习建议
- 理解 NAT 的必要性 - IPv4 地址不够用是根本原因
- 记住网关地址 - 通常是 192.168.1.1 或 192.168.0.1
- 学会配置端口映射 - 这是很实用的技能
- 了解内网穿透 - 很多时候会用到
- 注意安全 - 端口映射会暴露服务,注意防护
📝 小结
这一章我们学习了:
✅ NAT 的作用:节省 IPv4 地址、安全隔离、灵活组网
✅ NAT 工作原理:私网 IP ↔ 公网 IP + 端口转换
✅ NAT 类型:静态 NAT、动态 NAT、PAT/NAPT
✅ 网关的作用:路由转发、协议转换、安全防护
✅ 端口映射:外网访问内网服务的方法
✅ 实际应用:查看网关、配置 NAT、内网穿透
🎯 下一步
恭喜你完成了基础教程的学习!现在你已经掌握了计算机网络的核心知识。
接下来,你可以:
💪 练习题
- 为什么需要 NAT?
- 你家里的路由器的网关 IP 是多少?
- 如何配置端口映射让外网访问家里的服务器?
- 什么是内网穿透?
答案提示
为什么需要 NAT?
- IPv4 地址不够用:全球只有 43 亿个 IPv4 地址,远远不够
- 节省公网 IP:一个公网 IP 可以让多台设备上网
- 安全隔离:内网设备不直接暴露在互联网
- 灵活组网:更换 ISP 时内网不用重新配置
查看网关 IP:
# Windows ipconfig # 查看 "默认网关" # Linux/Mac ip route | grep default # 或 netstat -rn | grep default常见网关 IP:
- 192.168.1.1
- 192.168.0.1
- 10.0.0.1
配置端口映射步骤:
- 登录路由器管理页面(通常是 http://192.168.1.1)
- 找到“端口映射”或“虚拟服务器”设置
- 添加规则:
- 外部端口:80
- 内部 IP:192.168.1.100
- 内部端口:8080
- 协议:TCP
- 保存并重启路由器
- 确保防火墙开放对应端口
什么是内网穿透?
- 定义:在没有公网 IP 或无法配置端口映射的情况下,让外网能够访问内网服务的技术
- 原理:通过中间服务器作为桥梁,建立内网和外网的连接
- 常见工具:
- frp(花生壳)
- ngrok
- ZeroTier
- Tailscale
- 应用场景:
- 家庭服务器对外服务
- 开发环境展示
- 远程桌面访问
