Files
AWG2_harness/docs/ANTI_TORRENT.md
T

6.2 KiB
Raw Blame History

Anti-torrent connection-count guard

Этот модуль — часть текущего 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. Лимит в диапазоне 100–250 одновременных flows заметно ухудшает P2P-поведение, но почти не затрагивает обычные сценарии при корректной настройке.

Это мягкий технический барьер, а не abuse-система со страйками.

2. Важное исправление к простой команде

Не использовать такую форму как production rule (это антипример; 200 здесь не default и не production-рекомендация):

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.

Правило должно применяться в том же network namespace, где живёт Amnezia AWG/WG interface и где уже применяются tc/ifb0 rules. На практике это namespace контейнера Amnezia, полученный через /proc/<container_pid>/ns/net.

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-подсети:

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 100 } \
      counter name antitorrent_dropped_v4 \
      drop
  }
}

ct state new важен: ограничиваются новые flow attempts сверх порога, а уже установленные flows не начинают внезапно дропаться только потому, что счётчик стал высоким.

4. Threshold

Рекомендуемый стартовый production baseline:

[anti_torrent]
enabled = true
max_connections_per_peer = 150

Практические варианты:

  • 100 — более строгий режим.
  • 150 — текущий рекомендуемый стартовый baseline, мягче к обычному browsing/mobile traffic.
  • 200/250 — ещё более permissive варианты.
  • 70 — агрессивный режим только после наблюдения реального трафика.

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 × 100 flows = около 2300 активных flows до ограничения. Это не выглядит опасно для production-хоста само по себе.

Что надо мониторить:

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. Не надо автоматически увеличивать nf_conntrack_max из orchestrator без отдельного решения.

7. Acceptance criteria

  • В правильном Amnezia netns существует table inet awg2_harness.
  • В таблице есть chain forward_antitorrent с hook forward.
  • Правило ограничивает ip saddr <peer_ipv4_cidr>.
  • Лимит применяется per source VPN IP, а не глобально на всю подсеть.
  • Drop counter растёт при превышении threshold.
  • Нормальные сценарии с числом flows ниже threshold не затрагиваются.
  • При restart контейнера правило пересоздаётся в новом netns.
  • При anti_torrent.enabled = false удаляется или отключается только AWG2-owned nftables state.