Initial commit: Rampart v0.2.0
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
This commit is contained in:
commit
cf9608ce5d
159 changed files with 15341 additions and 0 deletions
337
docs/research/networking.md
Normal file
337
docs/research/networking.md
Normal file
|
|
@ -0,0 +1,337 @@
|
|||
# Networking - WireGuard, BGP Anycast, QUIC, MTU
|
||||
|
||||
> Актуально: v0.1+ (WireGuard), v0.5+ (BGP), v0.4+ (QUIC)
|
||||
|
||||
---
|
||||
|
||||
## WireGuard - hub-and-spoke (v0.1-v0.3)
|
||||
|
||||
### Адресация
|
||||
|
||||
```
|
||||
10.0.0.1 Manager + Redis + NATS (главный дедик)
|
||||
10.0.0.2-21 Velocity 1-20
|
||||
10.0.1.1-100 Hub 1-100
|
||||
10.0.2.x Survival серверы
|
||||
10.0.3.x Skyblock серверы
|
||||
10.0.100.x Edge ноды (EU, US, AS...)
|
||||
```
|
||||
|
||||
### Конфиг Manager ноды (Hub)
|
||||
|
||||
```ini
|
||||
# /etc/wireguard/wg0.conf
|
||||
|
||||
[Interface]
|
||||
Address = 10.0.0.1/16
|
||||
PrivateKey = <MANAGER_PRIVATE_KEY>
|
||||
ListenPort = 51820
|
||||
|
||||
# Edge нода EU
|
||||
[Peer]
|
||||
PublicKey = <EDGE_EU_PUBLIC_KEY>
|
||||
AllowedIPs = 10.0.100.1/32
|
||||
|
||||
# Edge нода US
|
||||
[Peer]
|
||||
PublicKey = <EDGE_US_PUBLIC_KEY>
|
||||
AllowedIPs = 10.0.100.2/32
|
||||
|
||||
# Velocity 1
|
||||
[Peer]
|
||||
PublicKey = <VEL1_PUBLIC_KEY>
|
||||
AllowedIPs = 10.0.0.2/32
|
||||
|
||||
# Hub 1
|
||||
[Peer]
|
||||
PublicKey = <HUB1_PUBLIC_KEY>
|
||||
AllowedIPs = 10.0.1.1/32
|
||||
|
||||
# ... и так для каждой ноды
|
||||
```
|
||||
|
||||
### Конфиг Spoke ноды (edge, velocity, hub, game server)
|
||||
|
||||
```ini
|
||||
# /etc/wireguard/wg0.conf на любой spoke ноде
|
||||
|
||||
[Interface]
|
||||
Address = 10.0.100.1/32 # свой адрес в mesh
|
||||
PrivateKey = <THIS_NODE_PRIVATE_KEY>
|
||||
|
||||
# Только один пир - Manager (Hub)
|
||||
[Peer]
|
||||
PublicKey = <MANAGER_PUBLIC_KEY>
|
||||
Endpoint = <MANAGER_PUBLIC_IP>:51820
|
||||
AllowedIPs = 10.0.0.0/16 # весь internal диапазон через hub
|
||||
PersistentKeepalive = 25 # держим туннель через NAT
|
||||
```
|
||||
|
||||
### Авто-генерация конфигов через CLI
|
||||
|
||||
```bash
|
||||
# rampart CLI генерирует wg конфиги для всех нод
|
||||
|
||||
rampart wg init --network 10.0.0.0/16 --hub 185.200.100.1
|
||||
rampart wg add-node --role edge --name edge-eu-1 --public-ip 45.200.10.1
|
||||
rampart wg add-node --role velocity --name vel-1
|
||||
rampart wg add-node --role hub --name hub-1
|
||||
|
||||
# Генерирует файлы:
|
||||
# wg-configs/edge-eu-1/wg0.conf
|
||||
# wg-configs/vel-1/wg0.conf
|
||||
# ...
|
||||
|
||||
# Деплой на ноду
|
||||
scp wg-configs/edge-eu-1/wg0.conf root@45.200.10.1:/etc/wireguard/
|
||||
ssh root@45.200.10.1 'systemctl enable --now wg-quick@wg0'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## MTU - важный нюанс
|
||||
|
||||
```
|
||||
Стандартный MTU Ethernet: 1500 байт
|
||||
WireGuard overhead: ~80 байт (заголовок + шифрование)
|
||||
Effective MTU в WG туннеле: 1420 байт
|
||||
|
||||
Если Minecraft пакет > 1420 байт → фрагментация → производительность падает.
|
||||
|
||||
Minecraft пакеты:
|
||||
Handshake: ~50-300 байт ✅ (безопасно)
|
||||
LoginStart: ~30-50 байт ✅
|
||||
Chunk Data: может быть > 1420 байт ⚠️
|
||||
|
||||
Для chunk data: MC клиент и сервер обрабатывают фрагментацию на уровне TCP.
|
||||
Для нашего edge проксирования: мы просто туннелируем TCP стрим,
|
||||
фрагментация прозрачна. Проблем нет.
|
||||
|
||||
Настройка MTU:
|
||||
```
|
||||
|
||||
```ini
|
||||
# /etc/wireguard/wg0.conf
|
||||
[Interface]
|
||||
MTU = 1420 # явно указываем чтобы не было auto-discovery проблем
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Firewall - полный набор правил
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# /etc/rampart/firewall.sh
|
||||
|
||||
# ── Edge нода ──
|
||||
setup_edge_firewall() {
|
||||
iptables -F INPUT
|
||||
iptables -F FORWARD
|
||||
iptables -P INPUT DROP
|
||||
iptables -P FORWARD DROP
|
||||
|
||||
# Localhost
|
||||
iptables -A INPUT -i lo -j ACCEPT
|
||||
|
||||
# Established соединения
|
||||
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
|
||||
|
||||
# WireGuard
|
||||
iptables -A INPUT -p udp --dport 51820 -j ACCEPT
|
||||
|
||||
# Minecraft от всех (мы принимаем атаки здесь и фильтруем)
|
||||
iptables -A INPUT -p tcp --dport 25565 -j ACCEPT
|
||||
|
||||
# SSH (только с нашего IP управления)
|
||||
iptables -A INPUT -p tcp --dport 22 -s ${MGMT_IP} -j ACCEPT
|
||||
|
||||
# Prometheus от Manager
|
||||
iptables -A INPUT -p tcp --dport 9090 -s 10.0.0.1 -j ACCEPT
|
||||
|
||||
# HAProxy stats (для Prometheus)
|
||||
iptables -A INPUT -p tcp --dport 8404 -s 10.0.0.0/16 -j ACCEPT
|
||||
|
||||
# Всё остальное - дроп
|
||||
iptables -A INPUT -j DROP
|
||||
}
|
||||
|
||||
# ── Velocity / HAProxy нода ──
|
||||
setup_backend_firewall() {
|
||||
iptables -F INPUT
|
||||
iptables -P INPUT DROP
|
||||
|
||||
iptables -A INPUT -i lo -j ACCEPT
|
||||
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
|
||||
|
||||
# WireGuard
|
||||
iptables -A INPUT -p udp --dport 51820 -j ACCEPT
|
||||
|
||||
# Minecraft только от edge нод через WireGuard
|
||||
iptables -A INPUT -i wg0 -p tcp --dport 25565 -s 10.0.100.0/24 -j ACCEPT
|
||||
|
||||
# SSH
|
||||
iptables -A INPUT -p tcp --dport 22 -s ${MGMT_IP} -j ACCEPT
|
||||
|
||||
# Prometheus сервисы (внутри WG)
|
||||
iptables -A INPUT -p tcp --dport 9091 -s 10.0.0.0/16 -j ACCEPT
|
||||
|
||||
iptables -A INPUT -j DROP
|
||||
}
|
||||
|
||||
# ── Game сервер ──
|
||||
setup_game_firewall() {
|
||||
iptables -F INPUT
|
||||
iptables -P INPUT DROP
|
||||
|
||||
iptables -A INPUT -i lo -j ACCEPT
|
||||
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
|
||||
|
||||
# WireGuard
|
||||
iptables -A INPUT -p udp --dport 51820 -j ACCEPT
|
||||
|
||||
# Minecraft только от Velocity нод
|
||||
iptables -A INPUT -i wg0 -p tcp --dport 25565 -s 10.0.0.2/28 -j ACCEPT
|
||||
|
||||
# SSH
|
||||
iptables -A INPUT -p tcp --dport 22 -s ${MGMT_IP} -j ACCEPT
|
||||
|
||||
# Prometheus метрики Paper
|
||||
iptables -A INPUT -p tcp --dport 9092 -s 10.0.0.0/16 -j ACCEPT
|
||||
|
||||
iptables -A INPUT -j DROP
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## QUIC - канал Edge ↔ Manager (v0.4+)
|
||||
|
||||
### Зачем для управляющего канала
|
||||
|
||||
```
|
||||
TCP проблема: Head-of-line blocking
|
||||
Большой blacklist update → блокирует heartbeat → edge думает что manager упал
|
||||
|
||||
QUIC решение: независимые streams
|
||||
Stream 0: heartbeat (5 сек) - не блокируется
|
||||
Stream 1: blacklist updates (push) - независимо
|
||||
Stream 2: metrics (1 сек) - независимо
|
||||
Stream 3: команды (drain/reload) - независимо
|
||||
|
||||
+ 0-RTT reconnect после разрыва (важно для мобильных VDS с нестабильным uplink)
|
||||
+ Встроенный TLS 1.3 (не нужен отдельный слой)
|
||||
```
|
||||
|
||||
### Реализация (quinn)
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
quinn = "0.11"
|
||||
```
|
||||
|
||||
```rust
|
||||
// manager/src/quic.rs
|
||||
|
||||
pub async fn start_quic_server(config: Arc<Config>) -> Result<()> {
|
||||
let tls = build_quic_server_tls(&config.tls);
|
||||
let endpoint = quinn::Endpoint::server(tls, "0.0.0.0:7777".parse()?)?;
|
||||
|
||||
while let Some(incoming) = endpoint.accept().await {
|
||||
let conn = incoming.await?;
|
||||
|
||||
// Получаем identity подключившейся edge ноды из сертификата
|
||||
let node_id = extract_node_id(&conn);
|
||||
tokio::spawn(handle_edge(conn, node_id));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn handle_edge(conn: quinn::Connection, node_id: String) {
|
||||
// Открываем исходящие streams для push уведомлений
|
||||
let blacklist_tx = conn.open_uni().await.unwrap();
|
||||
|
||||
// Слушаем входящие streams (heartbeat, metrics)
|
||||
loop {
|
||||
match conn.accept_bi().await {
|
||||
Ok((tx, rx)) => {
|
||||
tokio::spawn(handle_stream(tx, rx, node_id.clone()));
|
||||
}
|
||||
Err(_) => {
|
||||
tracing::warn!("Edge нода {} отключилась", node_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## BGP Anycast (v0.6+)
|
||||
|
||||
> Только если проект вырастет до 10+ edge нод и нужен настоящий anycast.
|
||||
|
||||
### Что нужно
|
||||
|
||||
```
|
||||
1. Свой AS номер - получить через RIPE NCC (Европа) или ARIN (США)
|
||||
Стоимость: ~500€/год членский взнос в RIPE
|
||||
Плюс: купить через LIR (Local Internet Registry) - дешевле
|
||||
|
||||
2. Своя /24 подсеть - 256 IP адресов
|
||||
Получить вместе с AS через RIPE
|
||||
Стоимость: включено в RIPE членство
|
||||
|
||||
3. VDS с поддержкой BGP сессий
|
||||
Vultr, Hetzner (не все локации), Leaseweb, OVH Premium
|
||||
Проверять явно: "BGP sessions supported"
|
||||
|
||||
4. FRRouting на каждой edge ноде
|
||||
```
|
||||
|
||||
### FRRouting конфиг
|
||||
|
||||
```ini
|
||||
# /etc/frr/frr.conf на edge ноде
|
||||
|
||||
router bgp 65001
|
||||
bgp router-id 185.200.100.1
|
||||
|
||||
# BGP сессия с upstream провайдером
|
||||
neighbor 149.248.2.1 remote-as 20473
|
||||
neighbor 149.248.2.1 description "Vultr upstream"
|
||||
|
||||
address-family ipv4 unicast
|
||||
# Анонсируем свою подсеть с этой edge ноды
|
||||
network 185.200.100.0/24
|
||||
|
||||
# NO_EXPORT - не распространяем анонс дальше (только к upstream)
|
||||
neighbor 149.248.2.1 route-map SET_COMMUNITY out
|
||||
exit-address-family
|
||||
|
||||
route-map SET_COMMUNITY permit 10
|
||||
set community no-export
|
||||
|
||||
! Когда edge нода падает - FRRouting перестаёт анонсировать
|
||||
! BGP withdraw → трафик автоматически идёт на другую ноду
|
||||
! Время failover: ~30-60 сек (BGP convergence)
|
||||
```
|
||||
|
||||
### Как это работает
|
||||
|
||||
```
|
||||
play.server.com → 185.200.100.1 (один IP, твоя подсеть)
|
||||
|
||||
Игрок из Европы:
|
||||
BGP → ближайшая нода которая анонсирует 185.200.100.0/24 → edge-eu-1
|
||||
|
||||
Игрок из США:
|
||||
BGP → ближайшая нода → edge-us-1
|
||||
|
||||
edge-eu-1 упала → FRRouting делает withdraw →
|
||||
Европейский трафик → автоматически → edge-us-1 или edge-as-1
|
||||
Время: 30-60 сек
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue