guard/docs/testing.md
loki5512344 0b53ed720b
feat: VDS stress test harness (edge-only) and load-test results
- deploy/test/stress/: multi-IP masked handshake flood (flood.py), legit client
  during attack (legit.py), full orchestration (run-stress.sh), edge Dockerfile
  with socat stub backend and high/defense configs
- docs/research/load-test-report.md: v3 VDS loopback results (2026-08-04)
- README.md: performance table update (4k conn/s raw, 99.6% blocked in defense,
  legit clients RTT 2-6ms during attack)
- docs/testing.md: multi-IP masked stress-test procedure
2026-08-04 19:16:27 +02:00

6.5 KiB
Raw Blame History

Testing - Rampart

Как тестировать: unit, integration, нагрузочное, DDoS simulation.


1. Unit тесты (Rust)

# Все тесты
cargo test

# Конкретный модуль
cargo test handshake
cargo test hmac
cargo test rate_limiter

# С выводом
cargo test -- --nocapture

# С профилированием
cargo test --release

Что тестировать

Модуль Happy path Error cases
VarInt parser обычный, короткий overflow, incomplete, >5 байт
MC Handshake vanilla, forge, hmac truncated, invalid utf8, wrong packet id
HMAC sign/verify правильный secret wrong secret, empty hostname, timing
Rate limiter under limit, reset over limit, burst, concurrent
Blacklist add/check/remove expired entry, duplicate add

Пример: VarInt

#[test]
fn test_varint_normal() {
    let buf = vec![0x00];
    assert_eq!(read_varint(&buf, 0).unwrap(), (0, 1));
}

#[test]
fn test_varint_max() {
    let buf = vec![0xFF, 0xFF, 0xFF, 0xFF, 0x07];
    assert_eq!(read_varint(&buf, 0).unwrap(), (i32::MAX, 5));
}

#[test]
fn test_varint_overflow() {
    let buf = vec![0xFF, 0xFF, 0xFF, 0xFF, 0x0F]; // > 5 байт
    assert!(matches!(read_varint(&buf, 0), Err(VarIntError::TooBig)));
}

#[test]
fn test_varint_incomplete() {
    let buf = vec![0x80]; // ждём ещё байты
    assert!(matches!(read_varint(&buf, 0), Err(VarIntError::Incomplete)));
}

2. Интеграционные тесты

# Требуют: docker compose up (redis, clickhouse)
cargo test --test integration

Что тестируем

#[tokio::test]
async fn test_full_flow() {
    // 1. Запускаем edge ноду (test config)
    // 2. Подключаемся Minecraft клиентом (через tokio::net::TcpStream)
    // 3. Шлём валидный handshake
    // 4. Проверяем что HMAC добавлен
    // 5. Проверяем что трафик проксирован до backend
}

#[tokio::test]
async fn test_blacklist_sync() {
    // 1. Добавляем IP в блэклист через Redis
    // 2. Проверяем что edge нода его подхватила
    // 3. Пытаемся подключиться с забаненного IP
    // 4. Проверяем что соединение отклонено
}

3. Fuzzing

// tests/fuzz/handshake.rs
#![no_main]

use libfuzzer_sys::fuzz_target;

fuzz_target!(|data: &[u8]| {
    // Должен крашиться на любой вход
    let _ = McHandshake::parse(data);
});
cargo install cargo-fuzz
cargo fuzz run handshake_parser

4. Нагрузочное тестирование

Базовый тест (tcpkali)

# Установка
cargo install tcpkali

# 50k новых соединений
tcpkali \
  --connections 1000 \
  --connect-rate 5000 \
  --duration 60s \
  EDGE_IP:25565

# 500 активных соединений с трафиком
tcpkali \
  --connections 500 \
  --connect-rate 100 \
  --duration 120s \
  --message-rate 1 \
  --message "$(xxd mc_handshake.bin)" \
  EDGE_IP:25565

SYN flood (hping3)

# Только на свои серверы!
hping3 -S --flood -p 25565 EDGE_IP

# С рандомным src IP
hping3 -S --flood -p 25565 --rand-source EDGE_IP

Реальные Minecraft боты (SoulFire)

java -jar SoulFire.jar \
  --target play.example.com:25565 \
  --amount 200 \
  --join-delay 50 \
  --protocol-version 765

5. DDoS simulation

# Сценарий 1: SYN flood
# Ожидание: XDP дропает, CPU < 30%
hping3 -S --flood -p 25565 EDGE_IP

# Сценарий 2: Handshake flood
# Ожидание: rate limit блокирует, CPU < 60%
for i in $(seq 1 1000); do
  (echo -n "$MC_HANDSHAKE" | nc -w1 EDGE_IP 25565) &
done

# Сценарий 3: Slowloris
# Ожидание: timeout 5 сек, соединение закрывается
while true; do
  echo -n -e '\x01' | nc -w 10 EDGE_IP 25565
done

# Сценарий 4: Fragmented handshake
# Ожидание: буферизация, успешный парсинг
# (отправляем handshake по 1 байту с задержкой 100ms)

Готовый много-IP стресс-тест на VDS (edge-only)

deploy/test/stress/ — полный цикл без Redis/Velocity/Paper: edge-контейнер с stub-бэкендом (socat echo) + attacker-контейнер со 100 source IP. Атака маскируется под обычный трафик (валидные handshake со случайными hostname), во время флуда параллельно заходят легитимные клиенты (legit.py), замеряющие RTT.

# На VDS
git clone https://github.com/loki5512344/rampart.git && cd rampart
cargo build --release --bin rampart-core
cp target/release/rampart-core deploy/test/stress/edge-ctx/rampart-core
cd deploy/test/stress && bash run-stress.sh

Фазы: A — сырая пропускная способность (лимиты 100k), B — защита (дефолт 5 pps/IP), C — SYN flood, D — активные соединения. Результаты прогона 2026-08-04 — в load-test-report.md.


6. CI Pipeline

# .github/workflows/test.yml
name: Test

on: [push, pull_request]

jobs:
  unit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: cargo test
      - run: cargo clippy -- -D warnings
      - run: cargo fmt --check

  integration:
    runs-on: ubuntu-latest
    services:
      redis:
        image: redis:7-alpine
        ports:
          - 6379:6379
    steps:
      - uses: actions/checkout@v4
      - run: cargo test --test integration

  fuzz:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: cargo fuzz run handshake_parser -- -runs=100000

  bench:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: cargo bench

7. Метрики качества

# Покрытие кода
cargo install cargo-tarpaulin
cargo tarpaulin --out Html
open tarpaulin-report.html

# Цели:
#   core/handshake.rs:  > 95%
#   core/hmac.rs:       > 90%
#   core/rate_limit:    > 85%
#   xdp/:               тесты в изолированной среде

Версия: 1.0 | Июль 2026