113 lines
6.9 KiB
Markdown
113 lines
6.9 KiB
Markdown
# Anti-torrent: ограничение числа соединений
|
||
|
||
Этот модуль — часть текущего production-контракта AWG2 Harness. Он вписывается в multi-orchestrator модель, потому что сервер выделенный, а бинарь уже владеет AWG2-owned network state вокруг Amnezia: `tc`, `ifb0`, lifecycle recovery и диагностика.
|
||
|
||
## 1. Цель
|
||
|
||
Не детектить BitTorrent как протокол. Цель проще: ограничить количество одновременных conntrack flows на один VPN peer IP. Торрент-клиенты обычно пытаются держать сотни TCP/UDP peer-сессий, DHT/uTP/trackers. Штатный baseline `500` сохраняет мягкий connection guard, не вмешиваясь в нормальный повседневный профиль по результатам эксплуатационных измерений проекта.
|
||
|
||
Это мягкий технический барьер, а не abuse-система со страйками.
|
||
|
||
## 2. Важное исправление к простой команде
|
||
|
||
Не использовать такую форму как production rule (это антипример; `200` здесь не default и не production-рекомендация):
|
||
|
||
```nft
|
||
nft add rule inet filter forward ip saddr 10.8.1.0/24 ct count over 200 drop
|
||
```
|
||
|
||
Проблемы:
|
||
|
||
1. Это может стать общим лимитом для всей подсети, а не лимитом на каждого клиента.
|
||
2. Нет ownership: правило кладётся в generic `inet filter forward`, который может принадлежать не нашему пакету.
|
||
3. Неочевидно, в каком network namespace оно применяется.
|
||
4. Нет named counter и нормальной диагностики.
|
||
|
||
Нужен per-source key через meter/set и отдельная таблица, которой владеет только AWG2 Harness.
|
||
|
||
## 3. Рекомендуемая форма правила nftables
|
||
|
||
Правило должно применяться в том же network namespace, где живёт Amnezia AWG/WG interface и где уже применяются `tc`/`ifb0` rules. На практике это namespace контейнера Amnezia, полученный через `/proc/<container_pid>/ns/net`.
|
||
|
||
```nft
|
||
table inet awg2_harness {
|
||
counter antitorrent_dropped_v4 {}
|
||
|
||
chain forward_antitorrent {
|
||
type filter hook forward priority filter; policy accept;
|
||
|
||
ip saddr <peer_ipv4_cidr> ct state new \
|
||
meter awg2_peer_connlimit_v4 { ip saddr ct count over <max_connections_per_peer> } \
|
||
counter name antitorrent_dropped_v4 \
|
||
drop
|
||
}
|
||
}
|
||
```
|
||
|
||
Пример для текущей production-подсети:
|
||
|
||
```nft
|
||
table inet awg2_harness {
|
||
counter antitorrent_dropped_v4 {}
|
||
|
||
chain forward_antitorrent {
|
||
type filter hook forward priority filter; policy accept;
|
||
|
||
ip saddr 10.8.1.0/24 ct state new \
|
||
meter awg2_peer_connlimit_v4 { ip saddr ct count over 500 } \
|
||
counter name antitorrent_dropped_v4 \
|
||
drop
|
||
}
|
||
}
|
||
```
|
||
|
||
`ct state new` важен: ограничиваются новые flow attempts сверх порога, а уже установленные flows не начинают внезапно дропаться только потому, что счётчик стал высоким.
|
||
|
||
## 4. Порог
|
||
|
||
Рекомендуемый стартовый production baseline:
|
||
|
||
```toml
|
||
[anti_torrent]
|
||
enabled = true
|
||
max_connections_per_peer = 500
|
||
```
|
||
|
||
`500` — production baseline, выбранный по прикладным и нагрузочным измерениям проекта. Connection guard остаётся включённым, но порог не должен мешать обычному browsing/mobile/application traffic. Любое значение ниже `500` является более агрессивной операторской политикой и требует отдельной проверки на реальных клиентах. Значение остаётся конфигурируемым и не зашито в алгоритм.
|
||
|
||
## 5. Почему это должно быть в orchestrator
|
||
|
||
Модуль должен жить в Rust-бинаре, а не отдельным ручным правилом, потому что orchestrator должен:
|
||
|
||
- применять правило после container restart/update, когда network namespace изменился;
|
||
- проверять actual state и чинить drift;
|
||
- показывать status/counters;
|
||
- не ломать unrelated nftables/Docker/Amnezia rules;
|
||
- удалять или отключать только owned state при `enabled = false`.
|
||
|
||
## 6. Conntrack и производительность
|
||
|
||
`ct count` использует conntrack. Для примера 23 peers × 500 flows дают до 11 500 потенциальных flow slots перед ограничением каждого peer. Само по себе это не является доказательством достаточной ёмкости конкретного хоста, поэтому фактическое состояние conntrack обязательно наблюдается.
|
||
|
||
Что надо мониторить:
|
||
|
||
```bash
|
||
sysctl net.netfilter.nf_conntrack_count
|
||
sysctl net.netfilter.nf_conntrack_max
|
||
nft list table inet awg2_harness
|
||
```
|
||
|
||
Если `nf_conntrack_count` приближается к `nf_conntrack_max`, проблема уже системная: надо разбираться с timeout, abuse или capacity. `awg2-harness status` показывает оба значения и вычисленный `nf_conntrack_utilization`, чтобы давление было видно без ручного деления. Не надо автоматически увеличивать `nf_conntrack_max` из orchestrator без отдельного решения.
|
||
|
||
## 7. Критерии приёмки
|
||
|
||
- В правильном Amnezia netns существует `table inet awg2_harness`.
|
||
- В таблице есть `chain forward_antitorrent` с hook `forward`.
|
||
- Правило ограничивает `ip saddr <peer_ipv4_cidr>`.
|
||
- Лимит применяется per source VPN IP, а не глобально на всю подсеть.
|
||
- Drop counter растёт при превышении threshold.
|
||
- `status` показывает count/max/utilization conntrack, если эти sysctl доступны.
|
||
- Нормальные сценарии с числом flows ниже threshold не затрагиваются.
|
||
- При restart контейнера правило пересоздаётся в новом netns.
|
||
- При `anti_torrent.enabled = false` удаляется или отключается только AWG2-owned nftables state.
|