Commit b0a2f9fe authored by Vitaly Lipatov's avatar Vitaly Lipatov

router: add route-update.md documentation

parent 0df79c2d
# route-update.sh — декларативная маршрутизация через каталоги
Единый скрипт для управления policy routing на Linux-шлюзе.
Заменяет набор однотипных скриптов (update_egw.sh, update_z-i.sh, ...) с ipset+iptables mangle
на чистые `ip route` + `ip rule` с файловой конфигурацией.
## Принцип работы
Каталог = группа маршрутов. Файлы внутри определяют куда и что маршрутизировать:
```
routes.d/
├── 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.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
```
При запуске скрипт:
1. Для каждой группы читает `gateway` и `table`
2. Собирает все `.list` файлы (следуя симлинкам)
3. Проверяет изменения (MD5 хэш содержимого)
4. Файлы с IP/подсетями — пропускает напрямую
5. Файлы с доменами — резолвит через `adnshost` (bulk async) + `dig` (fallback)
6. Сравнивает resolved IPs с предыдущими
7. Загружает маршруты через `ip -batch`
8. Создаёт `ip rule` для таблицы
## Формат файлов
### gateway
IP-адрес шлюза, одна строка — обычный маршрут:
```
91.232.225.12
```
Несколько строк — multipath (per-flow балансировка между gateway):
```
91.232.225.12
91.232.225.112
```
### table
Номер таблицы маршрутизации:
```
12
```
Приоритет `ip rule` = table × 10 (table 12 → pref 120).
### .list файлы
Симлинки на файлы со списками. Формат списка:
- Домены: `example.com` — будут зарезолвлены
- IP-адреса: `1.2.3.4` — пройдут напрямую
- Подсети: `10.0.0.0/24` — пройдут напрямую
- Диапазоны: `r[1-3].example.com` — развернутся в r1, r2, r3
- Комментарии: `# текст`
Файлы, содержащие только IP/подсети (antifilter), обрабатываются мгновенно через `grep`.
Файлы с доменами проходят через bulk DNS-резолв.
## Использование
```bash
# Основной запуск (пропускает неизменённые группы)
./route-update.sh
# Принудительная перезагрузка всех маршрутов
./route-update.sh --force
# Показать что будет сделано, ничего не менять
./route-update.sh --show
# Создать ip rule для всех групп (без загрузки маршрутов)
./route-update.sh --set-rules
# Очистить таблицу маршрутов группы
./route-update.sh --flush ogw
# Добавить маршрут вручную (немедленно, не сохраняется в файл)
./route-update.sh --add example.com egw
./route-update.sh --add 1.2.3.4 ogw
# Убрать маршрут
./route-update.sh --del example.com egw
```
## Обнаружение изменений
Двухуровневое:
1. **Хэш файлов** — MD5 содержимого всех .list файлов группы.
Если не изменился — группа пропускается (быстрый путь).
2. **Diff resolved IPs** — после резолва сравниваются IP с предыдущим запуском.
Если DNS вернул те же адреса — маршруты не трогаются, обновляется только хэш.
| Событие | Что происходит |
|---|---|
| Файл .list изменился | Хэш меняется → резолв + проверка |
| Симлинк добавлен/убран | Хэш меняется → пересборка |
| Симлинк перемещён между группами | Оба хэша меняются → обе пересобираются |
| DNS вернул те же IP | Маршруты не перезагружаются |
| Все .list убраны из группы | Таблица очищается |
| Каталог группы удалён | Cleanup находит осиротевший state → flush |
## Multipath
Если в файле `gateway` несколько строк, генерируются multipath маршруты:
```
route replace 1.2.3.4 table 100 nexthop via 91.232.225.12 weight 1 nexthop via 91.232.225.112 weight 1
```
Ядро распределяет трафик per-flow (хэш src/dst IP + порты).
Все пакеты одного соединения идут через один gateway.
Разные соединения балансируются по весам.
## Архитектура маршрутизации
```
ip rule show:
120: from all lookup 12 ← [ogw]
1120: from all lookup 112 ← [egw]
32766: from all lookup main ← default route
Пакет к dst 1.2.3.4:
→ lookup table 12: есть маршрут? → via 91.232.225.12
→ lookup table 112: есть маршрут? → via 91.232.225.112
→ lookup main: default route
```
Правила без `iif` — действуют на весь трафик (и транзитный, и локальный).
В таблицах нет default route — несовпавший трафик проваливается в main.
## State
Состояние хранится в `.state/` (вне git):
```
.state/
├── routes.d/
│ ├── egw/
│ │ ├── hash # MD5 содержимого .list файлов
│ │ ├── table # номер таблицы (для cleanup)
│ │ └── resolved # sorted список IP после резолва
│ └── ogw/
│ └── ...
└── routes6.d/
└── ...
```
## Добавление нового маршрута
### Новая группа
```bash
mkdir routes.d/mygroup
echo '10.0.0.1' > routes.d/mygroup/gateway
echo '50' > routes.d/mygroup/table
ln -s /path/to/domains.list routes.d/mygroup/domains.list
./route-update.sh
```
### Добавить список в существующую группу
```bash
ln -s /root/egw-route/newlist.list routes.d/ogw/newlist.list
./route-update.sh
```
### Переместить список между группами
```bash
mv routes.d/ogw/youtube.list routes.d/egw/
./route-update.sh # обе группы пересоберутся
```
## Сравнение со старым подходом
| | update_egw.sh (старый) | route-update.sh (новый) |
|---|---|---|
| Механизм | ipset + iptables mangle + fwmark | ip route + ip rule |
| Конфигурация | Переменные в скрипте | Файлы в каталогах |
| Добавление маршрута | Копировать весь скрипт | Создать каталог + симлинки |
| DNS-резолв | Последовательный dig | Bulk async adnshost |
| IPv4/IPv6 | Отдельные скрипты | Единый скрипт |
| Multipath | Нет | Несколько строк в gateway |
| Обнаружение изменений | diff файла целиком | MD5 хэш + diff resolved |
| Отладка | iptables -L, ipset list | ip route show table N |
## Зависимости
- `ip` (iproute2) — управление маршрутами
- `adnshost` (пакет `adns`) — bulk async DNS резолв
- `dig` — fallback для CNAME-доменов
- `md5sum` — хэширование
- Стандартные утилиты: grep, sed, sort, awk, find
## Альтернативные решения
### OpenWrt PBR
Наиболее близкий аналог. Использует nftables sets + dnsmasq nftset.
Реактивный подход: IP добавляются по мере DNS-запросов клиентов.
Привязан к OpenWrt (UCI, procd).
### dnsmasq + ipset/nftset
Классический подход для домашних роутеров.
`ipset=/domain.com/SETNAME` — IP попадают в set при DNS-запросах.
Плюс: ловит CDN-ротации в реальном времени.
Минус: set пустой до первого запроса, stale IP накапливаются.
### nbrpc (name-based-routing-policy-controller)
https://github.com/mk-fg/name-based-routing-policy-controller
Адаптивный контроллер на Python. Принципиально другой подход:
не "маршрутизируй эти домены через VPN", а "проверяй доступность
и переключай на VPN только заблокированные".
- Периодически проверяет HTTP-доступность каждого домена напрямую и через VPN
- Если напрямую не работает — добавляет IP в nftables set
- Если снова доступен — убирает маршрут
- SQLite для истории, grace period от флаппинга
- Политика `pick` — маршрутизирует только заблокированные IP из CDN-пула
Подходит как дополнение: route-update.sh предзагружает известные списки,
nbrpc может адаптивно обнаруживать новые блокировки.
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