Archived
vault backup: 2026-05-17 22:27:07
This commit is contained in:
@@ -0,0 +1,187 @@
|
||||
---
|
||||
tags: [计算机网络, IPv4, IP首部, TTL, MTU, 分片]
|
||||
create time: 2026-05-17 23:40
|
||||
---
|
||||
|
||||
# IPv4 首部与分段重组
|
||||
|
||||
## 概述
|
||||
|
||||
IPv4 数据包是互联网的基本传输单元。理解其首部结构,有助于排查 MTU 问题、分析抓包工具输出、以及理解 IP 级故障恢复机制。
|
||||
|
||||
## IPv4 首部格式(32-bit fields)
|
||||
|
||||
```
|
||||
Version(4b) │ IHL(4b) │ DSCP/ECN(8b) │ Total Length(16b) │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ Identification(16b) │DF│ MF │Offset(13b)│
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ TTL(8b) │ Protocol(8b) │ Header Checksum │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ Source Address (32b) │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ Destination Address (32b) │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ Options (variable) │
|
||||
│ ...padding... │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 各字段详解
|
||||
|
||||
| 字段 | 大小 | 说明 |
|
||||
|------|------|------|
|
||||
| **Version** | 4 bit | 版本号,IPv4 = `0100` |
|
||||
| **IHL** (Internet Header Length) | 4 bit | 首部长度,单位 4 bytes。**最小值 5**(20 bytes),最大 15(60 bytes) |
|
||||
| **DSCP** (Differentiated Services Code Point) | 6 bit | QoS 优先级标记;前 3 bit 为 ECN(Explicit Congestion Notification)|
|
||||
| **Total Length** | 16 bit | 整个 IP 包总长(含首部),最大 65535 字节 |
|
||||
| **Identification** | 16 bit | 唯一标识符。同一原始包的分片共享此 ID |
|
||||
| **DF** (Don't Fragment) | 1 bit | 置 1 则禁止分片;路由器不能分片的包如果 DF=1,直接丢弃并返回 ICMP "Fragmentation Needed" |
|
||||
| **MF** (More Fragments) | 1 bit | 置 1 表示后面还有分片;最后一个分片 MF=0 |
|
||||
| **Fragment Offset** | 13 bit | 该分片在原始数据中的偏移量(以 8 字节为单位) |
|
||||
| **TTL** (Time To Live) | 8 bit | 生存时间,每经过一个路由器减 1,归零时丢弃并发送 ICMP Timeout |
|
||||
| **Protocol** | 8 bit | 上层协议编号:TCP=6, UDP=17, ICMP=1, IGMP=2 |
|
||||
| **Header Checksum** | 16 bit | 仅校验首部的 CRC,**不校验 payload** |
|
||||
| **Source/Dest Address** | 各 32 bit | 源和目的 IP 地址 |
|
||||
|
||||
### 最小 vs 最大 IP 包
|
||||
|
||||
```
|
||||
最小 IP 包: 20B 首部 + 0B 数据 = 20 bytes
|
||||
最小以太网帧承载: 20B 首部 + 8B ICMP Echo = 28 bytes
|
||||
→ 加上 14B EthHdr + 4B FCS = 46 bytes ≥ MTU 下限 ✅
|
||||
|
||||
最大 IP 包: 20B 首部 + 65515B 数据 = 65535 bytes
|
||||
受限于链路 MTU: 通常 1500B Payload → 最大常用包 1520 bytes
|
||||
```
|
||||
|
||||
## TTL 深度解析
|
||||
|
||||
### TTL 的常见误解
|
||||
|
||||
很多人以为 TTL 的单位是秒。其实在 IPv4 中它是**跳数计数器**——每经过一个路由器(三层转发节点)减 1,不是按时间递减。
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A["Source<br/>TTL=64"] -->|"路由器减1"| B["TTL=63"]
|
||||
B -->|"路由器减1"| C["TTL=62"]
|
||||
C -->|"路由器减1"| D["TTL=61"]
|
||||
D -->|"到目的地"| E["TTL=60<br/>继续处理"]
|
||||
|
||||
style A fill:#DDA0DD,color:#000
|
||||
style E fill:#98FB98,color:#000
|
||||
```
|
||||
|
||||
### 查看 TTL 的实践
|
||||
|
||||
```bash
|
||||
# ping 默认从 64 或 128 开始,减去到达时的 TTL ≈ 经过了跳数
|
||||
$ ping -c 1 example.com
|
||||
PING example.com (93.184.216.34): 56 data bytes
|
||||
64 bytes from ... icmp_seq=0 ttl=55 time=23.1 ms
|
||||
# 64 - 55 = 9 跳
|
||||
|
||||
# Windows 默认 TTL=128
|
||||
$ tracert example.com
|
||||
1 1 ms 1 ms 1 ms 192.168.1.1
|
||||
2 2 ms 2 ms 2 ms 10.0.0.1
|
||||
...
|
||||
9 23 ms 23 ms 23 ms 93.184.216.34
|
||||
```
|
||||
|
||||
### Linux 系统初始 TTL
|
||||
|
||||
```bash
|
||||
$ sysctl net.ipv4.ip_default_ttl
|
||||
net.ipv4.ip_default_ttl = 64
|
||||
|
||||
# macOS / Windows 默认 128
|
||||
# 某些嵌入式设备可能用 32 或 60
|
||||
```
|
||||
|
||||
## MTU 与分片(Fragmentation)
|
||||
|
||||
### 什么是 MTU?
|
||||
|
||||
MTU(Maximum Transmission Unit)是链路层允许的最大 IP 包载荷大小。超出 MTU 的包需要被**分片**。
|
||||
|
||||
| 链路类型 | 典型 MTU | Jumbo Frame |
|
||||
|----------|---------|-------------|
|
||||
| Ethernet | 1500 bytes | 9000 bytes |
|
||||
| Wi-Fi (802.11n/ac/ax) | 1500 | ❌ 不支持 |
|
||||
| PPPoE (宽带拨号) | 1492 (预留 8B PPPoE头) | — |
|
||||
| IPv6 | 1280 (硬性最小) | 可选 |
|
||||
| GRE 隧道 | 1476 (预留 24B GRE头) | — |
|
||||
| VXLAN | 1450 (预留 50B VxLAN头) | — |
|
||||
|
||||
### 分片规则
|
||||
|
||||
当 IP 包 > MTU 且 DF=0 时,路由器将其切分为多个分片:
|
||||
|
||||
```
|
||||
原始 IP 包 (Payload = 3000 bytes) ── MTU=1500 ──→
|
||||
|
||||
分片 1: Headers + [Bytes 0..1479] Offset=0 MF=1
|
||||
分片 2: Headers + [Bytes 1480..2959] Offset=185*8=1480 MF=1
|
||||
分片 3: Headers + [Bytes 2960..2999] Offset=370*8=2960 MF=0 (最后一片)
|
||||
↑ offset × 8 = 实际偏移
|
||||
```
|
||||
|
||||
**关键限制:** 除最后一个分片外,每个分片的 payload 必须是 **8 字节的整数倍**。这就是为什么 offset 字段以 8 字节为单位。
|
||||
|
||||
### 分片的优缺点
|
||||
|
||||
| 优点 | 缺点 |
|
||||
|------|------|
|
||||
| 允许大应用层数据穿越小 MTU 链路 | 增加路由器的 CPU 负担 |
|
||||
| 透明(对应用层无感知) | 任一丢包导致整个原始包失效 |
|
||||
| — | 攻击者可以利用分片做碎片攻击(Teardrop 等) |
|
||||
| — | IPv6 已取消中间路由器分片,改由端到端 PMTUD |
|
||||
|
||||
### PMTUD(Path MTU Discovery)
|
||||
|
||||
现代网络推荐使用 **路径 MTU 发现**而非分片:
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Src as 源主机
|
||||
participant R as 瓶颈路由器(MTU=1400)
|
||||
participant Dst as 目标服务器
|
||||
|
||||
Src->>Dst: IP Packet (size=1500, DF=1)
|
||||
Note over Src: DF(Do Not Fragment)=1
|
||||
R->>R: MTU=1400 < 1500, DF=1 → 无法分片!
|
||||
R->>Src: ICMP Type 3 Code 4 "Fragmentation Needed"
|
||||
Note over Src: Path MTU = 1400 - IP头(20) - Eth(14) = 1366
|
||||
Src->>Dst: IP Packet (size=1366, DF=1) ✅
|
||||
Dst-->>Src: ACK ✅
|
||||
```
|
||||
|
||||
```bash
|
||||
# 检查当前 PMTUD 状态
|
||||
$ ip route show | grep mtu
|
||||
default via 192.168.1.1 dev eth0 mtu 1500
|
||||
|
||||
# Linux 内核 PMTUD 控制
|
||||
$ sysctl net.ipv4.tcp_mtu_probing
|
||||
net.ipv4.tcp_mtu_probing = 0 # 0=关闭, 1=低速率, 2=始终开启
|
||||
```
|
||||
|
||||
## 协议编号对照表
|
||||
|
||||
| Protocol 值 | 名称 | 用途 |
|
||||
|------------|------|------|
|
||||
| 1 | ICMP | 网络诊断(ping、traceroute) |
|
||||
| 2 | IGMP | 组播管理 |
|
||||
| 6 | TCP | 可靠面向连接传输 |
|
||||
| 17 | UDP | 无连接不可靠传输 |
|
||||
| 47 | GRE | 虚拟私有隧道 |
|
||||
| 50 | ESP | IPsec 加密封装安全载荷 |
|
||||
| 51 | AH | IPsec 认证头 |
|
||||
| 89 | OSPF | 动态路由协议 |
|
||||
|
||||
## 关联笔记
|
||||
|
||||
- [[hhs/NETWORK/CIDR与子网划分]] — IP 地址的子网分配方法
|
||||
- [[hhs/NETWORK/NAT原理与应用]] — NAT 如何处理 IP 包的 Checksum
|
||||
- [[hhs/NETWORK/ICMP与Ping-Traceroute]] — ICMP 协议细节
|
||||
@@ -0,0 +1,182 @@
|
||||
---
|
||||
tags: [计算机网络, CIDR, 子网划分, IP计算]
|
||||
create time: 2026-05-18 00:00
|
||||
---
|
||||
|
||||
# CIDR 与子网划分
|
||||
|
||||
## 概述
|
||||
|
||||
CIDR(Classless Inter-Domain Routing,无类别域间路由)是现代 IP 寻址的核心机制。它摒弃了 A/B/C 类地址的固定边界,允许任意长度的前缀——让网络管理员可以按需精确分配 IP 空间。
|
||||
|
||||
> [!QUESTION] 为什么需要子网划分?
|
||||
> 想象一个有 5000 台主机的公司,如果全放在 /12 大网络里:每秒数千个 ARP 广播、巨大的 MAC 表、单点故障影响面极大。子网划分将大问题拆小,既缩小了广播域,又加强了安全性隔离。
|
||||
|
||||
## CIDR 表示法
|
||||
|
||||
```
|
||||
192.168.1.0/24 ← /24 表示前 24 位是网络号
|
||||
```
|
||||
|
||||
即 `192.168.1.0` + 子网掩码 `255.255.255.0`
|
||||
|
||||
### 常见子网对照表
|
||||
|
||||
| CIDR | 子网掩码 | 主机数 ( usable) | 典型用途 |
|
||||
|------|---------|-----------------|---------|
|
||||
| /30 | 255.255.255.252 | 2 | 点对点链路 |
|
||||
| /29 | 255.255.255.248 | 6 | 小型办公室 |
|
||||
| /28 | 255.255.255.240 | 14 | VLAN 极小 |
|
||||
| /27 | 255.255.255.224 | 30 | 小组 VLAN |
|
||||
| /26 | 255.255.255.192 | 62 | 小型部门 |
|
||||
| /25 | 255.255.255.128 | 126 | 中型部门 |
|
||||
| /24 | 255.255.255.0 | 254 | **最常用**,标准办公室 VLAN |
|
||||
| /23 | 255.255.255.254 | 510 | 大型部门 |
|
||||
| /22 | 255.255.255.252 | 1022 | 数据中心租户 |
|
||||
| /21 | 255.255.255.248 | 2046 | 大规模部署 |
|
||||
| /16 | 255.255.255.0 | 65534 | 大型企业内网 |
|
||||
|
||||
> [!tip] 快速计算可用主机数
|
||||
> $N_{usable} = 2^h - 2$,其中 $h$ 是主机位数量($h = 32 - \text{prefix}$)
|
||||
> - `-2` 因为网络地址和广播地址不可用
|
||||
> - 对于 /31(点对点链路),RFC 3021 允许使用 2 个地址(无网络/广播位)
|
||||
|
||||
## 子网划分的核心算法
|
||||
|
||||
### 示例:从 /24 划分为 4 个子网
|
||||
|
||||
原始:`192.168.1.0/24`(254 台主机)
|
||||
目标:分成 4 个子网 → 需借 2 位主机位 → `/26`
|
||||
|
||||
```
|
||||
原始 /24 的网络位:
|
||||
192.168.1.0 = 11000000.10101000.00000001.00000000
|
||||
|
||||
借 2 位给子网:
|
||||
192.168.1.XX = XX 是子网位(00, 01, 10, 11)
|
||||
|
||||
四个子网:
|
||||
Subnet 0: 192.168.1.0/26 — 范围: .0 ~ .63 — 可用: .1 ~ .62 — Bcast: .63
|
||||
Subnet 1: 192.168.1.64/26 — 范围: .64 ~ .127 — 可用: .65 ~ .126 — Bcast: .127
|
||||
Subnet 2: 192.168.1.128/26 — 范围: .128~.191 — 可用: .129~.190 — Bcast: .191
|
||||
Subnet 3: 192.168.1.192/26 — 范围: .192~.255 — 可用: .193~.254 — Bcast: .255
|
||||
```
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
S0["192.168.1.0/26<br/>.1-.62"] -->|"PCs / Servers"| SW0[Switch-A]
|
||||
S1["192.168.1.64/26<br/>.65-.126"] -->|"IP Phones"| SW1[Switch-B]
|
||||
S2["192.168.1.128/26<br/>.129-.190"] -->|"Guest WiFi"| AP1[AP-C]
|
||||
S3["192.168.1.192/26<br/>.193-.254"] -->|"IoT Devices"| GW1[Gateway .1]
|
||||
|
||||
style S0 fill:#DDA0DD,color:#000
|
||||
style S1 fill:#FFD700,color:#000
|
||||
style S2 fill:#98FB98,color:#000
|
||||
style S3 fill:#B0C4DE,color:#000
|
||||
```
|
||||
|
||||
### VLSM(可变长子网掩码)
|
||||
|
||||
不同子网可以用不同长度的掩码——这就是**可变长子掩码**。
|
||||
|
||||
场景:公司有 4 个部门,需要不同规模:
|
||||
- 研发部:200 台 → 需要至少 202 → /24(254 台)
|
||||
- 市场部:50 台 → 需要至少 52 → /26(62 台)
|
||||
- 行政部:10 台 → 需要至少 12 → /28(14 台)
|
||||
- 互联链:2 台 → 需要 2 → /30(2 台)
|
||||
|
||||
总计借用:32 - 24 = 8 位主机位
|
||||
- 研发 /24: 借回 0 位子网位 → 用掉 1 个大块
|
||||
- 剩余给其他 3 个 /26, /28, /30...
|
||||
|
||||
## 实用计算工具
|
||||
|
||||
### Linux ipcalc
|
||||
|
||||
```bash
|
||||
$ ipcalc 192.168.10.50/26
|
||||
Network: 192.168.10.0/26
|
||||
Netmask: 255.255.255.192 = 26
|
||||
Wildcard: 0.0.0.63
|
||||
Broadcast: 192.168.10.63
|
||||
HostMin: 192.168.10.1
|
||||
HostMax: 192.168.10.62
|
||||
Hosts/Net: 62
|
||||
|
||||
# Python 中内置 ipaddress 模块
|
||||
$ python3 -c "import ipaddress; print(list(ipaddress.ip_network('192.168.10.0/26').hosts()))"
|
||||
[IPv4Address('192.168.10.1'), ..., IPv4Address('192.168.10.62')]
|
||||
```
|
||||
|
||||
### 快速手算方法
|
||||
|
||||
| 步骤 | 操作 |
|
||||
|------|------|
|
||||
| 1 | 将最后一个 octet 转换为二进制 |
|
||||
| 2 | 前 prefix%32 位为网络位,其余为主机位 |
|
||||
| 3 | 网络地址 = 全置 0;广播地址 = 全置 1 |
|
||||
| 4 | 可用范围 = 网络地址+1 ~ 广播地址-1 |
|
||||
|
||||
## 私有地址空间(RFC 1918)
|
||||
|
||||
以下地址段在公网不可路由,专供内部网络使用:
|
||||
|
||||
| 地址段 | 数量 | 默认掩码 | 适用场景 |
|
||||
|--------|------|---------|---------|
|
||||
| `10.0.0.0 – 10.255.255.255` | 16,777,216 | /8 | 大型企业、运营商 |
|
||||
| `172.16.0.0 – 172.31.255.255` | 1,048,576 | /12 | 中型企业 |
|
||||
| `192.168.0.0 – 192.168.255.255` | 65,536 | /16 | 家庭/小型办公室 |
|
||||
|
||||
> [!tip] 如何选择私有地址段?
|
||||
> - 单机房、<1000 台主机 → `192.168.0.0/16` 够用
|
||||
> - 多机房、分布式 → `10.0.0.0/8` 留有余量
|
||||
> - Docker 默认使用 `172.17.0.0/16`
|
||||
|
||||
## 超网聚合(Supernetting / CIDR Aggregation)
|
||||
|
||||
将多个连续的小网合并为一个更大的网:
|
||||
|
||||
```
|
||||
原始: 192.168.1.0/24, 192.168.2.0/24, 192.168.3.0/24
|
||||
= 11000000.10101000.00000001.0/24
|
||||
+ 11000000.10101000.00000010.0/24
|
||||
+ 11000000.10101000.00000011.0/24
|
||||
|
||||
共同前缀: 11000000.10101000.000000XX → /22
|
||||
|
||||
聚合后: 192.168.0.0/22 包含 1024 个 IP
|
||||
(注意:实际只用了其中两个 /24 块,浪费了中间两个)
|
||||
```
|
||||
|
||||
路由聚合减少了全球 BGP 路由表的大小。没有 CIDR 聚合,BGP 路由表会膨胀到百万级别。
|
||||
|
||||
## Go 中的子网判断
|
||||
|
||||
```go
|
||||
import "net"
|
||||
|
||||
ip := net.ParseIP("192.168.1.50")
|
||||
_, cidr, _ := net.ParseCIDR("192.168.1.0/26")
|
||||
|
||||
if cidr.Contains(ip) {
|
||||
fmt.Println("IP 在子网范围内 ✅")
|
||||
}
|
||||
|
||||
// 遍历所有可用 IP
|
||||
for ip := cidr.IP.Mask(cidr.Mask); cidr.Contains(ip); inc(ip) {
|
||||
if ip.Equal(cidr.IP) || ip.Equal(lastIP) {
|
||||
continue // 跳过网络地址和广播地址
|
||||
}
|
||||
// 处理每个可用 IP
|
||||
}
|
||||
func inc(ip net.IP) { for i := len(ip) - 1; i >= 0; i-- {
|
||||
ip[i]++
|
||||
if ip[i] > 0 { break }
|
||||
}}
|
||||
```
|
||||
|
||||
## 关联笔记
|
||||
|
||||
- [[hhs/NETWORK/IPv4首部与分段重组]] — IP 地址在 IPv4 包中的位置
|
||||
- [[hhs/NETWORK/IPv6地址与扩展头部]] — IPv6 同样使用 CIDR 表示法
|
||||
- [[hhs/NETWORK/NAT原理与应用]] — NAT 通常映射到私有地址空间
|
||||
@@ -0,0 +1,165 @@
|
||||
---
|
||||
tags: [计算机网络, IPv6, SLAAC, 地址空间]
|
||||
create time: 2026-05-18 00:20
|
||||
---
|
||||
|
||||
# IPv6 地址与扩展头部
|
||||
|
||||
## 概述
|
||||
|
||||
IPv6 是为解决 IPv4 地址枯竭而设计的下一代互联网协议。但它的改进远不止于地址空间——简化首部、内置安全支持、无分片(by design)、自动配置等特性使其更适合现代网络架构。
|
||||
|
||||
## IPv6 地址表示法
|
||||
|
||||
### 十六进制冒号分隔格式
|
||||
|
||||
```
|
||||
2001:0db8:0000:0000:0000:ff00:0042:8329
|
||||
```
|
||||
|
||||
### 缩写规则
|
||||
|
||||
| 规则 | 说明 |
|
||||
|------|------|
|
||||
| 前导零省略 | `0db8` → `db8`;`0042` → `42` |
|
||||
| 连续全零段压缩为 `::` | 只能出现**一次**(否则歧义) |
|
||||
|
||||
示例:
|
||||
```
|
||||
完整: 2001:0db8:0000:0000:0000:ff00:0042:8329
|
||||
缩写: 2001:db8::ff00:42:8329 ← 最简形式
|
||||
|
||||
loopback: 0000:0000:0000:0000:0000:0000:0000:0001
|
||||
::1 ← 仅一个字符
|
||||
|
||||
IPv4映射: 0000:0000:0000:0000:0000:ffff:c0a8:0101
|
||||
::ffff:192.168.1.1 ← 兼容旧系统
|
||||
```
|
||||
|
||||
### 常见 IPv6 地址类型
|
||||
|
||||
| 前缀 | 类型 | 示例 | 范围 |
|
||||
|------|------|------|------|
|
||||
| `2000::/3` | 全球单播 (GUA) | `2001:db8::1` | 公网路由 |
|
||||
| `::1/128` | 环回 (Loopback) | `::1` | 本机 |
|
||||
| `fc00::/7` | ULA (唯一本地地址) | `fd00::1` | 私有地址,等价 RFC1918 |
|
||||
| `fe80::/10` | 链路本地 (Link-Local) | `fe80::1` | 仅同链路可用,自动配置 |
|
||||
| `ff00::/8` | 组播 (Multicast) | `ff02::1` | 多播组 |
|
||||
| — | 未指定地址 | `::` | 类似 IPv4 的 0.0.0.0 |
|
||||
|
||||
## IPv6 地址组成
|
||||
|
||||
### EUI-64(自动生成)
|
||||
|
||||
从 MAC 地址生成接口标识符(正在被隐私扩展取代):
|
||||
|
||||
```
|
||||
MAC: aa:bb:cc:dd:ee:ff
|
||||
插入 ff:fe → aa:bb:cc:ff:fe:dd:ee:ff
|
||||
翻转第七位(UD bit) → ab:bb:cc:ff:fe:dd:ee:ff
|
||||
|
||||
结果: fe80::ab:bb:cc:ff:fe:dd:ee:ff (link-local)
|
||||
```
|
||||
|
||||
### SLAAC( Stateless Address Autoconfiguration )
|
||||
|
||||
主机无需 DHCP 服务器,通过 Router Advertisement(RA)消息自行配置:
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Host as 主机
|
||||
participant R as 路由器
|
||||
|
||||
R->>Host: Router Advertisement (每 200s~60min)
|
||||
Note over Host: RA 中包含:
|
||||
Note over Host: - 前缀 (如 2001:db8:abcd::/64)
|
||||
Note over Host: - prefix length
|
||||
Note over Host: - 默认网关
|
||||
Note over Host: - DNS (RFC 6106 / RDNSS)
|
||||
|
||||
Host->>Host: 自构 IPv6 地址
|
||||
Host->>R: NDP Neighbor Solicitation (查重)
|
||||
R-->>Host: (无冲突 → 无回复)
|
||||
Host->>Host: ✅ 分配 2001:db8:abcd::<interface-id>
|
||||
```
|
||||
|
||||
### DUID-DHCPv6
|
||||
|
||||
DHCPv6 服务器分配地址时需要客户端标识:
|
||||
- **DUID-LLT**: DUID + Link-Layer Time + Link-Layer Address
|
||||
- **DUID-UUID**: DUID + UUID (持久不变)
|
||||
|
||||
## IPv6 首部 vs IPv4 首部
|
||||
|
||||
| 字段 | IPv4 | IPv6 |
|
||||
|------|------|------|
|
||||
| 版本 | 4 bit | 4 bit |
|
||||
| 优先级 | DSCP+ECN (8 bit) | Traffic Class + Flow Label (20 bit) |
|
||||
| 长度 | Total Length (含首部) | Payload Length (**不含**首部) |
|
||||
| Next Header | Protocol (替代) | Next Header (等同) |
|
||||
| Hop Limit | TTL | Hop Limit (改名但不改功能) |
|
||||
| 源/目的 IP | ✅ | ✅ |
|
||||
| 首部 Checksum | ✅ | ❌ **已删除!** |
|
||||
| 分片 | ID/DF/MF/Offset | 移到扩展头(由源端分片) |
|
||||
|
||||
### IPv6 为什么去掉 Checksum?
|
||||
|
||||
- TCP/UDP/ICMPv6 自带端到端校验
|
||||
- 链路层 Ethernet FCS 已做底层校验
|
||||
- 每跳计算 Checksum 增加路由器负担 → 提升转发性能
|
||||
|
||||
### Flow Label(流标签)
|
||||
|
||||
新引入的 20-bit 字段,用于标识属于同一"流"的数据包序列。中间网络设备可据此做 QoS 或负载均衡——无需深度解析载荷。
|
||||
|
||||
## IPv6 扩展头部(Extension Headers)
|
||||
|
||||
IPv6 将可选功能移出固定首部,放在扩展头链中,由 Next Header 字段串联:
|
||||
|
||||
```
|
||||
Fixed Header → Hop-by-Hop Options (可选) → Destination Options → Routing → Fragment → Authentication (AH) → Encapsulating Security Payload (ESP) → Upper Layer (TCP/UDP/ICMPv6)
|
||||
```
|
||||
|
||||
| 扩展头 | 类型值 | 用途 |
|
||||
|--------|-------|------|
|
||||
| Hop-by-Hop Options | 0 | 逐跳选项(极少使用) |
|
||||
| Routing | 43 | 路由类型 0 (SRv6 前身)、Type 2 (Mobile IPv6) |
|
||||
| Fragment | 44 | 分片信息(ID/offset/MF),仅出现在原始包中 |
|
||||
| Authentication (AH) | 51 | IPsec 认证(较少独立使用) |
|
||||
| Encapsulating Security Payload (ESP) | 50 | IPsec 加密封装 |
|
||||
| Destination Options | 60 | 终点选项(MIO 移动 IPv6、Jumbo Payload) |
|
||||
| Mobility Header | 135 | Mobile IPv6 |
|
||||
|
||||
> [!warning] Path MTU Discovery in IPv6
|
||||
> IPv6 规定**路由器不允许对 IP 包分片**。如果包超过链路 MTU,路由器直接丢弃并返回 ICMPv6 "Packet Too Big"。这就是 PMTUD 在 IPv6 中成为强制要求的原因。
|
||||
|
||||
## IPv4 到 IPv6 的过渡机制
|
||||
|
||||
| 技术 | 原理 | 适用场景 |
|
||||
|------|------|---------|
|
||||
| Dual Stack | 同时运行 IPv4 和 IPv6 | 最常见,逐步迁移 |
|
||||
| Tunneling (6in4/6to4) | IPv6 包封装在 IPv4 中传输 | 穿越纯 IPv4 骨干网 |
|
||||
| NAT64/DNS64 | 客户端仅有 IPv6,NAT 翻译到 IPv4 | 运营商级部署 |
|
||||
| SIIT | 状态less 翻译,地址嵌入 (IPv4-mapped) | ISP、企业边界 |
|
||||
|
||||
## Go 中的 IPv6 支持
|
||||
|
||||
```go
|
||||
import "net"
|
||||
|
||||
// 创建双栈监听器(同时支持 v4/v6)
|
||||
ln, err := net.Listen("tcp6", ":8080")
|
||||
// 设置 IPv6Only = false 可同时接受 IPv4 连接 (DualStack)
|
||||
|
||||
// 解析 IPv6 地址
|
||||
ip := net.ParseIP("2001:db8::1") // net.IP 天然支持 v4/v6
|
||||
|
||||
_, cidr, _ := net.ParseCIDR("2001:db8::/32")
|
||||
fmt.Println(cidr.Contains(ip)) // true
|
||||
```
|
||||
|
||||
## 关联笔记
|
||||
|
||||
- [[hhs/NETWORK/IPv4首部与分段重组]] — IPv4 和 IPv6 首部的差异对比
|
||||
- [[hhs/NETWORK/DNS原理与优化]] — AAAA 记录解析 IPv6 地址
|
||||
- [[hhs/NETWORK/CIDR与子网划分]] — CIDR 在 IPv6 中的应用方式相同
|
||||
@@ -0,0 +1,175 @@
|
||||
---
|
||||
tags: [计算机网络, ARP, gratuitous-ARP, ARP欺骗]
|
||||
create time: 2026-05-18 00:40
|
||||
---
|
||||
|
||||
# ARP 协议完整流程
|
||||
|
||||
## 概述
|
||||
|
||||
ARP(Address Resolution Protocol,地址解析协议)负责将 IP 地址解析为同一局域网内的 MAC 地址。它是 IPv4 网络通信中不可或缺的"胶水协议"——每对首次通信的主机之间都必须经过一次 ARP。
|
||||
|
||||
## ARP 报文格式
|
||||
|
||||
ARP 直接封装在 Ethernet 帧中(EtherType = 0x0806),不依赖 IP:
|
||||
|
||||
```
|
||||
┌───────────────────┬───────────────┬────────────────────┐
|
||||
│ Hardware Type │ Protocol Type │ Hardware Addr Len │
|
||||
│ 2 bytes │ 2 bytes │ 1 byte │
|
||||
│ 1 = Ethernet │ 0x0800=IP │ always 6 │
|
||||
├───────────────────┼───────────────┼────────────────────┤
|
||||
│ Protocol Addr Len │ Operation │ Sender MAC │
|
||||
│ 1 byte │ 2 bytes │ 6 bytes │
|
||||
│ always 4 │ 1=Request │ │
|
||||
│ │ 2=Reply │ │
|
||||
├───────────────────┴───────────────┴────────────────────┤
|
||||
│ Sender IP Address (4 bytes) │
|
||||
├────────────────────────────────────────────────────────┤
|
||||
│ Target IP Address (4 bytes) │
|
||||
├────────────────────────────────────────────────────────┤
|
||||
│ Target MAC Address (6 bytes) │
|
||||
│ (in Request, this is zeroed/empty) │
|
||||
└────────────────────────────────────────────────────────┘
|
||||
Total: 28 bytes payload (padded to ≥ 46 bytes by Ethernet)
|
||||
```
|
||||
|
||||
### Operation 字段
|
||||
|
||||
| 值 | 含义 |
|
||||
|----|------|
|
||||
| 1 | **ARP Request** — "谁是 x.x.x.x?请告诉我的 MAC" |
|
||||
| 2 | **ARP Reply** — "我是 x.x.x.x,我的 MAC 是 yy" |
|
||||
| 3 | RARP (Reverse ARP) — 历史遗留,已废弃 |
|
||||
| 8 | InARP (Inverse ARP) — ATM 网络用 |
|
||||
|
||||
## ARP 请求与回复流程
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Src as PC-A<br/>192.168.1.10/aa:bb:cc:dd:ee:01
|
||||
participant Bcast as 广播域内所有主机
|
||||
participant Dst as PC-B<br/>192.168.1.20/?mac
|
||||
|
||||
Note over Src: Application wants to send packet to .20<br/>But needs MAC first!
|
||||
|
||||
Src->>Bcast: ARP Request (Broadcast)<br/>Who has 192.168.1.20? Tell 192.168.1.10
|
||||
Note over Src,Bcast: Src MAC=aa:bb:cc:dd:ee:01<br/>Dst MAC=ff:ff:ff:ff:ff:ff<br/>Target IP=.20, Target MAC=00:00:00:00:00:00
|
||||
|
||||
loop For each host on LAN
|
||||
Bcast-->>Host-C: 收到但不匹配 → 忽略
|
||||
end
|
||||
|
||||
Dst-->>Src: ARP Reply (Unicast)<br/>192.168.1.20 is at aa:bb:cc:dd:ee:20
|
||||
|
||||
Src->>Src: Update ARP Cache: 192.168.1.20 → aa:bb:cc:dd:ee:20
|
||||
```
|
||||
|
||||
### ARP 缓存条目
|
||||
|
||||
```bash
|
||||
$ ip neigh show
|
||||
192.168.1.20 dev eth0 lladdr aa:bb:cc:dd:ee:20 STALE
|
||||
192.168.1.1 dev eth0 lladdr aa:bb:cc:dd:ee:01 REACHABLE
|
||||
fe80::1 dev eth0 lladdr aa:bb:cc:dd:ee:01 DELAY
|
||||
|
||||
# 状态机:
|
||||
# INCOMPLETE — 请求已发但未收到回复
|
||||
# REACHABLE — 确认可达(刚收到回复或收到 ACK)
|
||||
# STALE — 过期但可用,等待下次验证
|
||||
# DELAY — 已标记为 STALE,等待 probe
|
||||
# FAILED — Probe 全部失败
|
||||
```
|
||||
|
||||
### ARP 缓存超时时间
|
||||
|
||||
```bash
|
||||
# Linux 默认超时(秒)
|
||||
$ sysctl net.ipv4.neigh.default.base_reachable_time_ms
|
||||
net.ipv4.neigh.default.base_reachable_time_ms = 30000 # 30s
|
||||
|
||||
# 可调为毫秒精度
|
||||
$ echo 60000 > /proc/sys/net/ipv4/neigh/default/base_reachable_time_ms # 改为 60s
|
||||
```
|
||||
|
||||
## Gratuitous ARP(免费 ARP / 主动 ARP)
|
||||
|
||||
### 什么是 Gratuitous ARP?
|
||||
|
||||
一台主机**主动发送 ARP 回复**,即使没有收到任何请求。这相当于在广播域中宣布:"我现在是 xx:xx:xx:xx:xx:xx,绑定的是 x.x.x.x"。
|
||||
|
||||
### 三种使用场景
|
||||
|
||||
| 场景 | 目的 |
|
||||
|------|------|
|
||||
| 网卡故障切换 (VRRP/Keepalived) | 通知交换机更新 MAC→端口映射 |
|
||||
| IP 冲突检测 | 先发送 GARP,如果有人回应则发现冲突 |
|
||||
| 虚拟机迁移 | 新宿主机的 MAC 替代旧主机的 IP |
|
||||
| DHCP 续租 | 重新声明自己的地址绑定关系 |
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant V1 as VM-on-Host-A<br/>IP: 10.0.0.10<br/>MAC: aa:bb:cc:00:00:01
|
||||
participant SW as Switch
|
||||
participant Migrate as VM migrates to Host-B
|
||||
|
||||
Note over V1: Live Migration starts...
|
||||
V1->>SW: 最后一帧 from Host-A<br/>Switch learns: .10 → Port-X
|
||||
|
||||
Note over Migrate: VM boots on Host-B<br/>Same IP, New MAC!
|
||||
Migrate->>SW: GARP "10.0.0.10 is now cc:dd:ee:00:00:01!"
|
||||
SW->>SW: UPDATE MAC table:<br/>.10 → Port-Y ✅
|
||||
|
||||
Note over V1,Migrate: Without GARP, all traffic would go to old port 😱
|
||||
```
|
||||
|
||||
## ARP 安全与攻击
|
||||
|
||||
### ARP Spoofing / Poisoning
|
||||
|
||||
攻击者发送伪造的 ARP Reply,让受害者认为网关的 MAC 已被篡改:
|
||||
|
||||
```
|
||||
Before:
|
||||
PC: "Gateway is at aa:bb:cc:gg:hh:ii ✅"
|
||||
Server: "I am at dd:ee:ff:jj:kk:ll ✅"
|
||||
|
||||
After Attack (Attacker injects fake ARP):
|
||||
PC: "Gateway is at mm:nn:oo:pp:qq:rr ❌ ← Attacker's MAC!"
|
||||
```
|
||||
|
||||
### 防范措施
|
||||
|
||||
| 措施 | 说明 | 部署位置 |
|
||||
|------|------|---------|
|
||||
| **静态 ARP** | `arp -s` 手动绑定 | 小型网络,管理成本高 |
|
||||
| **Dynamic ARP Inspection (DAI)** | Switch 拦截非合法 DHCP binding 的 ARP | 交换机配置 |
|
||||
| **ARP Watch / Arpmonitor** | 监控 ARP 变动并告警 | 服务端 |
|
||||
| **ndp-scan / arp-scan** | 定期扫描 ARP 表变化 | 运维工具 |
|
||||
|
||||
```bash
|
||||
# 手动添加静态 ARP 条目(重启失效)
|
||||
$ sudo ip neigh add 192.168.1.1 lladdr aa:bb:cc:dd:ee:01 nud permanent dev eth0
|
||||
|
||||
# 永久生效需写入 NetworkManager 或 systemd-networkd 配置
|
||||
```
|
||||
|
||||
## IPv6 中的替代:NDP(Neighbor Discovery Protocol)
|
||||
|
||||
IPv6 废除了 ARP,改用 NDP(ICMPv6 类型 133/134/135/136):
|
||||
|
||||
| ARP 功能 | NDP 实现 | ICMPv6 Type |
|
||||
|----------|---------|-------------|
|
||||
| ARP Request | Neighbor Solicitation (NS) | 135 |
|
||||
| ARP Reply | Neighbor Advertisement (NA) | 136 |
|
||||
| gratuitous ARP | Unsolicited NA | 136 |
|
||||
| 路由发现 | Router Solicitation / Advertisement | 133 / 134 |
|
||||
|
||||
> [!tip] 为什么 NDP 更安全?
|
||||
> NDP 支持 SEND(Secure Neighbor Discovery,RFC 3971),利用加密签名防止伪装。虽然部署不多,但架构上比明文 ARP 好得多。
|
||||
|
||||
## 关联笔记
|
||||
|
||||
- [[hhs/NETWORK/MAC地址与广播域]] — ARP 如何在广播域中工作
|
||||
- [[hhs/NETWORK/Switch与路由器]] — Switch 如何处理 ARP 包
|
||||
- [[hhs/NETWORK/OSI与TCP-IP模型对比]] — ARP 跨越链路层和网络层的边界
|
||||
@@ -0,0 +1,189 @@
|
||||
---
|
||||
tags: [计算机网络, ICMP, Ping, Traceroute]
|
||||
create time: 2026-05-18 00:50
|
||||
---
|
||||
|
||||
# ICMP 与 Ping / Traceroute
|
||||
|
||||
## 概述
|
||||
|
||||
ICMP(Internet Control Message Protocol,互联网控制消息协议)是 IP 的"副手"——它不承载用户数据,而是用来报告错误、传递诊断信息。ping 和 traceroute 这两个最常用的网络工具,底层全靠 ICMP。
|
||||
|
||||
## ICMP 报文格式
|
||||
|
||||
```
|
||||
┌──────────┬───────────┬──────────┬───────────────┐
|
||||
│ Type(8b) │ Code(8b) │ Checksum │ Rest of Header │
|
||||
├──────────┼───────────┴──────────┴───────────────┤
|
||||
│ Data (variable) │
|
||||
└───────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 常用 Type 对照表
|
||||
|
||||
| Type | Code | Name | 用途 |
|
||||
|------|------|------|------|
|
||||
| 0 | 0 | Echo Reply | ping 回复 |
|
||||
| 3 | 0–3 | Destination Unreachable | 目的不可达 |
|
||||
| 3/0 | Network Unreachable | 路由表中无目标网段 |
|
||||
| 3/1 | Host Unreachable | 同一网段但主机不存在 |
|
||||
| 3/2 | Protocol Unreachable | TCP/UDP 端口无监听 |
|
||||
| 3/3 | Port Unreachable | UDP 端口不可达(最常见) |
|
||||
| 8 | 0 | Echo Request | ping 请求 |
|
||||
| 11 | 0 | Time Exceeded | TTL 归零(traceroute 利用此) |
|
||||
| 12 | 0 | Parameter Problem | IP 首部字段错误 |
|
||||
| 13 | 0 | Timestamp Request | 时间戳查询 |
|
||||
| 14 | 0 | Timestamp Reply | — |
|
||||
| 17 | 0 | Address Mask Request | 子网掩码查询(老旧) |
|
||||
| 18 | 0 | Address Mask Reply | — |
|
||||
|
||||
## Ping — 最基础的连通性测试
|
||||
|
||||
### Ping 工作原理
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client as 客户端
|
||||
participant Server as 服务器
|
||||
|
||||
Client->>Server: ICMP Echo Request<br/>Type=8, ID=0x1234, Seq=0
|
||||
Note over Server: 内核自动回复,无需应用层处理
|
||||
Server-->>Client: ICMP Echo Reply<br/>Type=0, ID=0x1234, Seq=0
|
||||
|
||||
loop 继续发第 2, 3... 个包
|
||||
Client->>Server: Echo Request Seq=1
|
||||
Server-->>Client: Echo Reply Seq=1
|
||||
end
|
||||
```
|
||||
|
||||
### Linux ping 详解
|
||||
|
||||
```bash
|
||||
$ ping -c 4 -s 1024 example.com
|
||||
PING example.com (93.184.216.34): 1024 data bytes
|
||||
1032 bytes from 93.184.216.34: icmp_seq=0 ttl=55 time=23.4 ms
|
||||
1032 bytes from 93.184.216.34: icmp_seq=1 ttl=55 time=22.8 ms
|
||||
1032 bytes from 93.184.216.34: icmp_seq=2 ttl=55 time=23.1 ms
|
||||
1032 bytes from 93.184.216.34: icmp_seq=3 ttl=55 time=23.5 ms
|
||||
|
||||
--- example.com ping statistics ---
|
||||
4 packets transmitted, 4 received, 0% packet loss
|
||||
rtt min/avg/max/stddev = 22.8/23.2/23.5/0.30 ms
|
||||
```
|
||||
|
||||
参数速查:
|
||||
| 参数 | 含义 |
|
||||
|------|------|
|
||||
| `-c N` | 发送 N 个包后停止 |
|
||||
| `-i SEC` | 间隔秒数(默认 1s,root 可用 < 0.1s) |
|
||||
| `-s SIZE` | 载荷大小(默认 56 bytes,即 64 byte ICMP 包) |
|
||||
| `-t TTL` | 指定初始 TTL |
|
||||
| `-W MSEC` | 等待超时毫秒数 |
|
||||
| `-q` | 静默模式,仅显示统计摘要 |
|
||||
|
||||
### macOS / Windows 的差异
|
||||
|
||||
| 特性 | Linux | macOS | Windows |
|
||||
|------|-------|-------|---------|
|
||||
| 默认行为 | 不停发送直到 Ctrl+C | 不停发送 | 发 4 次后停止 |
|
||||
| 默认 TTL | 64 | 64 | 128 |
|
||||
| 默认载荷 | 56 bytes | 56 bytes | 32 bytes |
|
||||
| `-c` | ✅ 限制次数 | ❌ | ❌ |
|
||||
|
||||
> [!tip] 判断丢包率的阈值
|
||||
>
|
||||
> | 丢包率 | 评价 |
|
||||
> |--------|------|
|
||||
> | 0% | 正常 |
|
||||
> | < 0.1% | 可接受(偶尔重传) |
|
||||
> | 0.1%~1% | 注意观察 |
|
||||
> | 1%~5% | 可能存在瓶颈或线路老化 |
|
||||
> | > 5% | 严重问题,需排查物理链路或设备 |
|
||||
|
||||
## Traceroute — 路由路径探测
|
||||
|
||||
### 原理:利用 ICMP Time Exceeded
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant T as 客户端
|
||||
participant R1 as Router 1
|
||||
participant R2 as Router 2
|
||||
participant D as Destination
|
||||
|
||||
T->>R1: ICMP(TTL=1) → R1 TTL归零,返回 Time Exceeded
|
||||
Note over T: 收到 R1 的 reply → 第一跳延迟记录完毕
|
||||
|
||||
T->>R1: ICMP(TTL=2) → R1转发 → R2 TTL归零→ Time Exceeded
|
||||
Note over T: 收到 R2 的 reply → 第二跳记录完毕
|
||||
|
||||
T->>R1: ICMP(TTL=3) → ... → D 收到 → 返回 Echo Reply
|
||||
Note over T: ✅ 到达目的地
|
||||
```
|
||||
|
||||
### Linux traceroute vs tracepath
|
||||
|
||||
```bash
|
||||
# traceroute 使用 UDP(默认高位端口)或 ICMP(-I 参数)
|
||||
$ traceroute -I example.com # 使用 ICMP
|
||||
1 192.168.1.1 1ms 1ms 1ms
|
||||
2 10.0.0.1 10ms 10ms 10ms
|
||||
3 202.97.xx.xx 20ms 19ms 20ms
|
||||
...
|
||||
12 93.184.216.34 45ms 44ms 44ms
|
||||
|
||||
# tracepath 不需要 root 权限,默认 MTU 发现
|
||||
$ tracepath example.com
|
||||
1: 192.168.1.1 0.4ms
|
||||
2: 10.0.0.1 8.2ms
|
||||
...
|
||||
12: 93.184.216.34 43.5ms
|
||||
|
||||
No route to above host (mtu discovered: 1492)
|
||||
```
|
||||
|
||||
### Windows 等价命令
|
||||
|
||||
```cmd
|
||||
tracert example.com
|
||||
```
|
||||
|
||||
> [!warning] 为什么有些 traceroute "星号 * * *"?
|
||||
> 路由器可以配置为**不回复 ICMP Time Exceeded**(出于安全考虑)。此时你看不到中间节点,只能看到最后的目的地。
|
||||
|
||||
## ICMP Rate Limiting(限速)
|
||||
|
||||
Linux 内核默认对 ICMP 进行限速,防止 ICMP flood 攻击:
|
||||
|
||||
```bash
|
||||
$ sysctl net.ipv4.icmp_ratelimit # 每秒最多发出多少个 ICMP
|
||||
net.ipv4.icmp_ratelimit = 1000 # 默认 1000 msg/s
|
||||
|
||||
$ sysctl net.ipv4.icmp_ratemask # 哪些 type 受限速
|
||||
net.ipv4.icmp_ratemask = 6168 # mask bits
|
||||
```
|
||||
|
||||
> [!note] iptables 中也可以限速
|
||||
> ```bash
|
||||
> iptables -A INPUT -p icmp --icmp-type echo-request -m limit \
|
||||
> --limit 1/s --limit-burst 4 -j ACCEPT
|
||||
> ```
|
||||
|
||||
## IPv6 等价:ICMPv6
|
||||
|
||||
IPv6 中 ICMP 被增强为 NDP(Neighbor Discovery Protocol),功能更丰富:
|
||||
|
||||
| IPv4 ICMP | IPv6 ICMPv6 对应 |
|
||||
|-----------|-----------------|
|
||||
| Echo Request/Reply | 类型 8/0(不变) |
|
||||
| Destination Unreachable | 类型 1(相同语义) |
|
||||
| Time Exceeded | 类型 3(traceroute 用) |
|
||||
| Router Discovery | Router Solicitation / Advertisement(类型 133/134)|
|
||||
| ARP | Neighbor Solicitation / Advertisement(类型 135/136)|
|
||||
| PMTUD | Path MTU Discovery 成为强制要求 |
|
||||
|
||||
## 关联笔记
|
||||
|
||||
- [[hhs/NETWORK/IPv4首部与分段重组]] — ICMP 作为 IP 上层协议(Protocol=1)
|
||||
- [[hhs/NETWORK/CIDR与子网划分]] — 理解子网后才能正确使用 ping
|
||||
- [[hhs/NETWORK/NAT原理与应用]] — NAT 会影响 ICMP 的回程路径
|
||||
@@ -0,0 +1,166 @@
|
||||
---
|
||||
tags: [计算机网络, 静态路由, 默认网关, 策略路由]
|
||||
create time: 2026-05-18 01:00
|
||||
---
|
||||
|
||||
# 静态路由与默认网关
|
||||
|
||||
## 概述
|
||||
|
||||
路由是数据包从源到目的地所经历的路径选择过程。Linux 内核维护着一张**路由表**,每收到一个包就查表决定下一跳。最基础也是最常用的就是静态路由和默认网关。
|
||||
|
||||
## Linux 路由表结构
|
||||
|
||||
```bash
|
||||
$ ip route show
|
||||
default via 192.168.1.1 dev eth0 proto dhcp src 192.168.1.100 metric 100
|
||||
192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.100 metric 100
|
||||
10.0.0.0/8 via 10.0.0.1 dev eth1 proto static metric 200
|
||||
172.16.0.0/12 dev eth2 scope link
|
||||
```
|
||||
|
||||
### 关键字段含义
|
||||
|
||||
| 字段 | 说明 |
|
||||
|------|------|
|
||||
| `default` | 匹配所有目标(等价于 `0.0.0.0/0`),即**默认网关** |
|
||||
| `via` | 下一跳的 IP 地址 |
|
||||
| `dev` | 出口网卡 |
|
||||
| `proto` | 路由来源:kernel/auto/static/dhcp |
|
||||
| `scope` | 范围:link(直连)/ host(单主机)/ global(全局可路由)|
|
||||
| `metric` | 优先级,值越小越优先 |
|
||||
|
||||
## 最长前缀匹配原则
|
||||
|
||||
当多条路由能匹配目标 IP 时,选择**前缀最长**的那条:
|
||||
|
||||
```
|
||||
目标 IP: 10.0.0.5
|
||||
|
||||
路由表:
|
||||
default via 192.168.1.1 → /0 (0 bits)
|
||||
10.0.0.0/8 via 10.0.0.1 → /8 (8 bits) ✅ 选中!
|
||||
10.0.0.0/24 via 10.0.0.2 → /24 (24 bits) ← 实际上这条更长,应该选它!
|
||||
10.0.0.5/32 via 10.0.0.3 → /32 (32 bits) ← 最佳匹配!
|
||||
|
||||
结论: 最长前缀优先 → 选 /32 那条
|
||||
```
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
S["目标 IP: 10.0.0.5"] --> C{"/32 match?"}
|
||||
C -->|"是"| R3["10.0.0.5/32<br/>via 10.0.0.3 ✅"]
|
||||
C -->|"否"--> C2{"/24 match?"}
|
||||
C2 -->|"是"| R2["10.0.0.0/24<br/>via 10.0.0.2 ✅"]
|
||||
C2 -->|"否"| C8{"/8 match?"}
|
||||
C8 -->|"是"| R1["10.0.0.0/8<br/>via 10.0.0.1 ✅"]
|
||||
C8 -->|"否"| D["default route<br/>via 192.168.1.1 ✅"]
|
||||
|
||||
style R3 fill:#98FB98,color:#000
|
||||
style R2 fill:#DDA0DD
|
||||
style R1 fill:#FFD700
|
||||
style D fill:#B0C4DE
|
||||
```
|
||||
|
||||
## 默认网关
|
||||
|
||||
默认网关是所有未知目的地的兜底路径:
|
||||
|
||||
```bash
|
||||
# 查看当前默认网关
|
||||
$ ip route show default
|
||||
default via 192.168.1.1 dev eth0 proto dhcp
|
||||
|
||||
# 添加默认网关
|
||||
$ ip route add default via 192.168.1.1 dev eth0 metric 100
|
||||
|
||||
# 删除默认网关
|
||||
$ ip route del default via 192.168.1.1
|
||||
|
||||
# 修改默认网关(先删后加)
|
||||
$ ip route replace default via 192.168.1.254 dev eth0 metric 50
|
||||
```
|
||||
|
||||
### 多默认网关(负载均衡与故障转移)
|
||||
|
||||
```bash
|
||||
# ECMP(Equal-Cost Multi-Path)— 同开销的多条路径负载均衡
|
||||
$ ip route add default via 10.0.0.1 dev eth0
|
||||
$ ip route add default via 10.0.1.1 dev eth0
|
||||
|
||||
# 流量会自动在两条链路间负载均衡(基于哈希)
|
||||
$ ip -d route show
|
||||
default nexthop via 10.0.0.1 dev eth0 weight 1
|
||||
nexthop via 10.0.1.1 dev eth0 weight 1
|
||||
```
|
||||
|
||||
## 静态路由配置
|
||||
|
||||
### 基本语法
|
||||
|
||||
```bash
|
||||
# 格式: ip route add <网络>/<掩码> via <下一跳IP> dev <网卡> metric <优先级>
|
||||
$ sudo ip route add 172.16.0.0/12 via 192.168.1.1 dev eth0 metric 100
|
||||
$ sudo ip route add 10.100.0.0/16 via 10.0.0.1 dev eth1 onlink
|
||||
# onlink: 强制使用,即使下一跳不在同一子网
|
||||
```
|
||||
|
||||
### 不同发行版的持久化方式
|
||||
|
||||
| 系统 | 配置文件 | 示例 |
|
||||
|------|---------|------|
|
||||
| Debian/Ubuntu | `/etc/network/interfaces` | `up ip route add ...` |
|
||||
| RHEL/CentOS 7+ | `/etc/sysconfig/network-scripts/route-eth0` | `10.0.0.0/8 via 192.168.1.1` |
|
||||
| Systemd-networkd | `.network` 文件 | `Route:` section |
|
||||
| NetworkManager | `nmcli connection modify` | `ipv4.routes "..."` |
|
||||
| Alpine | `/etc/network/interfaces` | `post-up ip route add ...` |
|
||||
|
||||
### Netplan (Ubuntu 18.04+)
|
||||
|
||||
```yaml
|
||||
# /etc/netplan/01-netcfg.yaml
|
||||
network:
|
||||
version: 2
|
||||
ethernets:
|
||||
eth0:
|
||||
dhcp4: true
|
||||
routes:
|
||||
- to: 10.100.0.0/16
|
||||
via: 192.168.1.1
|
||||
```
|
||||
|
||||
## 策略路由(Policy-Based Routing)
|
||||
|
||||
Linux 支持基于源 IP、端口、协议等条件选择不同路由表:
|
||||
|
||||
```bash
|
||||
# 创建自定义路由表
|
||||
echo "100 web-table" >> /etc/iproute2/rt_tables
|
||||
echo "200 db-table" >> /etc/iproute2/rt_tables
|
||||
|
||||
# 为 web-table 添加路由
|
||||
ip route add 10.0.0.0/8 via 10.0.0.1 dev eth1 table web-table
|
||||
|
||||
# 策略:来自 192.168.10.0/24 的流量走 web-table
|
||||
ip rule add from 192.168.10.0/24 table web-table
|
||||
|
||||
# 效果:即使是同一个目的地,不同源 IP 走不同路径
|
||||
```
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
SrcA["192.168.10.5"] -->|"Source IP match"| Rule["ip rule policy"]
|
||||
SrcB["192.168.20.5"] -->|"Source IP match"| Rule
|
||||
|
||||
Rule -->|"web-table → eth1"| WebRouter["Web Router<br/>10.0.0.1"]
|
||||
Rule -->|"db-table → eth2"| DBRouter["DB Router<br/>10.1.0.1"]
|
||||
|
||||
style WebRouter fill:#DDA0DD,color:#000
|
||||
style DBRouter fill:#98FB98,color:#000
|
||||
```
|
||||
|
||||
## 关联笔记
|
||||
|
||||
- [[hhs/NETWORK/CIDR与子网划分]] — CIDR 前缀长度决定路由表的精确度
|
||||
- [[hhs/NETWORK/NAT原理与应用]] — NAT 常作为默认网关的角色存在
|
||||
- [[hhs/NETWORK/动态路由协议]] — OSPF/BGP 自动生成路由项,无需手动配置
|
||||
@@ -0,0 +1,200 @@
|
||||
---
|
||||
tags: [计算机网络, OSPF, BGP, 动态路由协议]
|
||||
create time: 2026-05-18 01:10
|
||||
---
|
||||
|
||||
# 动态路由协议:OSPF 与 BGP
|
||||
|
||||
## 概述
|
||||
|
||||
在大型网络中手动维护静态路由不现实——网络拓扑变化时每条路由都要手动更新。动态路由协议让路由器自动"学习"彼此的网络,发现链路故障后自动切换路径。核心分类:
|
||||
|
||||
| 类别 | IGP (内部网关协议) | EGP (外部网关协议) |
|
||||
|------|-------------------|-------------------|
|
||||
| 代表协议 | OSPF, IS-IS, RIP | **BGP** |
|
||||
| 使用场景 | 同一个 AS(自治系统)内 | **不同 AS 之间**(即互联网 backbone)|
|
||||
| 算法类型 | 链路状态 (LSA), 距离向量 | 路径向量 |
|
||||
|
||||
## OSPF(Open Shortest Path First)
|
||||
|
||||
### 基本概念
|
||||
|
||||
OSPF 是一种**链路状态**协议,每台路由器收集全网拓扑信息,独立计算最短路径树(SPF)。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
subgraph "AS 内部 — OSPF Area 0"
|
||||
R1["Router A"] --- R2["Router B"]
|
||||
R1 --- R3["Router C"]
|
||||
R2 --- R3
|
||||
R1 --- SW1["Network 192.168.1.0/24"]
|
||||
R2 --- SW2["Network 10.0.0.0/8"]
|
||||
R3 --- R4["Router D"]
|
||||
R4 --- SW3["Network 172.16.0.0/12"]
|
||||
end
|
||||
|
||||
style R1 fill:#DDA0DD,color:#000
|
||||
style R3 fill:#FFD700,color:#000
|
||||
```
|
||||
|
||||
### OSPF 工作流程
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant R1 as Router A
|
||||
participant R2 as Router B
|
||||
participant R3 as Router C
|
||||
|
||||
Note over R1,R3: Step 1: Neighbor Discovery
|
||||
R1->>R2: Hello Packet (multicast 224.0.0.5)
|
||||
R2-->>R1: Hello + DB Description
|
||||
R1->>R2: Adjacency Established ✅
|
||||
|
||||
Note over R1,R3: Step 2: LSA Exchange
|
||||
R1->>R2: LSUpdate (我的直连网络: 192.168.1.0/24, cost=10)
|
||||
R1->>R3: LSUpdate (我的直连网络: 192.168.1.0/24, cost=10)
|
||||
|
||||
Note over R1,R3: Step 3: SPF Calculation
|
||||
R2->>R2: Dijkstra → 最优路径已构建
|
||||
R3->>R3: Dijkstra → 最优路径已构建
|
||||
|
||||
Note over R1,R3: Step 4: Routing Table Updated
|
||||
```
|
||||
|
||||
### OSPF 区域(Area)概念
|
||||
|
||||
OSPF 用"区域"来水平扩展:
|
||||
|
||||
| 区域类型 | 特点 |
|
||||
|----------|------|
|
||||
| **Backbone Area 0** | 所有其他 Area 必须连接到 Area 0 |
|
||||
| Standard Area | 传播全部 LSA,路由表最大 |
|
||||
| Stub Area | 不接受 Type 5 LSA(外部路由),注入一条 default route |
|
||||
| Totally Stubby | Stub + 不接收 Type 3(区域间路由),只有一条默认路由 |
|
||||
| NSSA (Not-So-Stubby Area) | Stub 的变种,允许引入外部路由(Type 7)|
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
R1["ABR: Router A<br/>Area 0 ↔ Area 1"] -->|"全部LSA"| A0["Area 0 (Backbone)"]
|
||||
A0 -->|"全部LSA"| R1
|
||||
R1 -->|"汇总路由 → Stub"| A1["Area 1 (Totally Stubby)<br/>只有默认路由"]
|
||||
|
||||
style R1 fill:#FFD700,color:#000
|
||||
style A0 fill:#DDA0DD,color:#000
|
||||
style A1 fill:#98FB98,color:#000
|
||||
```
|
||||
|
||||
- **ABR** (Area Border Router): 连接多个区域的边界路由器
|
||||
- **ASBR** (AS Boundary Router): 引入外部路由的路由器
|
||||
|
||||
### Cost 计算
|
||||
|
||||
```
|
||||
Cost = Reference_Bandwidth / Interface_Bandwidth
|
||||
|
||||
参考带宽默认值: 100 Mbps (10^8)
|
||||
|
||||
接口实际 Cost:
|
||||
- 10 Mbps Ethernet: 100 / 10 = 10
|
||||
- 100 Mbps Ethernet: 100 / 100 = 1
|
||||
- 1 Gbps Ethernet: 100 / 1000 = 0 → 调为 1
|
||||
- 10 Gbps Ethernet: 100 / 10000 = 0 → 需调整参考带宽
|
||||
```
|
||||
|
||||
> [!warning] 参考带宽问题
|
||||
> 如果参考带宽是 100Mbps,那么 Gigabit (1G) 和 TenGig (10G) 的 cost 都是 1,无法区分优劣。正确做法:
|
||||
> ```bash
|
||||
> router ospf 1
|
||||
> distance ospf 10
|
||||
> auto-cost reference-bandwidth 10000 # 单位 Mbps → 支持到 100G
|
||||
> ```
|
||||
|
||||
### 查看 OSPF 状态
|
||||
|
||||
```bash
|
||||
$ ip route | grep O # 过滤 OSPF learned routes
|
||||
O 10.0.0.0/8 [110/20] via 192.168.1.1, eth0
|
||||
OE1 172.16.0.0/12 [110/130] via 192.168.1.1, eth0
|
||||
|
||||
$ ip -d ospf show # FRR/quagga/Zebra
|
||||
$ netstat -s | grep ospf # OSPF 统计信息
|
||||
|
||||
# Quagga/FRR 中的详细查看
|
||||
$ vtysh
|
||||
show ip ospf neighbor # 邻居关系
|
||||
show ip ospf database # LSA 数据库
|
||||
show ip ospf route # 计算出的 OSPF 路由
|
||||
show ip ospf interface eth0 # 接口 OSPF 状态
|
||||
```
|
||||
|
||||
## BGP(Border Gateway Protocol)
|
||||
|
||||
### BGP vs OSPF 对比
|
||||
|
||||
| 特性 | OSPF | BGP |
|
||||
|------|------|-----|
|
||||
| 范围 | AS 内部 (IGP) | **AS 间 (EGP)** |
|
||||
| 算法 | 链路状态 (Dijkstra) | **路径向量** |
|
||||
| 传输 | IP 协议号 89 | **TCP 179** |
|
||||
| 收敛速度 | 秒级 | 分钟级(设计如此,稳定优先)|
|
||||
| 可扩展性 | ~几千台路由器 | **全球互联网 10 万+ 前缀** |
|
||||
| 策略控制 | 基于 cost | **丰富的 attribute 策略** |
|
||||
|
||||
### BGP 两种会话类型
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
iBGP["iBGP<br/>同一 AS 内的路由器"] -->|"传递可达信息<br/>不改变 next-hop"| R1["AS 65001<br/>Peer A -- Peer B"]
|
||||
|
||||
eBGP["eBGP<br/>不同 AS 间"] -->|"交换路由并修改 next-hop"| R2["AS 65001 -- AS 65002<br/>Peer A -- Peer B"]
|
||||
|
||||
style iBGP fill:#DDA0DD,color:#000
|
||||
style eBGP fill:#98FB98,color:#000
|
||||
```
|
||||
|
||||
### BGP 属性(Attributes)选路顺序
|
||||
|
||||
当多条路径可选时,按以下优先级逐条比较:
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start["新路由到达"] --> Weight["① Cisco专有 Weight<br/>本地有效"]
|
||||
Weight --> LocPrf["② Local Preference<br/>AS 内传递"]
|
||||
LocPrf --> Originate["③ 本地起源 > 接收的路由"]
|
||||
Originate --> AS_Path["④ AS Path 最短"]
|
||||
AS_Path --> ORIGIN["⑤ Origin: IGD < EGP < INCOMPLETE"]
|
||||
ORIGIN --> MED["⑥ MED: 越低越好"]
|
||||
MED --> ebgp["⑦ eBGP > iBGP"]
|
||||
ebgp --> IGP_Cost["⑧ IGP cost to next-hop"]
|
||||
IGP_Cost --> Cluster["⑨ Cluster List 最短"]
|
||||
Cluster --> RouterID["⑩ Router ID 最小"]
|
||||
|
||||
style Start fill:#FFD700,color:#000
|
||||
style LocPrf fill:#DDA0DD,color:#000
|
||||
style AS_Path fill:#98FB98,color:#000
|
||||
```
|
||||
|
||||
### ASN(自治系统编号)
|
||||
|
||||
| 范围 | 说明 |
|
||||
|------|------|
|
||||
| 0–64511 | 私有 ASN(类似 RFC1918 IP 地址)|
|
||||
| 64512–65534 | 16-bit 扩展私有 ASN |
|
||||
| 65535 | 保留 |
|
||||
| 65536–4294967295 | 32-bit 全局 ASN(互联网注册)|
|
||||
|
||||
IANA 分配给各大 ISPs 和大型企业(如 Google: AS15169, Cloudflare: AS13335, Alibaba: AS37963)。
|
||||
|
||||
## RIP(Routing Information Protocol)— 了解即可
|
||||
|
||||
RIP 是最简单的距离向量协议,已基本被淘汰:
|
||||
|
||||
- 跳数上限 15(第 16 跳视为不可达)
|
||||
- 每 30 秒广播整个路由表
|
||||
- `routing protocol name is rip` → 太慢了,现代网络不用
|
||||
|
||||
## 关联笔记
|
||||
|
||||
- [[hhs/NETWORK/静态路由与默认网关]] — 静态路由是动态协议的替代方案
|
||||
- [[hhs/NETWORK/NAT原理与应用]] — NAT 后方的路由器不需要运行 OSPF/BGP
|
||||
- [[hhs/NETWORK/负载均衡]] — Load Balancer 通常依赖 L4/L7 而非完整路由协议
|
||||
@@ -0,0 +1,210 @@
|
||||
---
|
||||
tags: [计算机网络, NAT, SNAT, DNAT, PAT, STUN, TURN]
|
||||
create time: 2026-05-18 01:20
|
||||
---
|
||||
|
||||
# NAT 原理与应用
|
||||
|
||||
## 概述
|
||||
|
||||
NAT(Network Address Translation,网络地址转换)是 IPv4 时代最重要的"续命"技术之一——它让大量私有 IP 主机通过少数几个公网 IP 访问互联网。理解 NAT 的工作原理对于排查连接问题、设计分布式系统和部署 VPN 至关重要。
|
||||
|
||||
> [!QUESTION] NAT 为什么能工作?
|
||||
> NAT 的本质是一个中间人:它在修改经过的数据包的源或目的地址/端口。因为 TCP/IP 协议的端到端原则要求只有通信两端才应看到完整地址,而 NAT 在中间偷偷改了——这破坏了理论模型的"纯洁性",但解决了现实中的地址短缺问题。
|
||||
|
||||
## NAT 分类速览
|
||||
|
||||
| 类型 | 全称 | 方向 | 修改字段 | 用途 |
|
||||
|------|------|------|---------|------|
|
||||
| **SNAT** | Source NAT | 出向 | 源 IP | 内网 → 外网 |
|
||||
| **DNAT** | Destination NAT | 入向 | 目的 IP+Port | 外网 → 内网服务器 |
|
||||
| **PAT** | Port Address Translation | 双向 | 同时改 IP+Port | 多主机共享单公网 IP |
|
||||
| **静态 NAT** | Static NAT | 双向一对一 | 固定映射 | 内网服务器暴露到公网 |
|
||||
|
||||
## SNAT(源地址转换)— 内网上网的钥匙
|
||||
|
||||
### 工作流程
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant PC as 内网主机<br/>192.168.1.100:45678
|
||||
participant NAT as 路由器/NAT网关<br/>eth0: 203.0.113.5<br/>eth1: 192.168.1.1
|
||||
participant Server as 外部 Web 服务器<br/>93.184.216.34:80
|
||||
|
||||
PC->>NAT: SYN src=192.168.1.100:45678 dst=93.184.216.34:80
|
||||
Note over NAT: NAT Table Entry:<br/>192.168.1.100:45678 ↔ 203.0.113.5:50001
|
||||
NAT->>Server: SYN src=203.0.113.5:50001 dst=93.184.216.34:80
|
||||
Server-->>NAT: SYN-ACK dst=203.0.113.5:50001
|
||||
Note over NAT: 反向查找 NAT Table<br/>203.0.113.5:50001 → 192.168.1.100:45678
|
||||
NAT-->>PC: SYN-ACK
|
||||
PC->>NAT: ACK src=192.168.1.100:45678
|
||||
NAT->>Server: ACK src=203.0.113.5:50001
|
||||
|
||||
Note over PC,Server: ← 双方都不知道 NAT 的存在 →
|
||||
```
|
||||
|
||||
### iptables 实现 SNAT
|
||||
|
||||
```bash
|
||||
# 内网接口 eth1, 外网接口 eth0
|
||||
sudo iptables -t nat -A POSTROUTING \
|
||||
-s 192.168.1.0/24 -o eth0 -j MASQUERADE
|
||||
|
||||
# MASQUERADE vs SNAT:
|
||||
# MASQUERADE: 自动获取 eth0 的当前 IP(适合动态 IP,如 DHCP/拨号)
|
||||
# SNAT: 指定固定 IP (适合静态 IP,性能略高)
|
||||
# 等价写法:
|
||||
sudo iptables -t nat -A POSTROUTING \
|
||||
-s 192.168.1.0/24 -o eth0 -j SNAT --to-source 203.0.113.5
|
||||
```
|
||||
|
||||
```bash
|
||||
# 查看 NAT 表条目
|
||||
$ sudo conntrack -L | head -10
|
||||
tcp 6 119 SYN_SENT ... src=192.168.1.100 dst=93.184.216.34
|
||||
src=203.0.113.5 dst=93.184.216.34
|
||||
```
|
||||
|
||||
## DNAT(目的地址转换)— 反向代理
|
||||
|
||||
### 典型场景:将公网 IP 的 80 端口转发到内网 Web 服务器
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client as 外部客户端<br/>x.x.x.x:12345
|
||||
participant FW as 防火墙/NAT<br/>公网: 203.0.113.5:80
|
||||
participant Web as 内网 Web<br/>192.168.1.10:80
|
||||
|
||||
Client->>FW: SYN src=x.x.x.x:12345 dst=203.0.113.5:80
|
||||
Note over FW: PREROUTING 链: DNAT<br/>203.0.113.5:80 → 192.168.1.10:80
|
||||
FW->>Web: SYN src=x.x.x.x:12345 dst=192.168.1.10:80
|
||||
Note over Web: ← 注意: 源IP仍然是客户端真实IP (Full Cone)
|
||||
Web-->>FW: SYN-ACK dst=x.x.x.x:12345
|
||||
FW->>Client: SYN-ACK
|
||||
|
||||
Note over FW,Web: 回程路由需要配置: ip route add x.x.x.x via ...
|
||||
```
|
||||
|
||||
### iptables 实现 DNAT
|
||||
|
||||
```bash
|
||||
sudo iptables -t nat -A PREROUTING \
|
||||
-d 203.0.113.5 -p tcp --dport 80 -j DNAT \
|
||||
--to-destination 192.168.1.10:80
|
||||
|
||||
# 还需允许转发
|
||||
sudo iptables -A FORWARD -p tcp -d 192.168.1.10 --dport 80 -j ACCEPT
|
||||
|
||||
# 如果希望 Web 能看到客户端真实 IP(不启用 SNAT)
|
||||
sudo sysctl net.ipv4.conf.all.accept_local=1
|
||||
```
|
||||
|
||||
### Docker 的端口映射本质就是 DNAT + SNAT
|
||||
|
||||
```bash
|
||||
# docker run -p 8080:80 nginx
|
||||
# = DNAT: host:8080 → container_ip:80
|
||||
# + SNAT: container reply 时把源 IP 改回 host IP
|
||||
|
||||
iptables -t nat -A PREROUTING \
|
||||
-d <host_ip> -p tcp --dport 8080 -j DNAT --to-destination <container_ip>:80
|
||||
```
|
||||
|
||||
## PAT / NAPT(端口级 NAT)— 解决地址枯竭的关键
|
||||
|
||||
### 核心机制
|
||||
|
||||
```
|
||||
内网主机 NAT设备 公网IP:Port池
|
||||
───────── ─────── ─────────────
|
||||
192.168.1.10:45678 ──→ 203.0.113.5:50001 203.0.113.5
|
||||
192.168.1.11:45678 ──→ 203.0.113.5:50002 ← 多个内网IP
|
||||
192.168.1.12:45678 ──→ 203.0.113.5:50003 ← 复用同一个公网IP
|
||||
192.168.1.10:45679 ──→ 203.0.113.5:50004
|
||||
```
|
||||
|
||||
一个公网 IP 最多可提供 **65535 个端口**,理论上支持约 6.5 万并发内网用户。实际受限于内核文件描述符限制(通常 ~6.5 万)。
|
||||
|
||||
## NAT 对 TCP 的影响
|
||||
|
||||
### TIME_WAIT 放大效应
|
||||
|
||||
由于所有内网主机的连接都映射到同一个公网 IP,NAT 设备的 TIME_WAIT 连接数会远超单机。当 NAT 重启时,所有半关闭的连接都会丢失。
|
||||
|
||||
### FTP 的问题
|
||||
|
||||
FTP 使用**独立的控制连接和数据连接**,且在 HTTP body 中嵌入 IP 和端口信息:
|
||||
|
||||
```
|
||||
FTP 控制通道: PORT 192,168,1,100,180,13 ← "数据连接请发到这个IP和端口"
|
||||
```
|
||||
|
||||
NAT 后的内网 IP 对公网不可达!解决方案:
|
||||
|
||||
| 方案 | 说明 |
|
||||
|------|------|
|
||||
| **FTP ALG** | NAT 设备深度解析 FTP 控制流,改写 PORT 命令中的 IP |
|
||||
| **被动模式 PASV** | 服务器提供监听端口,由客户端发起数据连接 |
|
||||
| **SFTP over SSH** | 完全绕过 FTP,用加密隧道传输文件 |
|
||||
|
||||
> [!warning] NAT ALG 的隐患
|
||||
> ALG (Application Layer Gateway) 需要深度解析应用层协议内容,容易出错且增加安全风险。现代实践中更倾向于 SFTP/SCP 替代 FTP。
|
||||
|
||||
## NAT 穿透技术
|
||||
|
||||
### NAT 类型分类
|
||||
|
||||
| 类型 | 行为 | 连通性 |
|
||||
|------|------|--------|
|
||||
| Full Cone | 任何外部地址都能发送 UDP 到你的映射端口 | ⭐⭐⭐⭐⭐ 最佳 |
|
||||
| Restricted Cone | 仅已知 IP 能发 | ⭐⭐⭐⭐ |
|
||||
| Port Restricted Cone | 仅已知 IP+Port 能发 | ⭐⭐⭐⭐ |
|
||||
| Symmetric | 不同目的地获得不同映射端口 | ⭐⭐ 最难穿透 |
|
||||
|
||||
### 常用穿透方案
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
P1["STUN<br/>Session Traversal Utilities for NAT"] -->|"1. 告诉对方我的公网 IP:Port"| P2["TURN<br/>Traversal Using Relays around NAT"]
|
||||
P2 -->|"2. 中继服务器转发电文"| P3["ICE<br/>Interactive Connectivity Establishment"]
|
||||
P3 -->|"3. 尝试直连 → 失败则 fallback 到 TURN"| Final["WebSocket/WebRTC ✅"]
|
||||
|
||||
style P1 fill:#DDA0DD,color:#000
|
||||
style P2 fill:#FFD700,color:#000
|
||||
style P3 fill:#98FB98,color:#000
|
||||
```
|
||||
|
||||
### ICE 流程
|
||||
|
||||
```
|
||||
Step 1: Host Candidate — 本机直接 IP(局域网内直连最快)
|
||||
Step 2: SRFLX Candidate — STUN 探测得到的公网映射地址
|
||||
Step 3: Relay Candidate — TURN 服务器分配的 relay 地址
|
||||
|
||||
排序优先级: Host > SRFLX > Relay
|
||||
尝试顺序: 先试直连,超时后走中继
|
||||
```
|
||||
|
||||
## NAT64 / DNS64
|
||||
|
||||
IPv6 过渡的重要机制:IPv6-only 客户端访问 IPv4-only 服务器
|
||||
|
||||
```
|
||||
客户端 (IPv6): 2001:db8::1
|
||||
DNS64: 将 A 记录 93.184.216.34 → AAAA 记录 ::ffff:93.184.216.34
|
||||
NAT64 网关: 拦截 IPv6 包 → 转换为 IPv4 包 → 发送到 Internet
|
||||
回包: IPv4 → IPv6 转换 → 返回客户端
|
||||
```
|
||||
|
||||
```bash
|
||||
# Linux NAT64 内核模块
|
||||
modprobe nf_nat_ipv6
|
||||
sysctl -w net.ipv6.conf.all.forwarding=1
|
||||
ip6tables -t nat -A POSTROUTING -s fd00::/64 -j SNAT --to-source 2001:db8:64::1
|
||||
```
|
||||
|
||||
## 关联笔记
|
||||
|
||||
- [[hhs/NETWORK/CIDR与子网划分]] — NAT 使用 RFC1918 私有地址空间
|
||||
- [[hhs/NETWORK/TCP状态机详解]] — NAT 影响 TCP 连接生命周期
|
||||
- [[hhs/NETWORK/DNS原理与优化]] — DNS64 将 A 记录转为 AAAA 记录
|
||||
Reference in New Issue
Block a user