EP02:Source IP 能证明发送者身份吗?
在上一篇中,我们明确了 IP 协议的一个重要职责边界:
IP 地址用于寻址和转发,但不能单独证明通信身份。
数据包中的 Source IP,本质上只是 IP Header 中的一个字段。
当 Bob 收到:
Source IP = 192.168.106.130
它只能说明:
这个数据包声称自己来自
192.168.106.130。
但仅凭这个字段,Bob 无法证明真正发送数据包的一定就是 Alice。
这个结论能不能通过实验直接看到?
本实验准备三台主机:
Alice:192.168.106.130
Kali :192.168.106.131
Bob :192.168.106.132
我们先让真正的 Alice 向 Bob 发送一份 UDP 数据。
然后再让 Kali 构造另一份 UDP 数据包,但故意把 IP Header 中的 Source IP 写成:
192.168.106.130
也就是 Alice 的地址。
最后站在 Bob 的视角观察这两份数据包。
本实验只回答一个问题:
Bob 看到 Source IP = 192.168.106.130,能不能证明发送者一定是 Alice?
一、实验目标
整个实验只有两个阶段。
第一阶段:
Alice
192.168.106.130
│
│ 正常发送
▼
Bob
192.168.106.132
Source IP = 192.168.106.130
第二阶段:
Kali
192.168.106.131
│
│ 人为构造
▼
Bob
192.168.106.132
Source IP = 192.168.106.130
也就是说:
真实发送者不同
Alice
vs
Kali
但:
Source IP 相同
192.168.106.130
最终验证:
Source IP 表示数据包“声称从哪里来”,并不是经过身份认证之后得到的身份信息。
二、实验环境
继续复用整个 IPSec 专题使用的 VMware 实验环境。
| 角色 | 操作系统 | 实验 IP | 作用 |
|---|---|---|---|
| Alice | Rocky Linux | 192.168.106.130 | 正常发送数据 |
| Kali / Eve | Kali Linux | 192.168.106.131 | 构造伪造 Source IP |
| Bob | Rocky Linux | 192.168.106.132 | 抓包观察 |
| 宿主机 | Windows 11 | — | VMware Workstation |
实验仍然遵循一个原则:
在能够清楚展示机制的前提下,尽量减少资源占用。
三台虚拟机不需要复杂的图形环境。
推荐资源:
CPU:1~2 vCPU
内存:1.5~2 GB
三、实验网络设计
为了既保留虚拟机互联网访问,又建立独立实验网络,三台虚拟机都使用双网卡。
网卡 1
NAT
用于访问互联网、安装软件
网卡 2
VMnet2
用于 IPSec 系列实验
实验网段:
192.168.106.0/24
形成:
VMnet2
192.168.106.0/24
Alice Kali Bob
.130 .131 .132
│ │ │
└──────────────┼─────────────┘
实验网卡不需要配置默认网关。
因为三台主机处于同一个网段,可以直接进行二层通信。
四、确认实验网卡
不要直接假设实验接口叫:
eth1
不同 Linux 系统的接口名称可能不同。
例如 Rocky Linux 可能是:
ens160
ens192
ens37
Kali 可能是:
eth0
eth1
因此首先执行:
ip -br addr
更推荐使用:
ip route get <目标IP>
确认系统真正使用哪块接口。
例如 Alice:
ip route get 192.168.106.132
可能得到:
192.168.106.132 dev ens37 src 192.168.106.130
说明:
实验接口 = ens37
Kali:
ip route get 192.168.106.132
例如:
192.168.106.132 dev eth1 src 192.168.106.131
说明:
实验接口 = eth1
后面的 Scapy 和 tcpdump 都应该使用真正的实验接口。
五、配置实验 IP
如果前面的实验已经配置过这些地址,可以直接跳过本节。
假设:
Alice:ens37
Kali :eth1
Bob :ens37
Alice
sudo ip link set ens37 up
sudo ip addr add 192.168.106.130/24 dev ens37
确认:
ip -br addr show ens37
Kali
sudo ip link set eth1 up
sudo ip addr add 192.168.106.131/24 dev eth1
确认:
ip -br addr show eth1
Bob
sudo ip link set ens37 up
sudo ip addr add 192.168.106.132/24 dev ens37
确认:
ip -br addr show ens37
需要注意:
ip addr add配置的是临时地址,系统重启后会消失。
对于一次实验已经足够。
如果整个 IPSec 专题长期复用这套网络,再使用 NetworkManager 将地址永久保存即可。
六、验证网络可达
Alice:
ping -c 3 192.168.106.132
Kali:
ping -c 3 192.168.106.132
Bob:
ping -c 3 192.168.106.130
ping -c 3 192.168.106.131
确认:
Alice ↔ Bob
Kali ↔ Bob
都能够正常通信。
但注意:
到这里我们证明的仍然只是“网络可达”。
这并没有证明任何通信身份。
七、记录 Alice 和 Kali 的 MAC 地址
本实验还需要观察一个辅助字段:
Ethernet Source MAC
目的并不是把 MAC 当作可靠身份认证手段。
而是在当前这个同一二层网络的受控实验环境中,用它帮助区分:
数据帧实际由 Alice 的网卡发出,还是由 Kali 的网卡发出。
Alice:
ip link show <Alice实验接口>
例如:
link/ether 00:0c:29:aa:aa:aa
记录:
Alice MAC = 00:0c:29:aa:aa:aa
Kali:
ip link show <Kali实验接口>
例如:
Kali MAC = 00:0c:29:bb:bb:bb
实际地址以自己的实验环境为准。
八、准备实验工具
Bob 需要使用 tcpdump。
Rocky Linux:
sudo dnf install -y tcpdump
确认:
tcpdump --version
Alice 需要 Python 3:
python3 --version
如果没有:
sudo dnf install -y python3
Kali 使用 Scapy:
python3 -c "import scapy; print(scapy.__version__)"
如果没有安装:
sudo apt update
sudo apt install -y python3-scapy
这里使用 Scapy 的原因非常简单:
Scapy 允许我们自己构造 IP Header。
本实验最重要的就是人为指定:
IP(src="192.168.106.130")
九、Bob 开始抓包
首先确认 Bob 访问 Alice 时使用哪块接口:
ip route get 192.168.106.130
假设结果显示:
dev ens37
开始抓包:
sudo tcpdump -i ens37 -e -nn -s0 -vv -X \
'udp and dst host 192.168.106.132 and dst port 8080'
这里最值得关注的两个参数是:
-e
显示 Ethernet Header,也就是 MAC 地址。
以及:
-X
显示 Payload。
因此后面我们可以同时观察:
Ethernet Source MAC
IP Source Address
Payload
十、对照组:Alice 正常发送数据
首先建立正常数据包。
Alice 创建:
nano ep02_alice.py
写入:
import socket
ALICE_IP = "192.168.106.130"
BOB_IP = "192.168.106.132"
SOURCE_PORT = 40000
DESTINATION_PORT = 8080
payload = b"EP02 LEGITIMATE ALICE"
sock = socket.socket(
socket.AF_INET,
socket.SOCK_DGRAM
)
sock.bind(
(ALICE_IP, SOURCE_PORT)
)
sock.sendto(
payload,
(BOB_IP, DESTINATION_PORT)
)
print("Legitimate packet sent")
print(f"Source : {ALICE_IP}:{SOURCE_PORT}")
print(f"Destination : {BOB_IP}:{DESTINATION_PORT}")
print(f"Payload : {payload.decode()}")
sock.close()
运行:
python3 ep02_alice.py
应该看到:
Legitimate packet sent
Source : 192.168.106.130:40000
Destination : 192.168.106.132:8080
Payload : EP02 LEGITIMATE ALICE
Bob 观察正常报文
Bob 的 tcpdump 中应该出现类似:
Alice-MAC > Bob-MAC
IP 192.168.106.130.40000 >
192.168.106.132.8080
Payload:
EP02 LEGITIMATE ALICE
记录两个关键字段:
Ethernet Source
=
Alice MAC
以及:
IP Source
=
192.168.106.130
所以正常情况下:
实际发送主机:Alice
Ethernet Source:
Alice MAC
IP Source:
192.168.106.130
这就是后面伪造实验的对照组。
十一、实验组:Kali 伪造 Alice 的 Source IP
现在进入整个实验最关键的一步。
Kali 的真实地址是:
192.168.106.131
但是这一次,我们不让它使用自己的地址作为 Source IP。
而是人为构造:
Source IP = 192.168.106.130
也就是 Alice 的 IP。
在 Kali 创建:
nano ep02_spoof.py
写入:
from scapy.all import IP, UDP, Raw, send
ALICE_IP = "192.168.106.130"
KALI_IP = "192.168.106.131"
BOB_IP = "192.168.106.132"
SOURCE_PORT = 40000
DESTINATION_PORT = 8080
payload = b"EP02 SPOOFED BY KALI"
packet = (
IP(
src=ALICE_IP,
dst=BOB_IP
)
/
UDP(
sport=SOURCE_PORT,
dport=DESTINATION_PORT
)
/
Raw(
load=payload
)
)
print("Kali real IP :", KALI_IP)
print("Spoofed IP :", ALICE_IP)
print("Destination :", BOB_IP)
print()
print("Packet structure:")
packet.show()
send(
packet,
verbose=False
)
print()
print("Spoofed packet sent.")
关键代码只有一处
整个脚本中真正需要理解的是:
IP(
src=ALICE_IP,
dst=BOB_IP
)
而:
ALICE_IP = "192.168.106.130"
Kali 自己的真实 IP 明明是:
192.168.106.131
但构造 IP Header 时,我们直接把 Source Address 写成了:
192.168.106.130
也就是说:
IP Header 中的 Source Address 可以被发送者人为构造。
运行伪造脚本
Kali:
sudo python3 ep02_spoof.py
因为 Scapy 需要发送原始数据包,所以这里需要 root 权限。
输出类似:
Kali real IP : 192.168.106.131
Spoofed IP : 192.168.106.130
Destination : 192.168.106.132
packet.show() 中还会看到:
###[ IP ]###
src = 192.168.106.130
dst = 192.168.106.132
###[ UDP ]###
sport = 40000
dport = 8080
###[ Raw ]###
load = b'EP02 SPOOFED BY KALI'
此时形成了一个非常关键的事实:
运行脚本的机器:
Kali
192.168.106.131
但发出去的数据包:
Source IP
=
192.168.106.130
十二、Bob 观察伪造数据包
回到 Bob。
tcpdump 应该能够看到类似:
Kali-MAC > Bob-MAC
IP 192.168.106.130.40000 >
192.168.106.132.8080
Payload:
EP02 SPOOFED BY KALI
现在出现了整个实验最关键的现象。
Ethernet 层:
Source MAC
=
Kali MAC
但是 IP 层:
Source IP
=
192.168.106.130
也就是 Alice 的 IP 地址。
因此真正的数据包关系是:
Kali
真实 IP:192.168.106.131
真实网卡:Kali MAC
│
│ 构造 IP Header
▼
┌──────────────────────────┐
│ Ethernet Source │
│ Kali MAC │
│ │
│ IP Source │
│ 192.168.106.130 │
│ │
│ Payload │
│ EP02 SPOOFED BY KALI │
└──────────────────────────┘
│
▼
Bob
192.168.106.132
十三、比较两份数据包
现在把实验结果放在一起。
| 字段 | Alice 正常报文 | Kali 伪造报文 |
|---|---|---|
| 实际发送主机 | Alice | Kali |
| 主机真实 IP | .130 | .131 |
| Ethernet Source | Alice MAC | Kali MAC |
| IP Source | .130 | .130 |
| UDP Source Port | 40000 | 40000 |
| Destination IP | .132 | .132 |
| Destination Port | 8080 | 8080 |
| Payload | LEGITIMATE ALICE | SPOOFED BY KALI |
最重要的一行就是:
IP Source
Alice 正常发送:
192.168.106.130
Kali 伪造发送:
192.168.106.130
两份报文在 IP 层都声称:
我来自 Alice。
但真正发送它们的主机并不是同一台机器。
至此,本实验已经完成。
十四、可选:保存完整 PCAP
如果希望把实验结果长期保存,可以再进行一次抓包。
Bob:
sudo tcpdump -i ens37 -e -nn -s0 \
-w ep02-source-ip-spoofing.pcap \
'udp and dst host 192.168.106.132 and dst port 8080'
然后依次运行:
Alice:
python3 ep02_alice.py
Kali:
sudo python3 ep02_spoof.py
回到 Bob:
Ctrl+C
得到:
ep02-source-ip-spoofing.pcap
重新查看:
tcpdump -e -nn -vv -X \
-r ep02-source-ip-spoofing.pcap
这样可以连续看到正常报文和伪造报文。
PCAP 可以作为 EP02 的原始实验材料保存。
十五、为什么会出现这种现象
现在重新回答开头的问题。
Bob 收到:
Source IP = 192.168.106.130
是否能够证明:
发送者一定是 Alice?
答案是:
不能。
原因并不复杂。
IP 协议负责的是:
寻址
路由
转发
而不是:
身份认证
IP Header 中存在:
Source Address
Destination Address
它们首先用于网络通信。
例如:
Source 192.168.106.130
Destination 192.168.106.132
告诉网络这个数据包:
声称从哪里来
以及
准备到哪里去
但普通 IP 协议并没有要求:
发送者在填写 Source Address 之前,必须提供密码学证据证明自己确实就是这个身份。
所以:
Source IP
│
▼
网络层地址
不能直接变成:
Source IP
│
▼
经过验证的身份
十六、为什么实验还观察了 MAC 地址
这里需要特别控制实验结论的边界。
本实验观察:
Alice MAC
和:
Kali MAC
只是为了在当前这个同一二层 VMware 实验网络里辅助证明:
两个 Source IP 都是
.130的数据包,实际上来自不同虚拟机。
这绝不意味着:
IP 不可信
MAC 就可信
MAC 地址本身也不是密码学身份认证机制。
而且如果 Alice 和 Bob 之间经过路由器:
Alice
│
Router
│
Bob
Bob 在 Ethernet 层看到的 Source MAC 通常属于:
最后一跳路由器
而不是 Alice。
所以 MAC 在这里仅仅是:
实验观察手段。
而不是实验结论。
真正需要记住的仍然只有:
IP 地址
≠
身份认证
十七、本实验没有证明什么
Source IP 可以被伪造,并不意味着:
攻击者能够在任何网络中随意冒充任意 IP 完成完整通信。
真实网络中还可能部署:
ACL
防火墙
uRPF
源地址反欺骗
运营商过滤
交换机安全机制
其他网络访问控制
这些机制可能直接阻止伪造报文。
另外,伪造 Source IP 本身还有一个明显的问题。
例如 Kali 发送:
Source IP = Alice
Bob 如果进行回复:
Bob
│
│ Reply
▼
192.168.106.130
回复通常会发送给真正的 Alice,而不是 Kali。
所以:
能够伪造一个单向数据包,并不等于能够自动劫持完整的双向通信。
但是这些限制不会改变本实验已经证明的事实:
IP Source Address 本身没有提供身份认证能力。
十八、从实验回到安全通信
现在再考虑 Alice 和 Bob:
Alice
192.168.106.130
↕
Bob
192.168.106.132
Bob 不能简单地认为:
只要 Source IP 是
192.168.106.130
对方就一定是 Alice
因为我们刚刚亲手让:
Kali
192.168.106.131
发出了一份:
Source IP
=
192.168.106.130
的数据包。
于是一个新的问题自然出现:
如果地址本身不能证明身份,那么安全通信应该怎样确认对面到底是谁?
这就是后面会逐渐出现的:
身份认证
不过 EP02 到这里就应该停下来。
现在还不需要引入 IKE、PSK 或数字证书。
这一实验只需要建立一个清晰的认知边界:
Source IP 是地址,不是身份证。
实验总结
本实验使用三台主机:
Alice
192.168.106.130
Kali
192.168.106.131
Bob
192.168.106.132
首先由真正的 Alice 正常发送:
Source IP = 192.168.106.130
然后由 Kali 使用 Scapy 构造:
IP(
src="192.168.106.130",
dst="192.168.106.132"
)
Bob 最终观察到:
Alice 正常报文
Ethernet Source:
Alice MAC
IP Source:
192.168.106.130
而 Kali 伪造报文:
Ethernet Source:
Kali MAC
IP Source:
192.168.106.130
两个数据包的实际发送主机不同。
但是它们在 IP 层都声称:
Source IP = 192.168.106.130
因此我们最终验证了:
一个数据包声称自己来自 Alice,并不意味着发送者已经被证明就是 Alice。
换句话说:
IP 地址解决寻址
≠
IP 地址解决身份认证
或者更容易记:
Source IP 告诉你数据包“说自己是谁”,身份认证才负责证明“它到底是谁”。