implant ban / implant unban
Um comando só para banir um IP ou bloco CIDR (v2.44.0+), qualquer que seja o
mecanismo por baixo. O ban vai para o ipset central da blocklist do
implant (IMPLANT_RL_BLOCKLIST / IMPLANT_RL_BLOCKLIST6), que os ganchos da
chain INPUT e da DOCKER-USER leem — e a resposta diz onde ele vale de
fato. O unban desfaz nos três mecanismos: ipset, fail2ban e UFW.
Uso
implant ban [OPTIONS] <TARGET>
implant ban list
implant ban test <TARGET>
implant unban [OPTIONS] <TARGET>
`ban `
Bane o IP ou CIDR. CIDR é normalizado para o endereço de rede.
| Flag | Descrição |
|---|---|
--ttl <TTL> |
Duração: 3600, 90s, 30m, 24h, 7d. Padrão 24h; máximo ~24 dias (limite do ipset) |
--permanent |
Ban sem prazo |
--reason <TEXTO> |
Motivo; aparece na auditoria e no ban list |
--force |
Aceita prefixo mais amplo que /16 (IPv4) ou /48 (IPv6) |
--fail2ban |
Bane também nas jails ativas do fail2ban (só IP único) |
--dry-run |
Valida as guardas e mostra o que faria, sem aplicar |
Guardas (sem atalho para contorná-las):
- o IP da própria sessão SSH;
- faixas privadas (RFC 1918, CGNAT, ULA), loopback e link-local;
- IPs na whitelist do implant;
- prefixo mais amplo que
/16//48sem--force.
O ban nunca grava no UFW. No fail2ban, só com --fail2ban: sem a flag,
o sinal do fail2ban usado pelo auto-ban leria o IP e trocaria o TTL pedido
pelo dele.
Motivo e data do ban manual ficam em /var/lib/implant/bans.json; os
eventos manual_ban / manual_ban_permanent entram na auditoria do
auto-ban.
"Banido" não é o mesmo que "bloqueado"
O ipset sozinho não bloqueia nada: é preciso que a INPUT (e, em host com
Docker, a DOCKER-USER) tenha o DROP que lê o set. Por isso a resposta traz:
| Campo | Significado |
|---|---|
in_set |
Entrou no ipset (conferido com ipset test) |
enforced.input |
A INPUT tem o DROP da blocklist |
enforced.docker_user |
Idem na DOCKER-USER; null = host sem Docker |
effective |
in_set e ganchos presentes: o tráfego é barrado |
persisted |
Os sets e as regras que os usam voltam no boot: arquivo de sets gravado, unit de restore habilitada e persistência das regras (netfilter-persistent + iptables-persistent, serviço habilitado, /etc/iptables/rules.v4 com conteúdo) |
warnings |
O que falta (ex.: rodar implant rate-limit reconcile) |
effective: false com success: true significa que o IP está no set, mas
não está bloqueado: falta gancho. Rode implant rate-limit reconcile
para recriar os ganchos.
Para o ban sobreviver ao reboot, o host precisa de duas coisas:
- a unit de restore dos ipsets — ver firewall-restore;
- a persistência das regras que leem os sets:
netfilter-persistentcom o plugin doiptables-persistent, o serviçonetfilter-persistenthabilitado e/etc/iptables/rules.v4com conteúdo.
Desde a v2.59.0, o ban só responde persisted: true ("sobrevive a reboot:
sim") quando sets e regras voltam no boot. Sets sem as regras não
bloqueiam nada. Faltando qualquer parte, a resposta vem com
persisted: false e o motivo em warnings.
Instalar o pacote ufw remove o iptables-persistent e o
netfilter-persistent no apt (conflito de pacotes): os sets continuam
voltando pela unit, as regras não. Esse é o caso mais comum de
persisted: false com a unit instalada. O check "Boot-survival do firewall"
do hardening aponta a mesma falta.
Desde a v2.61.0, a unit atual reaplica as regras do implant no boot quando o
netfilter-persistent não as carrega, e isso conta como mecanismo:
persisted: true com a unit em dia, mesmo sem o netfilter-persistent (ver
firewall-restore).
`ban list`
Visão consolidada, uma linha por alvo, juntando ipset, fail2ban e UFW. Cada
item traz sources (ipset, fail2ban:<jail>, ufw), TTL restante (só
para o ipset; 0 = permanente), motivo e data quando o ban foi feito pelo
implant. O topo traz enforced (ganchos presentes) e warnings.
`ban test `
Diz se o IP está banido e se o ban bloqueia de fato: banned, blocked
(banido e com gancho), ipset/ipset_entry (inclusive quando o IP está
coberto por um CIDR), ttl_remaining_seconds, jails do fail2ban, UFW,
whitelisted e enforced. IP que está na blocklist e na whitelist não
aparece como blocked — a whitelist vale acima — e gera aviso.
Sobrevive a reboot? (v2.60.0+) O ban test responde com o mesmo cálculo
do ban: linha "sobrevive a reboot: sim/NÃO" no texto e campo persisted no
JSON ban.test — true só quando sets e regras voltam no boot. Quando
não sobrevive, o motivo vem em warnings. Alvo fora da blocklist:
persisted: null (- no texto).
Feed externo (v2.60.0+): o ban test também mostra se o IP está no
feed-block:
| Campo | Significado |
|---|---|
feed |
O IP está coberto por uma entrada do feed |
feed_entry |
A entrada do feed que o cobre (ex.: 198.51.100.0/24) |
feed_enforced |
Os ganchos do feed estão presentes: o feed barra de fato |
blocked passa a contar o feed: um IP fora da blocklist, mas no feed com
ganchos, aparece como bloqueado.
`unban `
Remove o IP/CIDR do ipset, de todas as jails do fail2ban e das regras do UFW, e encerra o cooldown do auto-ban mantendo o histórico de ofensas (a próxima ofensa conta como reincidência).
No UFW, remove o bloqueio total (deny from <IP>) e, desde a v2.60.0, também
as regras de porta do firewall deny --port P --from <IP> — antes respondia
"não estava banido" para elas. É o mesmo cálculo do
`firewall unblock-ip`.
O unban não tira o IP do feed-block: ele voltaria no
próximo update do feed. Nesse caso a resposta traz in_feed/feed_entry e
avisa que a saída é a whitelist, que vale acima do feed
(implant rate-limit whitelist-ip --ip <ip>).
| Flag | Descrição |
|---|---|
--dry-run |
Mostra o que removeria, sem aplicar |
Saída: was_banned, removed (ipset, fail2ban — lista de jails —, ufw),
auto_ban_cooldown_cleared, offense_count, still_blocked e
still_blocked_by: o que ainda bloqueia o alvo depois do unban — uma entrada
mais ampla da blocklist (ex.: o /24 que o contém), o feed externo ou o UFW.
Desde a v2.60.1 o unban e o ban test usam o mesmo cálculo, inclusive em
dry-run (como previsão). O evento manual_unban entra na auditoria do
auto-ban.
UFW no ban test (v2.60.1+): com o UFW ativo, um deny/reject de
entrada total que cobre o alvo conta como bloqueio (blocked_by: ["ufw"],
ufw_block.rule) quando vem antes de qualquer allow/limit de entrada cuja
origem também cubra o alvo. Se um allow vier antes, o bloqueio não vale de
fato: ufw_block.effective: false e shadowed_by aponta a regra que libera
(use implant firewall block-ip, que insere o deny no topo). Com Docker, o
deny do UFW não alcança as portas publicadas.
Exemplos
sudo implant ban 203.0.113.9 # 24 h (padrão)
sudo implant ban 203.0.113.9 --ttl 7d --reason "scanner em /.env"
sudo implant ban 198.51.100.0/24 --permanent
sudo implant ban 203.0.113.9 --fail2ban # também nas jails ativas
sudo implant ban 203.0.113.9 --dry-run # só valida as guardas
sudo implant ban list # ipset + fail2ban + UFW
sudo implant ban test 203.0.113.9 # banido? bloqueado de fato?
sudo implant unban 203.0.113.9 # desfaz nos três
sudo implant unban 203.0.113.9 --dry-runSaída JSON
-o json devolve o envelope com os comandos ban, unban, ban.list e
ban.test. Campos do ban: target, family (inet/inet6), set,
ttl_seconds, permanent, expires_at, reason, in_set, enforced,
effective, persisted, dry_run, warnings. O ban.test traz também
persisted (null fora da blocklist), feed, feed_entry e
feed_enforced; o unban, in_feed e feed_entry quando o alvo está no
feed.
Notas
- Precedência dos ganchos do implant: whitelist > blocklist > feed-block > geo-block > rate-limit (v2.46.0+; o feed entrou na v2.60.0). Um IP isento continua passando mesmo que esteja na blocklist ou no feed.
- O ban manual e o auto-ban usam o mesmo set;
unbanvale para os dois.
Veja também
- auto-ban — bans automáticos por sinais
- fail2ban
- rate-limit —
reconcilerecria os ganchos - firewall-restore — sets de volta no boot
- feed-block — feed externo de redes hostis