Files
nudtns2026spring/ICMP_Directing/Experiment_Guide.md
2026-04-10 10:24:42 +08:00

473 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ICMP Redirect 与 MITM 实验演示手册
本文档按“实际演示”来写,不只解释原理,还给出每个容器要执行的具体命令。
当前仓库已经包含可用脚本:
- `Labsetup/volumes/task1.py`
- `Labsetup/volumes/task1_improved.py`
- `Labsetup/volumes/task1_sniff_and_redirect.py`
- `Labsetup/volumes/mitm_attack.py`
其中:
- `task1.py` 是当前更适合展示的 ICMP Redirect 发送脚本
- `task1_sniff_and_redirect.py` 只在攻击者容器能看到 victim 单播流量时才适用
- `mitm_attack.py` 已修复死循环重发问题,可以直接用于 MITM 展示
---
## 1. 实验目标
本实验分两部分:
1. 演示 ICMP Redirect 攻击,尝试让 `victim` 把发往 `192.168.60.5` 的流量改走恶意路由器 `10.9.0.111`
2. 演示 MITM 篡改,在恶意路由器上把 `hello seedlabs` 改成 `hello AAAAAAAA`
---
## 2. 拓扑与角色
| 容器 | IP | 作用 |
| :--- | :--- | :--- |
| `victim-10.9.0.5` | `10.9.0.5` | 受害者 |
| `attacker-10.9.0.105` | `10.9.0.105` | 发送 ICMP Redirect 的攻击机 |
| `malicious-router-10.9.0.111` | `10.9.0.111` | 恶意路由器,负责 MITM |
| `router` | `10.9.0.11 / 192.168.60.11` | 合法路由器 |
| `host-192.168.60.5` | `192.168.60.5` | 目标主机 |
---
## 3. 启动环境
在宿主机的项目根目录执行:
```bash
cd /home/gh0s7/project/netsecurity2026/ICMP_Directing/Labsetup
docker-compose up -d
docker ps
```
建议先确认容器都起来了:
```bash
docker ps --format 'table {{.Names}}\t{{.Status}}'
```
---
## 4. 打开 5 个终端
建议分别打开以下终端,便于课堂展示:
### 终端 1: victim
```bash
docker exec -it victim-10.9.0.5 bash
```
### 终端 2: attacker
```bash
docker exec -it attacker-10.9.0.105 bash
```
### 终端 3: malicious-router
```bash
docker exec -it malicious-router-10.9.0.111 bash
```
### 终端 4: target host
```bash
docker exec -it host-192.168.60.5 bash
```
### 终端 5: router
```bash
docker exec -it router bash
```
`router` 终端不是必须,但展示路径时有帮助。
---
## 5. 演示前检查
### 在 victim 容器执行
先确认默认到目标网段的路由仍然指向合法网关:
```bash
ip route
```
你应该看到类似结果:
```bash
192.168.60.0/24 via 10.9.0.11 dev eth0
```
再清理路由缓存:
```bash
ip route flush cache
```
再查看当前 redirect 相关内核参数:
```bash
sysctl net.ipv4.conf.all.accept_redirects
sysctl net.ipv4.conf.eth0.accept_redirects
sysctl net.ipv4.conf.all.secure_redirects
sysctl net.ipv4.conf.eth0.secure_redirects
```
### 在 malicious-router 容器执行
先看恶意路由器的默认路由:
```bash
ip route
```
### 在 attacker 容器执行
确认脚本在共享目录里:
```bash
ls -l /volumes
```
---
## 6. 第一阶段: ICMP Redirect 展示
这一阶段分为两种情况:
1. 理想情况:当前内核接受 redirectvictim 会真的改路由
2. 当前环境常见情况victim 能收到 redirect但不会真的安装这条重定向路由
### 6.1 在 attacker 容器执行
先运行静态 redirect 脚本:
```bash
python3 /volumes/task1.py
```
这个脚本会:
- 伪造源 IP 为合法网关 `10.9.0.11`
- 伪造源 MAC 为合法网关的 MAC
- 发送 ICMP Type 5 Redirect
- 引用一个最小合法长度的“原始触发包”片段
如果你想把发送次数调大一点,可以这样运行:
```bash
python3 /volumes/task1.py --count 50 --interval 0.2
```
### 6.2 在 victim 容器执行
在 attacker 正在发包时,触发 victim 访问目标主机:
```bash
ping -c 3 192.168.60.5
```
然后检查缓存和路径:
```bash
ip route show cache
ip route get 192.168.60.5
mtr -n -r -c 2 192.168.60.5
```
### 6.3 成功时你应看到什么
理想情况下,`mtr` 第一跳会变成:
```bash
10.9.0.111
```
`ip route show cache` 可能出现类似:
```bash
192.168.60.5 via 10.9.0.111 dev eth0
cache <redirected>
```
### 6.4 如果没有成功,这在当前环境是正常的
我在当前环境里实际验证过:
- victim 能收到大量 ICMP Redirect
- 但路由没有真正切换到 `10.9.0.111`
原因不是脚本完全没工作,而是当前容器共享宿主机较新的 Linux 内核,对 redirect 的接受条件比实验 PDF 对应的旧环境更严格。
你可以在 victim 容器里用下面命令说明“包确实收到了”:
```bash
nstat -az | grep Redirect
```
如果 `IcmpInRedirects` 持续增加,就说明 redirect 已到达 victim 内核。
### 6.5 关于 `task1_sniff_and_redirect.py`
这个脚本只在攻击者能嗅探到 victim 发往 router 的单播 ICMP 时才适合使用:
```bash
python3 /volumes/task1_sniff_and_redirect.py
```
在当前 Docker bridge 拓扑里,`attacker` 通常看不到 `victim -> router` 的单播流量,所以这个脚本经常抓不到包。这不是代码语法问题,而是网络可见性问题。
---
## 7. 第二阶段: MITM 篡改展示
因为第一阶段在当前环境下可能不会真的完成“自动改路由”,所以演示时推荐手工把 victim 的目标网段路由改到恶意路由器。这一步相当于“模拟第一阶段已经成功”。
这能稳定完成第二阶段展示,而且可以清楚证明 MITM 篡改逻辑是正确的。
### 7.1 在 victim 容器执行
先把发往目标网段的路由改到恶意路由器:
```bash
ip route replace 192.168.60.0/24 via 10.9.0.111
```
验证:
```bash
ip route
mtr -n -r -c 2 192.168.60.5
```
此时 `mtr` 应该看到类似三跳:
```bash
10.9.0.111
10.9.0.11
192.168.60.5
```
说明流量已经先进入恶意路由器,再被转发到真实路由器和目标主机。
### 7.2 在 malicious-router 容器执行
关闭内核自动转发:
```bash
sysctl -w net.ipv4.ip_forward=0
```
然后启动 MITM 脚本:
```bash
python3 /volumes/mitm_attack.py
```
这个脚本只拦截:
- 源 IP 是 `10.9.0.5`
- 目的 IP 是 `192.168.60.5`
- 二层目的 MAC 真正发给恶意路由器本机
因此不会再把自己重发的包抓回来无限循环。
### 7.3 在 target host 容器执行
启动 netcat 监听:
```bash
nc -lp 9090
```
这个终端要保持打开。
### 7.4 在 victim 容器执行
发起 TCP 连接并发送测试字符串:
```bash
printf 'hello seedlabs\n' | nc -N 192.168.60.5 9090
```
### 7.5 在 target host 容器观察结果
如果 MITM 成功,目标主机终端不会看到:
```bash
hello seedlabs
```
而是会看到:
```bash
hello AAAAAAAA
```
### 7.6 在 malicious-router 容器观察结果
MITM 脚本终端会打印出它截获的原始载荷,例如:
```bash
Original data: b'hello seedlabs\n'
```
如果脚本是错误的,常见现象是会重复打印多次同一条已经修改过的数据,说明它抓到了自己重发的包。当前仓库中的 `mitm_attack.py` 已修复这个问题。
---
## 8. 一次完整展示时,各容器该执行什么命令
下面是一套可以直接照着走的顺序。
### 宿主机执行
```bash
cd /home/gh0s7/project/netsecurity2026/ICMP_Directing/Labsetup
docker-compose up -d
```
### victim 容器执行
```bash
ip route
ip route flush cache
sysctl net.ipv4.conf.all.accept_redirects
sysctl net.ipv4.conf.eth0.accept_redirects
ping -c 3 192.168.60.5
ip route show cache
ip route get 192.168.60.5
mtr -n -r -c 2 192.168.60.5
```
如果第一阶段未成功,继续执行:
```bash
ip route replace 192.168.60.0/24 via 10.9.0.111
mtr -n -r -c 2 192.168.60.5
printf 'hello seedlabs\n' | nc -N 192.168.60.5 9090
```
### attacker 容器执行
```bash
python3 /volumes/task1.py --count 50 --interval 0.2
```
可选:
```bash
python3 /volumes/task1_sniff_and_redirect.py
```
### malicious-router 容器执行
先在第一阶段前可只查看路由:
```bash
ip route
```
第二阶段执行:
```bash
sysctl -w net.ipv4.ip_forward=0
python3 /volumes/mitm_attack.py
```
### target host 容器执行
```bash
nc -lp 9090
```
### router 容器可选执行
如果老师想看正常路由器是否还在链路中,可以执行:
```bash
ip route
ip neigh
```
---
## 9. 现场讲解时可以这样解释
### Q1: 为什么第一阶段可能失败,但第二阶段还能演示成功?
答:
- 第一阶段依赖受害者内核真正接受 ICMP Redirect
- 当前环境下 victim 容器共享宿主机较新的 Linux 内核,检查更严格
- Redirect 包能到达 victim但内核未安装重定向缓存
- 为了继续展示 MITM 的核心思想,可以手工把 victim 的路由改到恶意路由器,相当于模拟第一阶段已经成功
### Q2: 为什么 `task1_sniff_and_redirect.py` 在当前环境未必好用?
答:
- 它要求 attacker 能看见 victim 发往 router 的单播包
- 当前 Docker bridge 网络通常不会把这类单播复制给 attacker
- 所以这个脚本在当前环境里常常抓不到包
### Q3: 为什么 `mitm_attack.py` 之前会重复打印很多次?
答:
- 因为原脚本只按 IP 层过滤
- 它把自己重发出去的包又抓回来处理了
- 现在脚本额外检查二层目的 MAC 是否真的是恶意路由器本机,从而避免死循环
### Q4: 为什么要关闭 `ip_forward`
答:
- 如果不关,内核会直接把原始包转发出去
- 应用层脚本来不及修改内容
- 关闭后,脚本才能接管“抓包、改包、重发”的过程
---
## 10. 恢复环境
展示完成后,建议把 victim 的路由恢复,避免后续混淆。
### 在 victim 容器执行
```bash
ip route replace 192.168.60.0/24 via 10.9.0.11
ip route flush cache
```
### 在 malicious-router 容器执行
```bash
sysctl -w net.ipv4.ip_forward=1
```
---
## 11. 最终建议
如果你要“稳定展示给老师看”,推荐这样安排:
1. 先演示第一阶段理论流程attacker 发 redirectvictim ping检查路径
2. 如果当前环境没有真的安装 redirect就用 `nstat -az | grep Redirect` 证明 victim 已收到 redirect
3. 然后说明由于当前内核更严格,手工把 victim 路由切到 `10.9.0.111`
4. 继续演示第二阶段 MITM`hello seedlabs` 成功改成 `hello AAAAAAAA`
这样展示是完整的,逻辑也是自洽的。