implant rate-limit

Subcomando para limitar conexões + rate de novas conexões por IP via iptables (módulos connlimit e hashlimit). Cria chains dedicadas isoladas do INPUT do operador.

Pack default

implant rate-limit apply aplica:

Porta/Proto max-conn (ESTABLISHED) max-new (NEW)
SSH (porta detectada) 20 5/minute
HTTP/80 50 200/minute
HTTPS/443 50 200/minute
ICMP — 5/second

Whitelist (bypassa o rate-limit)

  • IPs de security.trusted_ips no config.toml
  • 127.0.0.1 + ::1 (loopback)
  • IP da conexão SSH atual, detectado em apply (desligável com security.whitelist_current_ssh_ip = false)
  • IPs custom via whitelist-ip (ou implant ssh-key --whitelist-ip)

Backend ipset

A whitelist e a blocklist vivem em ipsets nativos em vez de regras iptables individuais. Lookup O(1) por IP, suporta milhões de entries, TTL nativo por entry.

Ipsets criados pelo apply:

Set Family Max Default TTL
IMPLANT_RL_WHITELIST inet 65536 0 (permanente)
IMPLANT_RL_WHITELIST6 inet6 65536 0
IMPLANT_RL_BLOCKLIST inet 1048576 0 (per-entry override)
IMPLANT_RL_BLOCKLIST6 inet6 1048576 0

Persistência: os sets são salvos em /etc/iptables/ipsets após cada mutação. Para que sejam restaurados no boot (antes das regras que os referenciam), instale a unit de restore com implant firewall-restore install, ou deixe o reconcile instalar: desde a v2.58.0 ele instala (ou atualiza) a unit sozinho, com guarda. O apply só devolve boot_restore_advice, e o check reprova o item "Boot-survival do firewall" enquanto ela faltar. Ver firewall-restore.

Persistência das regras (`rules_persist_warning`)

Os sets voltam pela unit; as regras (ganchos e chains do rate-limit) voltam pelo netfilter-persistent, a partir de /etc/iptables/rules.v4, que o rate-limit grava com netfilter-persistent save. Desde a v2.59.0, quando o mecanismo não está disponível — netfilter-persistent ausente, ou presente sem o plugin do iptables-persistent (o save saía 0 sem gravar nada) — o rate-limit não falha nem fica calado:

  • avisa no stderr que as regras não foram persistidas e valem só até o próximo reboot;
  • responde rules_persist_warning (texto com a causa) no JSON de apply, revert, reconcile e status. Sem o campo, nada a avisar.

Se a ferramenta está presente e o save falha, o erro traz a saída do comando. Nem --auto-fix instala o mecanismo: instalar o pacote ufw remove o iptables-persistent e o netfilter-persistent no apt, e reinstalá-los remove o UFW. O check "Boot-survival do firewall" do hardening reprova pelo mesmo motivo.

Desde a v2.61.0, sem o netfilter-persistent a unit firewall-restore atual reaplica o rate-limit no boot a partir do state, e o aviso deixa de valer quando ela está instalada e em dia. O save grava o arquivo sem as regras do Docker (ver iptables save).

Migração de state antigo (iptables raw → ipset)

Hosts com rate-limit aplicado por versões muito antigas (state schema 1.0, whitelist em regras iptables individuais) precisam:

sudo implant rate-limit migrate-to-ipset

Faz snapshot do iptables antes (anti-tijolar). Cria os 4 ipsets, popula whitelist com IPs do state atual, re-aplica chains, persiste, bumpa state para 2.0. Idempotente (erro se já em 2.0).

Instalações novas já usam ipset — migrate-to-ipset não é necessário.

Bulk-import — formatos aceitos

block-list-from-file e whitelist-list-from-file auto-detectam:

Formato Heurística Exemplo
JSON array começa com [ ["203.0.113.4", "198.51.100.0/24"]
CSV linha 1 não-comentário tem , ip,name\n203.0.113.4,attacker
Text plain resto 1 IP por linha, # comentário

Mostra preview (formato, válidos, inválidos, até 5 amostras de erro) e pede confirmação [s/N]. --yes skipa o prompt. --ttl N aplica o mesmo TTL a todos os IPs do arquivo (apenas no block-list).

Topologia

Precedência única dos ganchos do implant, na INPUT e na DOCKER-USER: whitelist > blocklist > feed-block > geo-block > rate-limit. A posição de cada gancho é calculada sobre a chain real (iptables -S), então a ordem é a mesma independentemente de qual feature foi aplicada primeiro.

INPUT: -j IMPLANT_RATELIMIT_WHITELIST                      (ACCEPT se em whitelist)
INPUT: -m set --match-set IMPLANT_RL_BLOCKLIST src -j DROP (blocklist)
INPUT: -j IMPLANT_FEED_IN                                  (se feed-block aplicado)
INPUT: -j IMPLANT_GEO_IN                                   (se geo-block aplicado)
INPUT: -j IMPLANT_RATELIMIT                                (rate-limit pela regra)

IP isento (whitelist) vale acima da blocklist: quem foi isentado não é derrubado por um ban automático. Na DOCKER-USER, os sets de whitelist/allowlist dão RETURN antes do DROP da blocklist.

O feed-block (v2.60.0+) entra depois da blocklist — o ban do operador é o julgamento mais específico, e é o contador dele que o auto-ban lê — e antes do geo-block, para o DROP ficar contado como "feed". As chains do feed e do geo repetem o RETURN da whitelist (IMPLANT_RL_WHITELIST e IMPLANT_AB_ALLOW), então rate-limit whitelist-ip isenta também do feed, mesmo sem o rate-limit aplicado.

Este rate-limit é L4 (iptables, por porta). Para limitar requisições HTTP por IP no Traefik, veja traefik-ratelimit.

Os DROPs do rate-limit passam pela chain IMPLANT_RL_DROP (ver drop-log abaixo).

Portas publicadas pelo Docker

Tráfego para portas publicadas pelo Docker não passa pela INPUT. Para limitar essas portas, use --docker <porta> (porta do lado do host):

sudo implant rate-limit add --docker 8080 --max-conn 50 --max-new 100/minute
sudo implant rate-limit remove --docker 8080

A regra vai para a chain IMPLANT_RL_FWD, saltada a partir da DOCKER-USER, casando --ctstate NEW e --ctstate DNAT --ctorigdstport <porta> (o que evita casar a saída dos containers para a mesma porta em hosts externos).

Drop-log

implant rate-limit drop-log enable|disable|status liga/desliga um LOG (iptables-drop:rl) limitado dos DROPs do rate-limit — é o que alimenta o sinal iptables_drops do auto-ban. O LOG é opt-in; desligado, a IMPLANT_RL_DROP fica só com o DROP.

Flag (enable) Descrição Default
--per-source <RATE> Cota por IP de origem 6/minute
--per-source-burst <N> Burst por origem 10
--global <RATE> Teto global somando todas as origens 60/minute
--global-burst <N> Burst global 10

Config em /etc/protocolo-implant/drop-log.yml (o revert do rate-limit não apaga). status mostra a config, a presença no kernel, o encaixe com o sinal do auto-ban e avisa quando o kern.log não tem maxsize no logrotate ou o journald não tem SystemMaxUse.

Comandos

Comando Descrição
apply Aplica pack default + cria 4 ipsets
revert [--keep-state] Remove chains/hooks (preserva ipsets). --keep-state guarda o state para um reconcile posterior
reconcile Reaplica a partir do state (regras de add e whitelist preservadas), incluindo ganchos que faltem — use após upgrade ou emergency. Desde a v2.58.0 também instala/atualiza a unit implant-firewall-restore, com guarda
status Estado resumido
list Dump completo (regras + whitelist + counters)
add --port N [--proto tcp] [--max-conn M] [--max-new R] Adiciona/substitui (--max-new default 10/minute)
add --docker N ... Idem, para porta publicada pelo Docker
remove --port N [--proto tcp] / remove --docker N Remove regra
drop-log enable|disable|status LOG limitado dos DROPs
whitelist-ip --ip IP|CIDR Adiciona à whitelist (ipset)
unwhitelist-ip --ip IP Remove da whitelist: tira do set do kernel e do arquivo de sets do boot (v2.60.1+). Idempotente: IP fora da whitelist sai com exit 0 e was_whitelisted: false. Se o IP também vem de outra fonte (ex.: security.trusted_ips, IP da sessão SSH registrado), continua isento e a saída diz still_whitelisted: true com other_sources
whitelist-list Lista entries com source
whitelist-list-from-file --file PATH [--yes] Bulk-import
migrate-to-ipset Migra state antigo para ipset
block-ip --ip IP [--ttl N] Bloqueia IP (0=permanente)
unblock-ip --ip IP Remove da blocklist
blocklist-list Lista entries com TTL restante
blocklist-clear Apaga blocklist (mantém sets)
block-list-from-file --file PATH [--ttl N] [--yes] Bulk-import bloqueio
emergency-disable [--duration 3600] [--source ID] Desabilita temporariamente
emergency-restore Re-aplica agora
emergency-status Estado emergency

Para banir um IP com TTL, motivo e verificação de onde o ban vale, prefira implant ban / implant unban.

Emergency-mode

rate-limit é uma feature opt-in. implant emergency-mode enable desabilita todas as features opt-in aplicadas (harden-network, fail2ban-ipset, rate-limit, auto-ban, geo-block, feed-block, capture, audit, traefik-ratelimit) com TTL e auto-restore via deadman. O restore usa revert --keep-state + reconcile, então as regras de add e a whitelist extra são preservadas.

Distro

Debian/Ubuntu.

Anti-tijolar

Toda mutação destrutiva cria snapshot via implant iptables antes. Recuperação: implant iptables restore --snapshot-id N.

Portas isentas (v2.57.0+)

A porta UDP de cada rede WireGuard criada pelo implant fica isenta do rate-limit: um RETURN marcado wireguard-<iface> no topo da IMPLANT_RATELIMIT (v4 e v6), guardado no state (whitelist_ports) e refeito por apply, reconcile, add e remove. Só o rate-limit deixa de valer para a porta; blocklist e geo-block continuam. Quem põe e tira é o wireguard init/remove — veja wireguard.