87cf5fe05f
- test_netns_stand.py — 8 тестов: топология и линки, policy routing по fwmark, правила меток и kill-switch, готовность мока и детектора, доставка handshake из LAN и из шлюза с ростом счётчика метки, имитация недоступности провайдера (mode=drop), положительный контроль утечки и блокировка при kill-switch. Тесты пропускаются вне run.sh, чтобы не падать при случайном pytest-прогоне; - README.md харнесса — схема топологии, состав файлов, таблица тестов, переменные окружения и pitfalls (root/CAP_NET_ADMIN, rp_filter, отсутствие nft и ping в alpine-образе). Refs #21 Refs #15
105 lines
7.4 KiB
Markdown
105 lines
7.4 KiB
Markdown
# tests/netns — сетевой тестовый стенд
|
|
|
|
Задача **#21**, используется тестами split-tunnel (#40, #41, #43).
|
|
|
|
Цель: проверять маршрутизацию, policy routing, метки трафика и fail-closed
|
|
**без реального VPN-провайдера** и без доступа к продакшн-сети.
|
|
|
|
## Топология
|
|
|
|
```
|
|
client ns gw ns (шлюз awg-dash) uplink ns («ISP»)
|
|
10.213.0.2/24 ──veth──► 10.213.0.1/24 10.214.0.1/24 ──veth──► 10.214.0.2/24
|
|
(LAN-устройство) ip_forward=1, ip rule fwmark 51820 мок-endpoint udp/51820
|
|
→ table 51820 → default via uplink детектор утечки
|
|
198.51.100.9:9999
|
|
```
|
|
|
|
| Namespace | По умолчанию | Роль | Адреса |
|
|
|---|---|---|---|
|
|
| `awgt21-client` | `AWG_NS_CLIENT` | LAN-устройство за шлюзом | `10.213.0.2/24` |
|
|
| `awgt21-gw` | `AWG_NS_GW` | хост со шлюзом: forwarding, policy routing, netfilter | `10.213.0.1/24`, `10.214.0.1/24` |
|
|
| `awgt21-uplink` | `AWG_NS_UPLINK` | «ISP»: мок WireGuard-endpoint + детектор утечки | `10.214.0.2/24`, `198.51.100.9/32` |
|
|
|
|
Правила в `gw`: `ip rule fwmark 51820 lookup 51820` + `table 51820 default via 10.214.0.2`
|
|
(как в `wg-quick`), метки ставит netfilter на исходящий трафик шлюза (OUTPUT) и на
|
|
транзитный трафик LAN (FORWARD). Kill-switch — правило DROP в FORWARD для трафика
|
|
LAN, уходящего напрямую в «публичную» сеть `198.51.100.0/24` (RFC 5737 TEST-NET-2).
|
|
Адрес детектора утечки поднят на `lo` аплинка: если при включённом kill-switch пакет
|
|
дошёл до детектора — тест падает.
|
|
|
|
## Запуск
|
|
|
|
```bash
|
|
make test-netns # поднять стенд, прогнать тесты, снести стенд
|
|
make test-netns-keep # оставить топологию и логи для отладки
|
|
make test-netns NETNS_ARGS="--no-tests" # только поднять стенд
|
|
make test-netns-ci # то же в привилегированном контейнере (путь для CI)
|
|
|
|
bash tests/netns/topology.sh status # состояние топологии
|
|
bash tests/netns/topology.sh down # снести топологию вручную
|
|
bash tests/netns/topology.sh killswitch on # включить fail-closed правило
|
|
```
|
|
|
|
Требования: Linux, **root** (или CAP_NET_ADMIN + CAP_SYS_ADMIN), `ip`, `python3`;
|
|
backend netfilter — `nft` или `iptables` (в alpine-образе приложения есть только
|
|
`iptables`, на Debian/Ubuntu — оба). Код возврата `3` означает «заблокировано
|
|
окружением»: нет прав на создание netns.
|
|
|
|
## Состав
|
|
|
|
| Файл | Назначение |
|
|
|---|---|
|
|
| `run.sh` | точка входа: preflight → топология → мок → тесты → снос |
|
|
| `lib.sh` | конфигурация стенда + правила netfilter (nft/iptables) |
|
|
| `topology.sh` | `up`/`down`/`status`/`killswitch on|off` |
|
|
| `mock_wg_endpoint.py` | мок WireGuard-endpoint: отвечает на handshake initiation |
|
|
| `leak_sink.py` | детектор утечки: UDP+TCP `198.51.100.9:9999` |
|
|
| `probe.py` | генератор тестового трафика из указанного netns |
|
|
| `netns_common.py` | утилиты для тестов (ns_exec, счётчики правил, JSONL-логи) |
|
|
| `run_tests.py` | прогон unittest + JSON-отчёт |
|
|
| `test_netns_stand.py` | 8 интеграционных тестов стенда |
|
|
|
|
## Что проверяют тесты (`test_netns_stand.py`)
|
|
|
|
1. `test_01` — netns и veth-пары созданы, адреса выданы, `ip_forward=1`.
|
|
2. `test_02` — policy routing: `ip rule fwmark 51820` → `table 51820` → аплинк.
|
|
3. `test_03` — правила меток (OUTPUT/FORWARD) и DROP kill-switch на месте.
|
|
4. `test_04` — мок-endpoint и детектор утечки слушают и залогировали `listen`.
|
|
5. `test_05` — handshake initiation из LAN доходит до мока, мок отвечает
|
|
(148 → 92 байта), счётчик правила метки растёт.
|
|
6. `test_06` — то же для трафика, инициированного самим шлюзом (OUTPUT-метка).
|
|
7. `test_07` — режим `drop` мока имитирует недоступность провайдера: ответа нет,
|
|
пакеты фиксируются; возврат в `respond` восстанавливает стенд.
|
|
8. `test_08` — kill-switch: при выключенном правиле трафик доходит до детектора
|
|
(положительный контроль), при включённом — утечки нет.
|
|
|
|
## Параметры (переменные окружения)
|
|
|
|
| Переменная | По умолчанию | Назначение |
|
|
|---|---|---|
|
|
| `AWG_NETNS_PREFIX` | `awgt21` | префикс имён namespace/veth |
|
|
| `AWG_NS_CLIENT` / `AWG_NS_GW` / `AWG_NS_UPLINK` | `awgt21-*` | имена namespace |
|
|
| `AWG_MOCK_PORT` | `51820` | порт мока WireGuard-endpoint |
|
|
| `AWG_LEAK_IP` / `AWG_LEAK_PORT` | `198.51.100.9` / `9999` | адрес и порт детектора утечки |
|
|
| `AWG_FWMARK` / `AWG_ROUTE_TABLE` | `51820` / `51820` | метка и таблица policy routing |
|
|
| `AWG_FW_BACKEND` | `auto` | `nft`, `iptables` или автоопределение |
|
|
| `AWG_NETNS_WORKDIR` | `mktemp -d` | каталог логов и отчёта стенда |
|
|
|
|
## Pitfalls
|
|
|
|
* **`ip netns add` в контейнере** требует `--privileged` (CAP_SYS_ADMIN) — иначе
|
|
`run.sh` завершится кодом 3 с сообщением «заблокировано окружением».
|
|
* **rp_filter** в шлюзе выставлен в `2` (loose): маркированная политика даёт
|
|
асимметрию reverse-пути, strict-режим молча дропает ответы.
|
|
* **Мок не умеет криптографию**: он повторяет раскладку сообщений WireGuard
|
|
(тип и длины), но не выполняет Noise IK handshake. Годится для топологии,
|
|
меток, policy routing и fail-closed — **не** для проверки шифрования, MTU и
|
|
пропускной способности.
|
|
* **`nft` в alpine-образе нет**: в контейнере используется `iptables`
|
|
(nft-backend). Стенд поддерживает оба backend; при отладке форсируйте
|
|
`AWG_FW_BACKEND=iptables`.
|
|
* **`ping` в образе нет** (пакет `iputils` не установлен) — тесты не используют
|
|
ICMP: связность проверяется UDP-трафиком через мок и детектор утечки.
|
|
* **Остатки после падения**: `bash tests/netns/topology.sh down` и `ip netns list`.
|