Files
poc-frr-anycast/docs/2026-09-11-system-hardening-plan.md
ayurishchevandClaude Sonnet 5 72367682b5 Harden frr_anycast against unattended-upgrade-triggered route flush
Prod-инцидент: apt-daily-upgrade обновил libc6 -> postinst вызвал
рестарт зависимых юнитов -> перезапустился systemd-networkd -> он
вычистил из ядра BGP-маршруты zebra (KeepConfiguration не был задан,
networkd по умолчанию удаляет "чужие" маршруты при старте). Zebra не
знала о вычистке, трафик встал до ручного restart frr. Повторилось
10 сентября с обновлением systemd, но было замаскировано плейбуком.

Роль frr_anycast теперь защищает от этого класса сбоя безусловно:
- отключены apt-daily/apt-daily-upgrade (20auto-upgrades + маскирование
  таймеров и сервисов) - обновления пакетов только вручную;
- systemd-networkd получает drop-in KeepConfiguration=yes - устраняет
  сам механизм вычистки маршрутов при любом будущем рестарте networkd,
  не только от конкретного пакета-триггера;
- новый handler Restart systemd-networkd между Apply netplan и Restart
  frr (networkd должен переустановить владение интерфейсами до того,
  как zebra переустановит маршруты).

Шаблоны FRR/nftables не затронуты: render-check.sh 6/6,
render-check-cloud.sh 84/84, без изменений.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Bc3HkMiDwooSyLBLoMKNyF
2026-09-11 13:09:17 +03:00

26 lines
3.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# План внедрения: защита от auto-update-триггеров и networkd route-flush
**Дата:** 2026-09-11
## Инцидент
`apt-daily-upgrade.service` обновил `libc6` → postinst вызвал `daemon-reexec`/рестарт зависимых юнитов → перезапустился `systemd-networkd`. Networkd по умолчанию (`KeepConfiguration` не задан) при старте вычищает на управляемых интерфейсах маршруты, которые не совпадают с его конфигом — «чужие» для него BGP-маршруты zebra. Zebra не знала о вычистке (её RIB не менялся), кернел-FIB был пуст до ручного `systemctl restart frr`. Аналогичный триггер сработал повторно 10 сентября (обновление `systemd`), но был замаскирован плейбуком, перезапускавшим FRR следом.
Вывод пользователя: триггером может стать обновление **любого** пакета, тянущего рестарт networkd — защита должна быть не от конкретного пакета, а структурная.
## Решение (роль `frr_anycast`, применяется безусловно на всех узлах)
1. **Отключить автоматические/unattended обновления**:
- `/etc/apt/apt.conf.d/20auto-upgrades` → `Update-Package-Lists "0"`, `Unattended-Upgrade "0"`.
- Замаскировать `apt-daily.timer`, `apt-daily-upgrade.timer` и их `.service` — двойная защита, даже если конфиг-файл будет вручную изменён.
- Обновления пакетов остаются возможны, но только явным `apt update && apt upgrade`, инициированным администратором.
2. **`systemd-networkd` не должен вычищать маршруты, поставленные не им** — drop-in `/etc/systemd/networkd.conf.d/99-keep-configuration.conf` с `KeepConfiguration=yes`. Защищает от той же категории сбоя при **любом** будущем рестарте networkd, независимо от причины.
3. Handler-цепочка при изменении networkd-конфига: `Restart systemd-networkd` → `Restart frr` (та же логика, что и ручной remediation 08:57 — зебра переустанавливает маршруты после того, как networkd перечитал конфиг).
## Definition of done
- Задачи добавлены в `roles/frr_anycast/tasks/main.yml`, handler — в `handlers/main.yml` (порядок: после `Apply netplan`, перед `Restart frr`).
- `frr.conf.j2`/`daemons.j2`/`nftables.conf.j2` не затронуты — `render-check.sh`/`render-check-cloud.sh` проходят без изменений (регресс-проверка).
- `--syntax-check` чист для обоих playbook'ов.
- README и summary обновлены.