
Временное смягчение для CVE-2026-98432 (use-after-free в Linux IPv4 TCP ireq_opt): отбрасывать IPv4 TCP с IP-опциями, отключить MPTCP. Протестированные скрипты + проверка. EN/KO.
Этот репозиторий содержит скрипты, которые отбрасывают IPv4 TCP-пакеты с IP-опциями на хосте Linux. На хостах без маркировки SELinux/Smack NetLabel CIPSO CVE-2026-98432 (use-after-free в IPv4 TCP ядра Linux) не может сработать без таких пакетов. Это временная мера защиты, а не исправление. Она не тестировалась против реального эксплойта (публичного PoC не существует), и ни один вендор её не одобряет. Если ваш дистрибутив уже поставляет исправленное ядро, установите его, а если вы применили эту меру, запустите revert.sh. Если исправленного ядра нет, проверьте, применима ли мера к вашему хосту, затем примените и проверьте её с помощью шагов ниже (около 10 минут). Автор — частный администратор, а не вендор.
uname -r с исправленными стабильными версиями: 5.10.272, 5.15.223, 6.1.190, 6.6.159, 6.12.113, 6.18.56, 7.2.10, 7.3 (коммит с исправлением e3f33b0a1d89d738e2b913dab519226eaf76e15b). Ядро дистрибутива может содержать исправление под другим номером версии, поэтому также проверьте трекер вашего вендора.cat /sys/kernel/security/lsm. Если в списке есть SELinux или Smack и вы используете NetLabel с отображением CIPSOV4, эта мера не покрывает такой путь.nft. У OpenWrt свой путь (см. раздел Files). Хосты без systemd, кроме OpenWrt, не покрываются.Уровень серьёзности: CNA ядра присваивает CVSS 9.8. Red Hat, Oracle и SUSE присваивают 8.1, а Amazon — 7.0. Anthropic публично описал удалённый эксплойт для получения root против серверов Linux с MPTCP-листенером (2026-10-27). По состоянию на 2026-10-29 сообщений об эксплуатации в реальных атаках не поступало.
Статус дистрибутивов по состоянию на 2026-10-29/30 (это снимок, поэтому проверяйте своего вендора):
| Дистрибутив | Статус |
|---|---|
| Ubuntu (все поддерживаемые релизы) | исправленного ядра нет |
| RHEL 8/9/10 | исправленного ядра нет |
| Proxmox VE | в changelog pve-kernel на 2026-10-30 не было записи об этом CVE |
| Debian, Oracle Linux UEK, некоторые SUSE, некоторые Amazon Linux | исправления доступны |
Запустите sudo ./mitigate.sh. Скрипт идемпотентен (повторный запуск перезагружает набор правил). Он устанавливает файлы, перечисленные в разделе Files, и завершается, если вы не root, если отсутствует nft или если отсутствует systemd.
Сравните вывод с эталоном ниже. Первая строка должна быть:
svc=active enabled=enabled mptcp=0
Следующие два правила идут за ним: одно в таблице inet, другое в таблице bridge.
Если служба слушает через MPTCP, перезапустите её. net.mptcp.enabled=0 влияет только на новые сокеты, поэтому уже открытый MPTCP-слушатель остаётся MPTCP до перезапуска своей службы. Sysctl задаётся для каждого сетевого пространства имён, а mitigate.sh устанавливает его только для пространства имён хоста.
Если на хосте работают контейнеры LXC или Docker, перейдите к разделу «Контейнеры».
Опубликованный эксплойт был нацелен на MPTCP-слушатели. Сама гонка не требует MPTCP (вывод из описания исправления). Можно ли полностью скомпрометировать хост без MPTCP, не установлено.
SYN-ACK цели отражает IP-опции. Клиент, на котором применена эта мера защиты, отбрасывает такой SYN-ACK, поэтому check-blocked.py сообщает «blocked», даже если цель не защищена. Измерено на одном хосте: после revert.sh на цели check-blocked.py с защищённого клиента всё равно выводил ipopt FAIL TimeoutError, тогда как verify-synack.sh показывал ipopt synack=5.
Выберите один инструмент:
python3 check-blocked.py <host> <port> (root не нужен). Он подключается дважды: обычным способом, затем с опцией IPv4 Record Route, заданной через опцию сокета IP_OPTIONS.sudo ./verify-synack.sh <ip> <port> на любом клиенте (на клиенте нужны root, tcpdump и python3). Он отправляет обычный SYN и SYN с IP-опциями с фиксированных исходных портов и подсчитывает SYN-ACK цели с помощью tcpdump.Затем сравните вывод с таблицей для этого инструмента.
check-blocked.py (с клиента без меры защиты):
| Вывод | Значение |
|---|---|
plain CONNECTED | обычный TCP работает |
ipopt FAIL TimeoutError | SYN с IP-опциями отброшен, как и задумано |
verify-synack.sh:
| Вывод | Значение |
|---|---|
plain: CONNECTED synack=N | ipopt: TimeoutError synack=0 | цель защищена |
ipopt ... synack>=1 | цель не защищена (на SYN с IP-опциями был получен ответ) |
Результат на уровне ядра (один хост Proxmox VE, ядро 7.0, 2026-10-30): при выключенной мере защиты уязвимый путь кода выполнялся один раз на путь, через WireGuard и от LXC к LXC. При включённой мере SYN завершался по тайм-ауту, и путь выполнялся 0 раз. Выборка — 2 пути в 2 состояниях на одном хосте. Метод трассировки описан в docs/ANALYSIS.md (на английском).
Состояние nftables задаётся для каждого сетевого пространства имён, поэтому правила только на хосте не защищают пространства имён контейнеров. Измерено на контейнерах LXC: при наличии только правил на хосте SYN с IP-опциями изнутри контейнера к его собственному 127.0.0.1 или к его собственному IP устанавливал соединение. Контейнеры используют общее ядро хоста, поэтому код внутри любого контейнера мог таким образом достичь уязвимого пути.
sudo ./inject-netns.sh на хосте. Он загружает тот же набор правил в каждый работающий контейнер LXC (через pct/lxc-info, Proxmox) и каждый работающий контейнер Docker (контейнеры с сетью хоста пропускаются).| Вывод | Значение |
|---|---|
ok lxc:<id> или ok docker:<id> | набор правил загружен в пространство имён этого контейнера |
injected=N failed=M | итоги, M должно быть равно 0 |
Внедрение не является постоянным. Оно теряется при перезапуске контейнера, поэтому повторно запускайте скрипт после перезапусков. Для контейнеров Docker, вложенных в контейнер LXC, скрипт нужно запускать внутри этого контейнера LXC (не измерялось).
Измеренный результат: на 5 хостах Proxmox в 64 пространства имён контейнеров было выполнено внедрение с 0 сбоев. После внедрения тот же тест завершался по тайм-ауту, а счётчик отброшенных пакетов в пространстве имён контейнера возрастал.
Симптом вмешательства этой меры защиты — TCP-соединение, которое зависает (завершается по тайм-ауту), а не получает отказ, вместе с растущим счётчиком в выводе:
nft list ruleset | grep counter
| Команда | Действие |
|---|---|
systemctl stop cve-2026-98432-mitigation | немедленно отключается, включается снова при перезагрузке |
systemctl disable --now cve-2026-98432-mitigation | отключается сейчас и при последующих перезагрузках |
Совместимость измерена на протестированных хостах: правила находятся в собственных таблицах и сосуществовали с Docker, ufw, NAT-правилами iptables-legacy и маршрутизацией NetBird (WireGuard). Обычные TCP-соединения продолжали работать на всех протестированных путях. Счётчики сброса оставались на уровне количества тестовых пакетов во время нормальной работы (ни один легитимный трафик не совпал) в течение короткого окна наблюдения (часы, а не дни).
Предположение, не измерено: nftables.service, конфигурация которого содержит flush ruleset, удалит таблицы при перезагрузке. Проверьте это и повторно запустите mitigate.sh после такой перезагрузки.
uname -r.sudo ./revert.sh. Добавьте --mptcp, если вы также хотите снова включить MPTCP.