maxlluky/VPN-Traffic-Obfuscation-Lab
GitHub: maxlluky/VPN-Traffic-Obfuscation-Lab
一个基于 Docker 的 VPN 流量检测与混淆测试平台,用于评估不同隧道技术在 IDS/IPS 中的可见性。
Stars: 0 | Forks: 0
# VPN 混淆实验室(学士项目)
一个可重现的基于 Docker 的测试平台,用于评估 VPN 流量(原始 WireGuard)和 VPN 混淆技术(UDP2RAW、OBFS4)的可检测性,使用 Suricata IDS、Zeek NSM 和 nDPI 深度包检测。
**Max Luckert** · Wrexham University · [mluckert@outlook.de](mailto:mluckert@outlook.de)
## 目录
1. [项目结构](#project-structure)
2. [快速开始](#quickstart)
3. [流量模式](#traffic-modes)
4. [场景](#scenarios)
5. [IDS 验证](#ids-validation)
6. [分析(Jupyter 笔记本)](#analysis-jupyter-notebook)
7. [架构](#architecture)
8. [清理](#cleanup)
9. [故障排除](#troubleshooting)
10. [许可证](#license)
## 项目结构
### 组合文件(`compose/`)
| 文件 | 用途 |
|---|---|
| `compose.yml` | 基础堆栈:目标、Suricata、Zeek、ndpi、网络 |
| `compose.baseline.yml` | 场景 1:原始 WireGuard |
| `compose.udp2raw.yml` | 场景 2:封装在 TCP/443 中的 WireGuard |
| `compose.obfs4.yml` | 场景 3:通过 Shadowsocks-rust + obfs4proxy 的 WireGuard |
| `compose.validate.yml` | IDS 正向控制(明文 HTTP,无 VPN) |
### 脚本(`scripts/`)
```
scripts/
├── run_scenario.sh – Main experiment runner (all scenarios + traffic modes)
├── lib.sh – Shared functions (stack management, capture, artifact collection)
├── validate_ids.sh – IDS positive control
├── cleanup.sh – Tears down all containers, networks, volumes
└── pcap_to_packet_csv.sh – Internal: extracts packet features via tshark
```
### 服务(`services/`)
```
services/
│
│ ── Detection ──────────────────────────────────────────────────────
├── suricata/ – IDS (ET Open ~49 k rules + custom WG behavioral rules)
├── zeek/ – NSM (JSON conn.log output)
├── ndpi/ – DPI (nDPI 5.0, built from source)
│
│ ── VPN & Proxies ───────────────────────────────────────────────────
├── vpn-client/ – WireGuard client configurations
│ ├── baseline/ – wg0.conf for Baseline
│ ├── udp2raw/ – wg0.conf for UDP2RAW
│ └── obfs4/ – wg0.conf for OBFS4
├── vpn-gateway/ – WireGuard server configurations
│ ├── baseline/ – Standard MTU config
│ ├── udp2raw/ – Low MTU + sidecar entrypoint.sh
│ └── obfs4/ – Low MTU config
├── proxy-obfs4/ – Shadowsocks-rust + obfs4proxy (SIP003 plugin via pt_adapter.py)
├── proxy-udp2raw/ – UDP2RAW proxy (fake-TCP/443 wrapping)
│
│ ── Clients & Traffic ───────────────────────────────────────────────
├── traffic-client/ – Traffic generator (Python HTTP + iperf3 streaming)
├── target-server/ – Nginx + iperf3 server (pre-installed in Dockerfile)
│ └── html/ – Static assets for HTTP burst traffic
└── http-client/ – IDS validation client (curl/bind-tools, no VPN)
```
### 结果(`results/`)
```
results/runs/
//
├── metadata.json – Scenario, mode, seed, tool versions
├── pcap/ – Raw packet capture (.pcap)
├── pcap_features/ – Tshark-extracted packets.csv
├── suricata/ – eve.json, fast.log
├── zeek/ – conn.log
├── ndpi/ – summary.txt, flows.csv
└── iperf/ – iperf.json (streaming mode only)
```
## 快速开始
### 先决条件
- Linux 主机(已在 Ubuntu / Arch Linux 上测试)
- Docker Engine ≥ 24.x + Docker Compose v2
- 内核 WireGuard 支持(`wireguard`、`udp_tunnel` 模块)
- 主机上的 `tcpdump` 和 `tshark`:
# Ubuntu/Debian
sudo apt install tcpdump tshark
# Arch Linux
sudo pacman -S tcpdump wireshark-cli
### 安装
```
# 1. 克隆
git clone https://github.com/maxlluky/VPN-Traffic-Obfuscation-Lab.git
cd VPN-Traffic-Obfuscation-Lab
# 2. 环境
cp compose/.env.example compose/.env
# 如需编辑 compose/.env(UDP2RAW_IMAGE,BRIDGE_IF)
# 3. 验证检测堆栈
bash scripts/validate_ids.sh
# 4. 运行首次实验
bash scripts/run_scenario.sh baseline
```
## 流量模式
| 模式 | 描述 | 用途 |
|---|---|---|
| **burst**(默认) | 50 个顺序 HTTP 请求 | 连接性检查,快速告警生成 |
| **streaming** | 持续 60 秒的 iperf3 TCP 流 | 吞吐量统计,流量分析(Zeek) |
```
bash scripts/run_scenario.sh baseline # burst (default)
bash scripts/run_scenario.sh baseline streaming # streaming
# 完整实验集 — 每个场景 1× 突发 + 2× 流式传输(总计 9 次运行)
# 每个场景的两次流式传输运行提供平均 ± 95% 置信区间的吞吐量统计(t 分布)。
for scenario in baseline udp2raw obfs4; do
bash scripts/run_scenario.sh "$scenario" burst
bash scripts/run_scenario.sh "$scenario" streaming
bash scripts/run_scenario.sh "$scenario" streaming
done
```
## 场景
### 场景 1:基线 — 明文 WireGuard
```
bash scripts/run_scenario.sh baseline
```
明文 WireGuard 隧道,UDP/51820。无混淆。作为检测参考:ndpi 识别 WireGuard,且自定义 Suricata 规则(SID 9000001/9000002)在 WireGuard 握手时触发。
### 场景 2:UDP2RAW — WireGuard 封装在 TCP/443
```
bash scripts/run_scenario.sh udp2raw
```
WireGuard UDP 被封装为伪 TCP 并通过端口 443 隧道传输。ndpi 将其归类为 TLS(基于端口匹配),但找不到 TLS Client Hello — 这是明显的 FakeTCP 指示。
### 场景 3:OBFS4 — Shadowsocks + obfs4proxy
```
bash scripts/run_scenario.sh obfs4
```
WireGuard 通过 Shadowsocks-rust(ChaCha20-Poly1305)加密,并经由 obfs4proxy 作为 SIP003 插件(`pt_adapter.py`)进行混淆。线上的流量为 **UDP**,端口 12345,载荷随机。ndpi 将其归类为 Unknown — 混淆有效。
## IDS 验证
在得出结论前,请运行正向控制以确认检测堆栈功能正常:
```
bash scripts/validate_ids.sh
```
发送明文 HTTP(无 VPN),并期望 Suricata ET 告警、Zeek 的 `service=http` 以及 nDPI HTTP 分类。**VPN 场景中无告警是真实发现,而非配置错误。**
## 分析(Jupyter 笔记本)
### 安装
```
python3 -m venv .venv
source .venv/bin/activate
pip install -r analysis/requirements.txt
```
在 VS Code 或 JupyterLab 中打开 `analysis/Analysis_Starter.ipynb`(选择 `.venv` 内核)。
### 笔记本涵盖内容
1. **IDS 可见性(Suricata 与 Zeek)** — 每个运行的告警计数;ET 开源规则与自定义 WireGuard 规则命中情况(SID 9000001/9000002);Zeek 协议检测流程
2. **深度包检测(nDPI)** — 协议指纹识别结果及各场景分类
3. **流量指纹识别** — 分组大小与到达间隔分布;TCP 与 UDP 分解
4. **协议合理性检查** — TCP/443 流中 TLS Client Hello 的存在(UDP2RAW FakeTCP 指示)
5. **性能** — 各场景吞吐量的均值 ± 95% 置信区间(t 分布,`t.ppf(0.975, df=n−1)`)
6. **香农熵** — 原始 PCAP 载荷的随机性;越高表示混淆越有效
7. **描述性统计与 KS 检验** — 分组大小与到达间隔的描述统计;成对 Kolmogorov-Smirnov 检验
8. **汇总表** — 场景 × 指标矩阵,用于论文评估章节
### 自定义 WireGuard 检测规则
`services/suricata/rules/local.rules` 包含两个随 ET Open 加载的行为规则:
- **SID 9000001** — 握手发起者:UDP,148 字节载荷,前 4 字节为 `01 00 00 00`
- **SID 9000002** — 握手响应:UDP,92 字节载荷,前 4 字节为 `02 00 00 00`
这些规则基于 **数据包结构** 检测 WireGuard,而非端口号。仅基线场景会触发它们。
## 架构
### 网络
| 网络 | 子网 | 用途 |
|---|---|---|
| `client_net` | 192.168.10.0/24 | VPN 客户端侧 — 所有检测工具的捕获点 |
| `external_net` | 172.30.30.0/24 | 目标服务器侧 |
| `internal_net` | 192.168.20.0/24 | 代理到网关链路(仅 UDP2RAW 与 OBFS4 使用) |
### 流量流程:基线
```
traffic-client (192.168.10.10)
↓ HTTP requests
wg-client [WireGuard tunnel established]
↓ WireGuard encrypted UDP/51820
[client_net bridge] ← Suricata / Zeek / nDPI capture
↓ WireGuard encrypted UDP/51820
vpn-gateway (192.168.10.2 ↔ 172.30.30.2) [decrypts]
↓ plain HTTP
target-server (172.30.30.10)
```
### 流量流程:UDP2RAW
```
traffic-client (192.168.10.10)
↓ HTTP requests
wg-client [WireGuard → 127.0.0.1:51820]
↓ WireGuard UDP/51820 (loopback)
proxy-udp2raw client [wraps UDP → fake TCP/443]
↓ fake TCP/443
[client_net bridge] ← Suricata / Zeek / nDPI capture
↓ fake TCP/443
proxy-udp2raw gateway [unwraps TCP → UDP/51820]
↓ WireGuard UDP/51820
vpn-gateway [decrypts]
↓ plain HTTP
target-server (172.30.30.10)
```
### 流量流程:OBFS4
```
traffic-client (192.168.10.10)
↓ HTTP requests
wg-client [WireGuard → 127.0.0.1:51820]
↓ WireGuard UDP/51820 (loopback)
proxy-obfs4 client [sslocal -U + obfs4proxy via SIP003]
↓ Shadowsocks ChaCha20 + obfs4 randomisation, UDP/12345
[client_net bridge] ← Suricata / Zeek / nDPI capture
↓ obfuscated UDP/12345
proxy-obfs4 gateway [ssserver + obfs4proxy]
↓ WireGuard UDP/51820
vpn-gateway [decrypts]
↓ plain HTTP
target-server (172.30.30.10)
```
## 清理
```
bash scripts/cleanup.sh # stop all containers, remove networks & volumes
bash scripts/cleanup.sh --all # also remove built images
sudo rm -rf results/* # delete all experiment results (optional)
```
## 故障排除
**桥接接口未找到**
```
BRIDGE_IF=br-a1b2c3d4e5f6 bash scripts/run_scenario.sh baseline
```
**Suricata 未启动**
```
docker logs suricata-ids # check BRIDGE_IF is set correctly in .env
```
**UDP2RAW 连接失败**
```
docker logs proxy-udp2raw # verify UDP2RAW_GATEWAY_PORT=443 in .env
```
**OBFS4 连接失败**
```
docker logs obfs4-gateway
docker logs obfs4-client # check pt_adapter.py started and certs match
```
## 许可证
© 2026 Max Luckert。本项目根据 [GNU General Public License v3.0](LICENSE) 授权。
你可以自由使用、学习、修改和分发本项目,衍生作品也必须在 GPL-3.0 下发布。标签:Docker, Metaprompt, nDPI, NSM, obfs4, PCAP, Rootkit, Suricata, UDP2RAW, VPN, VPN混淆, Windows内核驱动, WireGuard, Zeek, 可重现, 学士论文, 安全防御评估, 流量检测, 流量混淆检测, 测试床, 深度包检测, 深度学习, 现代安全运营, 系统分析, 网络分析, 网络安全, 网络安全分析, 网络流量, 请求拦截, 逆向工具, 隐私保护