Commit ea2f8f05 authored by Vitaly Lipatov's avatar Vitaly Lipatov

route-update.md: update docs for IPv6 support, NETMAP, auto-recovery

- Document routes6.d/ structure and IPv6 processing - Add GRE tunnel + NPTv6 prefix translation diagram - Document "default" keyword behavior for IPv4/IPv6 - Document IPv4 filtering in IPv6 mode - Document automatic rules/routes recovery - Note routes.d/ and routes6.d/ are site-specific (not in git) - Update state section with gateway tracking Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent 1cea8b1b
......@@ -9,40 +9,88 @@
Каталог = группа маршрутов. Файлы внутри определяют куда и что маршрутизировать:
```
routes.d/
├── dgw/ # группа "dgw" (direct, через дефолтный шлюз)
│ ├── gateway # default
│ ├── table # 2
routes.d/ # IPv4
├── dgw/ # группа "dgw" (direct, через дефолтный шлюз)
│ ├── gateway # default
│ ├── table # 2
│ └── dgw.list -> /root/egw-route/dgw.list
├── egw/ # группа "egw"
│ ├── gateway # 91.232.225.112
│ ├── table # 112
├── egw/ # группа "egw"
│ ├── gateway # 91.232.225.112
│ ├── table # 112
│ └── egw.list -> /root/egw-route/egw.list
├── ogw/ # группа "ogw"
│ ├── gateway # 91.232.225.12
│ ├── table # 12
├── ogw/ # группа "ogw"
│ ├── gateway # 91.232.225.12
│ ├── table # 12
│ ├── ogw.list -> /root/egw-route/ogw.list
│ ├── youtube.list -> /root/egw-route/youtube.list
│ └── antifilter-*.list -> /root/antifilter/...
routes6.d/
└── egw-v6/ # IPv6 группа
├── gateway # fc00:eeee:eeee:eeee::1
├── table # 201
└── egw.list -> /root/egw-route/egw.list
routes6.d/ # IPv6
├── dgw/ # те же списки, шлюз через default IPv6
│ ├── gateway # default
│ ├── table # 2
│ └── dgw.list -> /root/egw-route/dgw.list
├── egw/ # обход блокировок через GRE-туннель
│ ├── gateway # 2a03:5a00:c:20::122
│ ├── table # 201
│ └── egw.list -> /root/egw-route/egw.list
└── ogw/ # доменные списки (IPv4-подсети фильтруются)
├── gateway # 2a03:5a00:c:20::122
├── table # 12
├── ogw.list -> /root/egw-route/ogw.list
└── youtube.list -> /root/egw-route/youtube.list
```
Каталоги `routes.d/`, `routes6.d/` и `.state/` — site-specific, не хранятся в git.
При запуске скрипт:
1. Для каждой группы читает `gateway` и `table`
2. Собирает все `.list` файлы (следуя симлинкам)
3. Проверяет изменения (MD5 хэш содержимого)
4. Файлы с IP/подсетями — пропускает напрямую
4. Файлы с IP/подсетями — пропускает напрямую (IPv4-адреса фильтруются в IPv6 режиме)
5. Файлы с доменами — резолвит через `adnshost` (bulk async) + `dig` (fallback)
6. Сравнивает resolved IPs с предыдущими
7. Загружает маршруты через `ip -batch`
8. Создаёт `ip rule` для таблицы
9. Если ip rules/routes потеряны (перезагрузка сети), автоматически восстанавливает
## IPv6 поддержка
Скрипт обрабатывает `routes.d/` (IPv4) и `routes6.d/` (IPv6) последовательно.
Для IPv6 групп:
- Ключевое слово `default` в gateway резолвится через `ip -6 route show default`
- Файлы `.list` с IPv4-адресами/подсетями автоматически фильтруются
- Доменные списки резолвятся через AAAA-записи (`adnshost -t aaaa`)
- Один и тот же `.list` файл можно использовать в routes.d и routes6.d —
IPv4-адреса попадут в IPv4 маршруты, домены будут зарезолвлены в обоих режимах
### GRE-туннель для IPv6
IPv6-трафик к заблокированным ресурсам маршрутизируется через GRE-туннель:
```
egw (2a03:5a00:c:20::14)
│ ip rule → table egw-v6 → via 2a03:5a00:c:20::122
CT 680 gre.hetzner (2a03:5a00:c:20::122)
│ nft SNAT prefix: 2a03:5a00:c:20::/120 → 2a01:4f9:c010:cf42::/120
═══ GRE tunnel (fd32::2 ↔ fd32::1) ═══
hetzner (2a01:4f9:c010:cf42::1)
│ route: 2a01:4f9:c010:cf42::/120 via fd32::2
│ НЕТ NAT — src уже в hetzner /64
интернет (видит src 2a01:4f9:c010:cf42::14)
```
Prefix translation (NPTv6) через nftables `snat prefix` / `dnat prefix` на CT 680.
Предсказуемое сопоставление: внутренний `::N` → внешний `::N`.
## Формат файлов
......@@ -52,8 +100,9 @@ IP-адрес шлюза, одна строка — обычный маршру
91.232.225.12
```
Ключевое слово `default` — использовать текущий дефолтный шлюз машины
(определяется из `ip route show default`):
Ключевое слово `default` — использовать текущий дефолтный шлюз машины.
Для IPv4 групп (routes.d) определяется из `ip route show default`,
для IPv6 групп (routes6.d) — из `ip -6 route show default`:
```
default
```
......@@ -72,10 +121,14 @@ default
Приоритет `ip rule` = table × 10 (table 12 → pref 120).
Таблицы IPv4 и IPv6 с одинаковым номером — независимы в ядре.
Имена таблиц определяются в `/etc/iproute2/rt_tables`.
### .list файлы
Симлинки на файлы со списками. Формат списка:
- Домены: `example.com` — будут зарезолвлены
- IP-адреса: `1.2.3.4` — пройдут напрямую
- Домены: `example.com` — будут зарезолвлены (A для IPv4, AAAA для IPv6)
- IP-адреса: `1.2.3.4` — пройдут напрямую (фильтруются в IPv6 режиме)
- IPv6-адреса: `2001:db8::1` — пройдут напрямую (фильтруются в IPv4 режиме)
- Подсети: `10.0.0.0/24` — пройдут напрямую
- Диапазоны: `r[1-3].example.com` — развернутся в r1, r2, r3
- Комментарии: `# текст`
......@@ -116,18 +169,23 @@ default
Двухуровневое:
1. **Хэш файлов** — MD5 содержимого всех .list файлов группы.
1. **Хэш файлов** — MD5 содержимого всех .list файлов + gateway + table.
Если не изменился — группа пропускается (быстрый путь).
2. **Diff resolved IPs** — после резолва сравниваются IP с предыдущим запуском.
Если DNS вернул те же адреса — маршруты не трогаются, обновляется только хэш.
3. **Проверка ip rules/routes** — даже при совпадении хэшей скрипт проверяет,
что ip rule и маршруты в таблице существуют. Если потеряны (перезагрузка
сети, `networkctl reconfigure`), автоматически перезагружает группу.
| Событие | Что происходит |
|---|---|
| Файл .list изменился | Хэш меняется → резолв + проверка |
| Симлинк добавлен/убран | Хэш меняется → пересборка |
| Симлинк перемещён между группами | Оба хэша меняются → обе пересобираются |
| Gateway изменился | Хэш меняется → перезагрузка маршрутов |
| DNS вернул те же IP | Маршруты не перезагружаются |
| ip rules/routes потеряны | Автоматическая перезагрузка |
| Все .list убраны из группы | Таблица очищается |
| Каталог группы удалён | Cleanup находит осиротевший state → flush |
......@@ -163,12 +221,18 @@ routes.d/dgw/
## Архитектура маршрутизации
```
ip rule show:
ip rule show (IPv4):
20: from all lookup 2 ← [dgw] (direct, через дефолтный шлюз)
120: from all lookup 12 ← [ogw]
1120: from all lookup 112 ← [egw]
32766: from all lookup main ← default route
ip -6 rule show (IPv6):
20: from all lookup 2 ← [dgw] (direct, через дефолтный IPv6 шлюз)
120: from all lookup 12 ← [ogw]
2010: from all lookup 201 ← [egw-v6]
32766: from all lookup main ← default route
Пакет к dst 1.2.3.4:
→ lookup table 2: есть маршрут? → via default gw (прямой доступ)
→ lookup table 12: есть маршрут? → via 91.232.225.12
......@@ -187,8 +251,9 @@ ip rule show:
.state/
├── routes.d/
│ ├── egw/
│ │ ├── hash # MD5 содержимого .list файлов
│ │ ├── hash # MD5 содержимого .list + gateway + table
│ │ ├── table # номер таблицы (для cleanup)
│ │ ├── gateway # копия gateway (для обнаружения смены шлюза)
│ │ └── resolved # sorted список IP после резолва
│ └── ogw/
│ └── ...
......@@ -207,6 +272,15 @@ ln -s /path/to/domains.list routes.d/mygroup/domains.list
./route-update.sh
```
### Новая IPv6 группа
```bash
mkdir routes6.d/mygroup
echo '2a03:5a00:c:20::1' > routes6.d/mygroup/gateway
echo '50' > routes6.d/mygroup/table
ln -s /path/to/domains.list routes6.d/mygroup/domains.list
./route-update.sh
```
### Добавить список в существующую группу
```bash
ln -s /root/egw-route/newlist.list routes.d/ogw/newlist.list
......@@ -230,6 +304,7 @@ mv routes.d/ogw/youtube.list routes.d/egw/
| IPv4/IPv6 | Отдельные скрипты | Единый скрипт |
| Multipath | Нет | Несколько строк в gateway |
| Обнаружение изменений | diff файла целиком | MD5 хэш + diff resolved |
| Восстановление | Ручной перезапуск | Автоматическое при потере rules/routes |
| Отладка | iptables -L, ipset list | ip route show table N |
## Зависимости
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment