473 lines
10 KiB
Markdown
473 lines
10 KiB
Markdown
# 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`
|
||
|
||
这样展示是完整的,逻辑也是自洽的。
|