
Набор правил nftables и юнит systemd, которые отбрасывают IPv4 TCP-пакеты с IP-опциями для смягчения use-after-free в ядре Linux (CVE-2026-98432) до выхода исправленного ядра.
Временная мера защиты на уровне межсетевого экрана для CVE-2026-98432 на Ubuntu 24.04 (noble) — для хостов, предоставляющих публичный TCP-листенер (например, узел Geth на порту 30303), пока исправленное ядро ещё недоступно.
CVE-2026-98432 — это use-after-free в коде рукопожатия IPv4 TCP ядра Linux. Когда входящий SYN содержит IP-опции IPv4, эти опции передаются новому дочернему сокету без копирования; повторно переданный SYN, обрабатываемый одновременно на другом CPU, может затем прочитать их после того, как они были освобождены. Существует второй триггер через миграцию request-сокета (net.ipv4.tcp_migrate_req=1 или программу BPF_SK_REUSEPORT_SELECT_OR_MIGRATE).
Ubuntu оценивает её как High priority (CVSS 3: 9.8). На момент написания исправление ядра linux для noble всё ещё в разработке.
MPTCP-листенеры не являются отдельным случаем. Бинарники Go 1.24+ (включая свежий Geth) по умолчанию открывают листенеры как MPTCP, поэтому ss показывает их как mptcp. Подпотоки MPTCP проходят через тот же путь IPv4 TCP SYN, поэтому они подвержены ровно тому же риску, что и обычный TCP. Отключение MPTCP (GODEBUG=multipathtcp=0) не устраняет уязвимость.
Одно правило nftables в собственной таблице отбрасывает любой IPv4 TCP-пакет, длина заголовка которого не равна 5 (то есть любой пакет, несущий IP-опции), прежде чем его увидит TCP-стек ядра:
ip protocol tcp ip hdrlength != 5 counter drop
ip hdrlength != 5) также отбрасывала запросы членства IGMP, которые несут опцию Router Alert, и может незаметно нарушить LAN-мультикаст (mDNS/Avahi, кастинг).inet cvefix), поэтому сосуществует с ufw и не затрагивается перезагрузками ufw.| Файл | Куда установить | Назначение |
|---|---|---|
nftables-cve-2026-98432.nft | /etc/nftables-cve-2026-98432.nft | Набор правил (идемпотентный; безопасно запускать повторно) |
cve-2026-98432.service | /etc/systemd/system/cve-2026-98432.service | Oneshot-юнит, загружающий набор правил при загрузке |
Не помещайте это правило в
/etc/nftables.conf. Этот файл начинается сflush ruleset, что сотрёт правила ufw, если запуститсяnftables.service.
git clone <this-repo> && cd <this-repo>
sudo install -m 0644 nftables-cve-2026-98432.nft /etc/nftables-cve-2026-98432.nft
sudo install -m 0644 cve-2026-98432.service /etc/systemd/system/cve-2026-98432.service
sudo systemctl daemon-reload
sudo systemctl enable --now cve-2026-98432.service
sudo nft list table inet cvefix
Также убедитесь, что триггер миграции отключён (по умолчанию):
sysctl net.ipv4.tcp_migrate_req # expect: 0
Установите nping. В Ubuntu он входит в пакет nmap; отдельного пакета nping нет:
sudo apt install nmap
Сначала перезагрузите набор правил, чтобы сбросить счётчик до 0, затем отправьте обычный SYN (без IP-опций) через loopback:
sudo nft -f /etc/nftables-cve-2026-98432.nft # reload; resets the counter to 0
sudo nping --tcp -p 30303 --flags syn -c 3 127.0.0.1
sudo nft list table inet cvefix
Ожидается: ответы SA (SYN-ACK), показывающие, что слушатель по-прежнему доступен, а счётчик остаётся на packets 0 bytes 0. Если ответов нет, возможно, nping не может захватывать трафик на loopback; в этом случае запустите этот тест и следующий против LAN IP хоста вместо 127.0.0.1.
Отправьте тот же SYN, на этот раз с IP-опцией (Record Route). Трафик loopback проходит через хук prerouting, поэтому это проверяет правило без каких-либо промежуточных звеньев:
sudo nping --tcp -p 30303 --flags syn --ip-options R -c 3 127.0.0.1
sudo nft list table inet cvefix
Ожидается: nping не получает ответов (Lost: 3 (100.00%)), и счётчик показывает ровно:
ip protocol tcp ip hdrlength != 5 counter packets 3 bytes 240 drop
(3 пробы × 80 байт.)
Удалённые тесты задействуют правило только в том случае, если проба действительно достигает хоста. На другой машине в той же локальной сети укажите LAN-адрес хоста:
sudo nping --tcp -p 30303 --flags syn --ip-options R -c 3 <host-lan-ip>
Затем проверьте счётчик на защищённом хосте:
sudo nft list table inet cvefix
Ожидается: ответов нет, а счётчик увеличивается на 3 (до packets 6 bytes 480, если вы сначала выполнили шаг 2).
Зондирование публичного IP извне обычно не даёт однозначного результата. Многие маршрутизаторы и устройства провайдера сами отклоняют пакеты с IP-опциями. Типичный признак — ответ RA (reset) с высоким TTL, например ttl=250, что указывает на устройство с начальным TTL 255, а не на хост Linux (начальный TTL 64). Зонд так и не достигает хоста, поэтому счётчик не меняется. Шаг 4 показывает, как это определить.
Выполните их на защищаемом хосте.
Убедитесь, что удалённые зонды доходят. Запустите это, затем повторите зонд из шага 3 с другой машины:
sudo tcpdump -ni any 'tcp port 30303 and (ip[0] & 0x0f) > 5'
| tcpdump на хосте | счётчик nft | ответ nping | Значение |
|---|---|---|---|
| показывает пакеты | увеличивается | нет | Мера защиты работает |
| показывает пакеты | без изменений | SA | Правило не активно; проверьте nft list table inet cvefix |
| ничего | без изменений | нет или RA | Проба остановлена выше по потоку; проверьте из LAN или loopback |
Убедитесь, что больше ничего не перехватывается. Не трогайте счётчик несколько минут; он должен оставаться на вашем тестовом значении. Чтобы увидеть приходящий трафик с опциями, отличными от TCP (который это правило намеренно пропускает):
sudo tcpdump -ni any '(ip[0] & 0x0f) > 5 and not tcp'
IGMP-запросы от LAN-маршрутизатора (например, igmp query v3 к 224.0.0.1) являются нормальными и не должны увеличивать счётчик.
systemctl is-enabled cve-2026-98432.service # expect: enabled
sudo nft list table inet cvefix # table present
sysctl net.ipv4.tcp_migrate_req # expect: 0
Это временное решение. Периодически проверяйте наличие исправленного ядра:
uname -r
sudo pro fix CVE-2026-98432
Когда исправление доступно:
sudo apt update && sudo apt full-upgrade
sudo reboot
Livepatch (через бесплатную персональную подписку Ubuntu Pro; pro status, canonical-livepatch status) может позволить избежать перезагрузки, но нет гарантии, что для этой CVE будет выпущен livepatch.
После запуска исправленного ядра (оставлять его также безвредно):
sudo systemctl disable --now cve-2026-98432.service
sudo nft delete table inet cvefix
sudo rm /etc/systemd/system/cve-2026-98432.service /etc/nftables-cve-2026-98432.nft
sudo systemctl daemon-reload
Для дополнительной защиты до установки исправления входящий трафик на порт 30303 можно полностью закрыть (Geth продолжит синхронизацию через исходящие пиры, но с меньшим их количеством):
sudo ufw deny 30303/tcp
# later:
sudo ufw delete deny 30303/tcp