Add DNAT anycast -> backend in frr_anycast nftables config

Трафик на anycast-адрес (172.31.255.10) теперь сначала DNAT'ится на
реальный backend (DNAT_TARGET_IP=95.163.53.117 для site-cloud) в
prerouting, и только потом проходит уже существующий sNAT/masquerade
в postrouting — обе цепочки в одной table inet nat, порядок хуков
гарантирует правильную последовательность.

DNAT включается автоматически по факту заданного dnat_target_ip (без
отдельного булева флага), выключен по умолчанию — площадка A не
затронута. Pre-flight assert не даёт задать dnat_target_ip без
enable_snat (иначе nftables.conf вообще не разворачивается).

render-check-cloud.sh дополнен проверкой DNAT-правила и валидацией
синтаксиса каждого nftables.conf через `nft -c -f`.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Bc3HkMiDwooSyLBLoMKNyF
This commit is contained in:
ayurishchevandClaude Sonnet 5 committed 2026-09-10 17:25:09 +03:00
1 parent b2b7306a3c
commit 1e287ee81c
9 files changed
+88 -2

No files matched your search

+2 -1
View File
@@ -140,6 +140,7 @@ ansible/tests/render-check.sh # golden-diff: рендер frr.conf
- **Основной канал** — сегмент к «Основная площадка» (внешняя сторона, ASN `65104`, пиры M1/M2) — анонсы **без** as-path prepend.
- **Резервный канал** — сегмент к «Резервная площадка» (внешняя сторона, ASN `65103`, пиры B1/B2) — анонсы **с** as-path prepend (на всех 4 узлах, `AS_PATH_PREPEND_COUNT` из env, по умолчанию 3), чтобы при исправном основном канале трафик шёл через него.
- **sNAT** (nftables, masquerade) на внешнем интерфейсе — на всех 4 узлах: трафик на anycast-адрес транслируется для выхода в интернет.
- **DNAT** (nftables, `prerouting`) — на всех 4 узлах трафик на anycast-адрес (`ANYCAST_PREFIX`) сначала перенаправляется на `DNAT_TARGET_IP` (реальный backend, напр. `95.163.53.117`), и только потом, в `postrouting`, применяется sNAT-masquerade. Включается автоматически, если в env задан `DNAT_TARGET_IP` (не нужен отдельный булев флаг); имеет смысл только вместе с `enable_snat: true`, иначе `nftables.conf` не разворачивается — при нарушении playbook останавливается на pre-flight `assert`.
Все значения — в `ansible/site-cloud.env` (ASN, anycast-префикс, IP всех 4 пиров, имена интерфейсов, per-node router-id). Т.к. пиры общие для всех 4 узлов, список `bgp_neighbors` задан один раз в `group_vars/site_cloud.yml`, а не per-node.
@@ -159,6 +160,6 @@ ansible/tests/render-check.sh # регресс: площадка A ре
ansible/tests/render-check-cloud.sh # 4 соседа, prepend только на резервном канале, sNAT
```
`render-check-cloud.sh` проверяет: у каждого из 4 узлов ровно 4 `neighbor ... remote-as` (2×65104 без route-map, 2×65103 с `route-map RM-PREPEND-OUT out`), `route-map` содержит `set as-path prepend 65200 65200 65200`, `nftables.conf` содержит `masquerade` на заданном внешнем интерфейсе.
`render-check-cloud.sh` проверяет: у каждого из 4 узлов ровно 4 `neighbor ... remote-as` (2×65104 без route-map, 2×65103 с `route-map RM-PREPEND-OUT out`), `route-map` содержит `set as-path prepend 65200 65200 65200`, `nftables.conf` содержит DNAT (`dnat to 95.163.53.117`) и `masquerade` на заданном внешнем интерфейсе, а также (если `nft` доступен на control node) валидирует синтаксис каждого `nftables.conf` через `nft -c -f`.
Детали и разбор диаграммы: [docs/2026-09-09-ansible-site-cloud-plan.md](docs/2026-09-09-ansible-site-cloud-plan.md) / [docs/2026-09-09-ansible-site-cloud-summary.md](docs/2026-09-09-ansible-site-cloud-summary.md).