Multi-layer DDoS protection for Minecraft servers. - rampart-core: Edge node with XDP/eBPF + Rust L7 filtering - rampart-manager: REST API with JWT auth, Redis sync - rampart-cli: CLI tool for operators - velocity-plugin: Domain check, HMAC verify, server registry, load balancer - paper-plugin: Auto-registration, heartbeat, HMAC verify - dashboard: React + Vite web UI for management
275 lines
8.3 KiB
Markdown
275 lines
8.3 KiB
Markdown
# Benchmark - Инструменты и методология
|
||
|
||
> Актуально: v0.3+
|
||
|
||
---
|
||
|
||
## Инструменты
|
||
|
||
| Инструмент | Что измеряет | Когда |
|
||
|---|---|---|
|
||
| **tcpkali** | TCP conn/sec, throughput | Основной benchmark |
|
||
| **SoulFire** | Реальные MC боты (Fabric код) | Anti-bot тест |
|
||
| **BotMark** | Быстрые MC handshake | Handshake throughput |
|
||
| **hping3** | SYN flood | XDP тест |
|
||
| **pktgen** | Max pps (kernel module) | XDP верхний предел |
|
||
| **iperf3** | Bandwidth | Throughput VDS |
|
||
| **cargo bench** | Rust unit benchmarks | Парсер, HMAC, rate limit |
|
||
|
||
---
|
||
|
||
## Методология
|
||
|
||
### Правила честного бенчмарка
|
||
|
||
```
|
||
1. Изолированная среда - никаких фоновых процессов
|
||
2. Прогрев (warm-up) - первые 10 сек не считаются
|
||
3. Несколько прогонов - минимум 3, берём медиану
|
||
4. Одна переменная - меняем одно за раз
|
||
5. Фиксируем конфигурацию - версия ядра, CPU, RAM, NIC
|
||
6. Не на той же машине - источник нагрузки на отдельном VDS
|
||
```
|
||
|
||
### Конфигурация тестового стенда
|
||
|
||
```
|
||
Тестируемый (edge нода):
|
||
VDS: Hetzner CX31 (4 vCPU, 8GB, 1Gbps, KVM)
|
||
OS: Ubuntu 22.04 LTS
|
||
Kernel: 5.15.x
|
||
NIC: virtio (XDP generic mode)
|
||
|
||
Источник нагрузки (отдельный VDS в той же сети):
|
||
VDS: Hetzner CX21 (2 vCPU, 4GB, 1Gbps)
|
||
|
||
Измеряем:
|
||
CPU edge ноды: htop / top
|
||
Память: /proc/meminfo
|
||
Connections: ss -s
|
||
Latency: tcpkali --latency-percentiles
|
||
```
|
||
|
||
---
|
||
|
||
## tcpkali - основной инструмент
|
||
|
||
```bash
|
||
# Установка
|
||
cargo install tcpkali # или apt install tcpkali
|
||
|
||
# Тест 1: новых соединений/сек
|
||
tcpkali \
|
||
--connections 1000 \
|
||
--connect-rate 5000 \ # 5000 новых conn/сек
|
||
--duration 30s \
|
||
--message-rate 0 \ # без данных - только коннект
|
||
TARGET_IP:25565
|
||
|
||
# Тест 2: активные соединения + трафик
|
||
tcpkali \
|
||
--connections 50000 \ # 50k одновременно
|
||
--connect-rate 1000 \
|
||
--duration 60s \
|
||
--message-rate 1 \ # 1 msg/сек от каждого
|
||
--message "$(cat mc_handshake.bin)" \
|
||
TARGET_IP:25565
|
||
|
||
# Тест 3: latency percentiles
|
||
tcpkali \
|
||
--connections 1000 \
|
||
--connect-rate 500 \
|
||
--duration 30s \
|
||
--latency-connect \ # измеряем latency до connect
|
||
--latency-percentiles 50,95,99,99.9 \
|
||
TARGET_IP:25565
|
||
```
|
||
|
||
---
|
||
|
||
## SoulFire - реальные MC боты
|
||
|
||
```bash
|
||
# SoulFire запускает настоящий Fabric MC клиент
|
||
# Боты ведут себя как реальные игроки на уровне протокола
|
||
|
||
# Скачать: github.com/AlexProgrammerDE/SoulFire
|
||
java -jar SoulFire.jar \
|
||
--target play.server.com:25565 \
|
||
--amount 500 \ # 500 ботов
|
||
--join-delay 100 \ # 100мс между подключениями
|
||
--protocol-version 765 # MC 1.20.4
|
||
```
|
||
|
||
---
|
||
|
||
## hping3 - SYN flood
|
||
|
||
```bash
|
||
# ТОЛЬКО для тестирования своих серверов!
|
||
# Запускать с отдельного VDS
|
||
|
||
# SYN flood
|
||
hping3 -S --flood -p 25565 TARGET_IP
|
||
|
||
# С рандомным src IP (проверяем uRPF)
|
||
hping3 -S --flood -p 25565 --rand-source TARGET_IP
|
||
|
||
# Смотрим на XDP счётчики
|
||
watch -n 1 'cat /sys/kernel/debug/tracing/trace_pipe'
|
||
# или через наш /metrics endpoint
|
||
curl http://TARGET_IP:9090/metrics | grep xdp_drops
|
||
```
|
||
|
||
---
|
||
|
||
## Rust unit benchmarks
|
||
|
||
```toml
|
||
# Cargo.toml
|
||
[dev-dependencies]
|
||
criterion = { version = "0.5", features = ["html_reports"] }
|
||
|
||
[[bench]]
|
||
name = "core_benchmarks"
|
||
harness = false
|
||
```
|
||
|
||
```rust
|
||
// benches/core_benchmarks.rs
|
||
use criterion::{black_box, criterion_group, criterion_main, Criterion, BenchmarkId};
|
||
|
||
fn bench_handshake_parse(c: &mut Criterion) {
|
||
let mut group = c.benchmark_group("handshake_parse");
|
||
|
||
// Разные варианты hostname
|
||
let cases = vec![
|
||
("vanilla", build_handshake("play.server.com", 765, 2)),
|
||
("forge", build_handshake("play.server.com\0FML2\0", 765, 2)),
|
||
("hmac", build_handshake("play.server.com\0shield\0abcdef", 765, 2)),
|
||
];
|
||
|
||
for (name, packet) in &cases {
|
||
group.bench_with_input(BenchmarkId::new("parse", name), packet, |b, p| {
|
||
b.iter(|| McHandshake::parse(black_box(p)))
|
||
});
|
||
}
|
||
group.finish();
|
||
}
|
||
|
||
fn bench_hmac(c: &mut Criterion) {
|
||
let secret = b"test_secret_32_bytes_long_here!!";
|
||
let hostname = "play.server.com";
|
||
let signed = sign_hostname(hostname, secret);
|
||
|
||
let mut group = c.benchmark_group("hmac");
|
||
group.bench_function("sign", |b| {
|
||
b.iter(|| sign_hostname(black_box(hostname), secret))
|
||
});
|
||
group.bench_function("verify", |b| {
|
||
b.iter(|| verify_hostname(black_box(&signed), secret))
|
||
});
|
||
group.finish();
|
||
}
|
||
|
||
fn bench_rate_limiter(c: &mut Criterion) {
|
||
let rt = tokio::runtime::Runtime::new().unwrap();
|
||
let limiter = RateLimiter::new(100, 10.0);
|
||
let ips: Vec<IpAddr> = (0..1000u32)
|
||
.map(|i| IpAddr::V4(Ipv4Addr::from(i)))
|
||
.collect();
|
||
|
||
c.bench_function("rate_limit_check", |b| {
|
||
b.to_async(&rt).iter(|| async {
|
||
let ip = ips[fastrand::usize(..ips.len())];
|
||
limiter.check(black_box(ip)).await
|
||
})
|
||
});
|
||
}
|
||
|
||
criterion_group!(benches, bench_handshake_parse, bench_hmac, bench_rate_limiter);
|
||
criterion_main!(benches);
|
||
```
|
||
|
||
```bash
|
||
# Запуск
|
||
cargo bench
|
||
|
||
# HTML отчёт в target/criterion/
|
||
open target/criterion/report/index.html
|
||
```
|
||
|
||
---
|
||
|
||
> ⚠️ **Важное уточнение:** Цифры 110k conn/s - для **synthetic echo benchmark** (простое прокси без L7 парсинга).
|
||
> Реальная производительность Rampart (handshake парсинг + HMAC + DashMap + rate limit) на 4 vCPU:
|
||
> - **~60-70k conn/s** (реалистично для v0.1-v0.3 на epoll)
|
||
> - **~85-95k conn/s** (с io_uring)
|
||
>
|
||
> Для простого TCP proxy без L7 логики - 110k+.
|
||
> Для точных цифр - прогони `cargo bench` на своём железе.
|
||
|
||
## Ожидаемые результаты (Hetzner CX31, 4 vCPU)
|
||
|
||
```
|
||
Unit benchmarks:
|
||
handshake_parse (vanilla): ~160 ns → 6.2M парсингов/сек
|
||
handshake_parse (forge): ~180 ns → 5.5M парсингов/сек
|
||
hmac_sign: ~820 ns → 1.2M подписей/сек
|
||
hmac_verify: ~840 ns → 1.2M верификаций/сек
|
||
rate_limit_check: ~220 ns → 4.5M проверок/сек
|
||
|
||
Системные (epoll / tokio):
|
||
Новых соединений/сек: ~80,000
|
||
Активных соединений: ~200,000
|
||
CPU при 80k conn/s: ~65%
|
||
|
||
Системные (io_uring):
|
||
Новых соединений/сек: ~110,000 (+37%)
|
||
Активных соединений: ~260,000
|
||
CPU при 110k conn/s: ~48%
|
||
|
||
XDP (generic mode на virtio):
|
||
Drop rate: ~3-5M pps
|
||
CPU при 3M pps: ~25%
|
||
|
||
XDP (native, bare metal):
|
||
Drop rate: ~15-20M pps
|
||
CPU при 10M pps: ~15%
|
||
```
|
||
|
||
### Таблица для README
|
||
|
||
```markdown
|
||
## Performance
|
||
|
||
Tested on Hetzner CX31 (4 vCPU, 8GB, KVM), Ubuntu 22.04, kernel 5.15
|
||
|
||
| Mode | New conn/s | Active conn | CPU |
|
||
|---|---|---|---|
|
||
| 1 core, epoll | 20k | 50k | ~100% |
|
||
| 4 core, epoll | 80k | 200k | ~65% |
|
||
| 4 core, io_uring | 110k | 260k | ~48% |
|
||
| XDP drop (generic) | 3-5M pps | - | ~25% |
|
||
| XDP drop (native) | 15-20M pps | - | ~15% |
|
||
```
|
||
|
||
---
|
||
|
||
## Профилирование под нагрузкой
|
||
|
||
```bash
|
||
# 1. Запускаем нагрузку
|
||
tcpkali --connections 50000 --connect-rate 5000 --duration 300s TARGET:25565 &
|
||
|
||
# 2. Пока идёт нагрузка - снимаем профиль CPU
|
||
perf record -g -p $(pgrep rampart-edge) -- sleep 30
|
||
perf report --stdio | head -100
|
||
|
||
# 3. Flamegraph
|
||
cargo flamegraph --pid $(pgrep rampart-edge) --output flamegraph.svg
|
||
open flamegraph.svg
|
||
|
||
# 4. tokio-console - смотрим какие async tasks тормозят
|
||
tokio-console http://TARGET:6669
|
||
```
|