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_ipsnoconfig.toml 127.0.0.1+::1(loopback)- IP da conexão SSH atual, detectado em
apply(desligável comsecurity.whitelist_current_ssh_ip = false) - IPs custom via
whitelist-ip(ouimplant 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 deapply,revert,reconcileestatus. 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-ipsetFaz 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 8080A 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.