
Scripts shell que verificam hosts Linux para CVE-2026-98432 e aplicam uma regra iptables u32 temporária descartando pacotes TCP IPv4 com opções IP, com unidade systemd, autoteste e reversão.
Este repositório contém três scripts que verificam um host Linux para CVE-2026-98432 e, quando não há um kernel corrigido disponível, descartam pacotes TCP IPv4 que carregam opções IP com uma única regra iptables. É a contraparte iptables de typhoon1217/cve-2026-98432-mitigation, que faz o mesmo com nftables. É uma mitigação temporária, não uma correção. Não foi testada contra um exploit real (não há PoC público), e nenhum fornecedor a endossa. O autor é um administrador individual, não um fornecedor.
Destina-se a hosts que não podem obter um kernel corrigido e não podem executar a variante nftables:
5.15.0-203, para 24.04 para 6.8.0-149. Até esse kernel ser iniciado, a mitigação fecha a lacuna.iptables mas sem nft, ou com um nft demasiado antigo para ip hdrlength.Não se destina a hosts Proxmox VE, que têm o seu próprio kernel corrigido (7.0.14-25-pve e posteriores) e tráfego em bridge que necessita da regra de bridge do repositório nftables. Não se destina a hosts com SELinux ou rotulagem CIPSO do Smack NetLabel, que podem alcançar o código vulnerável sem opções IP. Não se destina a kernels anteriores a 4.4, que não contêm o bug.
Se a sua distribuição fornece um kernel corrigido, instale-o, reinicie e execute cve-98432-revert-iptables.sh se aplicou esta mitigação.
CVE-2026-98432 é uma race condition na configuração de conexões TCP IPv4. O kernel mantém as opções IP de um SYN recebido em ireq_opt, e com o timing certo uma CPU liberta esse objeto enquanto outra ainda o lê. No código-fonte mainline, ireq_opt só é definido quando o SYN transportava opções de cabeçalho IPv4, ou seja, o cabeçalho IP tem mais de 20 bytes (IHL > 5), ou através de rotulagem CIPSO. Sem opções, não há nada para libertar ou ler. Assim, a regra descarta todos os pacotes TCP IPv4 cujo cabeçalho tem mais de 20 bytes:
iptables -t raw -I PREROUTING -p tcp -m u32 --u32 "0>>24&0xF=6:15" -j DROP
A correspondência u32 lê os primeiros quatro bytes do cabeçalho IP, desloca o primeiro byte para baixo e mantém o seu nibble inferior, que é o campo IHL em palavras de 32 bits. 6:15 corresponde a todos os valores acima de 5. O hook PREROUTING da tabela raw é executado antes de o kernel analisar as opções e antes do conntrack. O tráfego de loopback passa pelo mesmo hook, que é aquilo em que o autoteste se baseia.
Num network namespace com um listener de loopback, um SYN simples ligou-se e um SYN com a opção Record Route expirou, com o contador da regra em 2 pacotes (SYN e uma retransmissão). A regra nftables ip hdrlength gt 5 comportou-se de forma idêntica. Foram testados tanto o iptables-legacy como o iptables-nft.
O tráfego TCP legítimo com opções IP é raro. Em nove hosts de produção (mail, DNS, web, XMPP) o contador manteve-se nos pacotes do autoteste durante a janela de observação.
cve-98432-check.sh. É apenas de leitura. Observe status, kernel_upstream_base e kernel_changelog_cve. Os kernels de fornecedor incluem a correção sob os seus próprios números de versão, pelo que, quando o changelog do kernel em execução menciona a CVE, isso prevalece sobre a comparação de versões.iptables_u32_probe. Deve indicar ok. A sonda executa iptables -C, que apenas pergunta se a regra existe e, portanto, não acrescenta nada; a resposta indica se a correspondência u32 e a tabela raw são utilizáveis neste kernel.selftest_ipopt. CONNECTED significa que um SYN com opções IP atualmente passa. FAIL significa que já está a ser descartado.bash, iptables com xt_u32 e iptable_raw, systemd. Python 2 ou 3 para o autoteste. Hosts sem systemd não são abrangidos.Testado em Debian 9 (iptables 1.6.0, legacy), Debian 10 e 11 (iptables 1.8.x, backend nf_tables) e Ubuntu 22.04 (iptables 1.8.7). O caminho de arranque foi testado em Debian 10.
Os scripts são enviados para o host via SSH na entrada padrão, pelo que não é necessário copiar nada primeiro.
ssh root@HOST 'bash -s' < cve-98432-check.sh
ssh root@HOST 'bash -s' < cve-98432-apply-iptables.sh
É idempotente. Instala /usr/local/sbin/cve-2026-98432-mitigation (start|stop|status), uma unit oneshot do systemd cve-2026-98432-mitigation.service que carrega a regra antes de network-pre.target e, apenas quando o kernel conhece MPTCP, /etc/sysctl.d/99-cve-2026-98432.conf com net.mptcp.enabled = 0. Ele encerra antes de alterar qualquer coisa se não for root, se iptables ou systemd estiverem ausentes, ou se a sondagem u32 falhar.host=... svc=active enabled=enabled mptcp=n/a
-A PREROUTING -p tcp -m u32 --u32 "0x0>>0x18&0xf=0x6:0xf" -j DROP
selftest_plain=CONNECTED
selftest_ipopt=FAIL TimeoutError
mptcp=0 nos kernels 5.6 e posteriores. Versões mais antigas do Python imprimem FAIL timeout, que é o mesmo resultado.ssh root@HOST 'systemctl is-active cve-2026-98432-mitigation; /usr/local/sbin/cve-2026-98432-mitigation status'
while read -r h; do echo "##### $h"; ssh root@$h 'bash -s' < cve-98432-apply-iptables.sh; done < hosts.txt
Execute a verificação novamente em cada host mitigado e observe dois campos:
| Campo | Esperado |
|---|---|
cve_service | enabled/active |
selftest_ipopt | FAIL ... (o SYN com opções IP foi descartado) |
O autoteste usa loopback. O tráfego da rede passa pelo mesmo hook PREROUTING, portanto o resultado se aplica. Se quiser confirmar de fora, check-blocked.py e verify-synack.sh do repositório nftables funcionam sem alterações contra um host mitigado desta forma.
Para observar os contadores:
while read -r h; do
printf '%-28s ' "$h"
ssh -n root@$h '/usr/local/sbin/cve-2026-98432-mitigation status' 2>&1 | awk '{print "pkts="$1, "bytes="$2}'
done < hosts.txt
Cada autoteste adiciona 2 pacotes. Um contador que cresce além disso significa tráfego real com opções IP chegando ao host; observe isso antes de decidir qualquer coisa. O -n é importante: sem ele, o ssh lê o restante da lista de hosts da entrada padrão e o loop para após o primeiro host.
O sintoma é uma conexão TCP que trava (expira) em vez de ser recusada, junto com um contador crescente.
| Comando | Efeito |
|---|---|
systemctl stop cve-2026-98432-mitigation | desliga imediatamente, volta a ligar no reboot |
systemctl disable --now cve-2026-98432-mitigation | desliga agora e entre reboots |