# 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. 理想情况：当前内核接受 redirect，victim 会真的改路由
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 发 redirect，victim ping，检查路径
2. 如果当前环境没有真的安装 redirect，就用 `nstat -az | grep Redirect` 证明 victim 已收到 redirect
3. 然后说明由于当前内核更严格，手工把 victim 路由切到 `10.9.0.111`
4. 继续演示第二阶段 MITM，把 `hello seedlabs` 成功改成 `hello AAAAAAAA`

这样展示是完整的，逻辑也是自洽的。
