
Conjuntos de regras de ingress do nftables que descartam SYNs TCP IPv4 que transportam opções IP para mitigar a use-after-free da CVE-2026-98432, com contadores e registro por origem.
Mitigação com nftables para CVE-2026-98432: descartar SYNs TCP IPv4 que carregam opções IP, o mais cedo que o nftables conseguir.
A CVE é um use-after-free no caminho do request-socket TCP IPv4
(ireq->ireq_opt / inet_opt, lido em ip_options_build()). A correção adequada é
uma atualização do kernel; isto apenas reduz a exposição até que você tenha uma.
ireq->ireq_opt é definido em um
único lugar, tcp_v4_init_req(), a partir das opções do SYN que abre o request
socket; o SYN retransmitido em corrida apenas lê o que foi salvo ali, e o cenário
da CVE tem o atacante enviando um SYN com opções Record Route ou Timestamp. Portanto, um
SYN com opções é o pacote que importa. A migração do request socket reutiliza o
mesmo ireq_opt salvo. Isto se baseia no código-fonte do kernel e no texto da CVE, não em uma
afirmação dos autores da CVE de que apenas o SYN é suficiente; remova a
correspondência tcp flags & (syn | ack) == syn das regras para a versão
conservadora.
Defina IFACES com as NICs que recebem tráfego externo, depois
sudo nft -f simple.nft. O ruleset é:
define IFACES = { eth0 }
table netdev cve_2026_98432 {
chain ingress {
type filter hook ingress devices = $IFACES priority -500; policy accept;
ip protocol tcp ip hdrlength > 5 tcp flags & (syn | ack) == syn limit rate 5/second burst 10 packets log prefix "CVE-2026-98432 drop: " level warn
ip protocol tcp ip hdrlength > 5 tcp flags & (syn | ack) == syn counter drop
}
}
netdev ingress na prioridade -500 é o primeiro hook do netfilter, à frente de
prerouting, conntrack e roteamento. O XDP ainda é executado antes dele.ip hdrlength > 5 é o IHL do IPv4 em palavras de 32 bits; acima de 5 significa opções.tcp flags & (syn | ack) == syn é um SYN sem ACK.counter na regra de descarte é o total.Acompanhe: sudo nft list chain netdev cve_2026_98432 ingress e
journalctl -k -g 'CVE-2026-98432'.
fancy.nftfancy.nft é o mesmo descarte mais um contador total nomeado e contadores por endereço,
mantidos em dois conjuntos dinâmicos. Ele também conta e registra no log todos os outros pacotes TCP que têm
opções IP (permitidos, não descartados), com os bytes de opção na linha de log
(flags ip options, prefixo CVE-2026-98432 ip-options: ):
| Contador | Onde | O que mostra |
|---|---|---|
| total | contador nomeado dropped_total | SYNs com opções IP, descartados |
| other | contador nomeado options_other | outros TCP com opções IP, permitidos |
| por IP de origem | conjunto by_src | pacotes e bytes por endereço de origem descartado |
| por origem . destino | conjunto by_pair | o mesmo por par (origem, destino) |
| qualquer IP usando opções | conjunto options_by_src | pacotes e bytes por endereço de origem para todo pacote IPv4 com opções, qualquer protocolo (TCP, UDP, ICMP...), incluindo os SYNs descartados |
sudo nft -f fancy.nft
sudo ./cve-log.sh # counters, then follow the kernel log
sudo ./cve-log.sh -c # counters only
sudo ./cve-log.sh -r # reset the total and the per-IP sets
Ou diretamente:
sudo nft list counter netdev cve_2026_98432 dropped_total
sudo nft list counter netdev cve_2026_98432 options_other
sudo nft list set netdev cve_2026_98432 by_src
sudo nft list set netdev cve_2026_98432 by_pair
sudo nft list set netdev cve_2026_98432 options_by_src
Cada elemento tem seu próprio contador de pacotes e bytes e expira 1h após sua última ocorrência. Cada conjunto comporta no máximo 65535 entradas; quando um está cheio, novos endereços não são rastreados, mas o pacote ainda é descartado. Endereços de origem podem ser falsificados, então os contadores por IP mostram o que os pacotes alegavam, não quem os enviou.
sudo nft delete table netdev cve_2026_98432.
Nenhuma delas persiste após uma reinicialização; inclua o arquivo de /etc/nftables.conf.
fancy.nft adiciona a tabela e reconstrói apenas as regras, portanto recarregar mantém os
contadores; execute nft delete table netdev cve_2026_98432 primeiro para zerá-los ou para
alterar um conjunto. Os contadores residem na memória do kernel e não sobrevivem a uma reinicialização.