iplist/docs/REPLACE.md

124 lines
7 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.

# Замена пересекающихся CIDR зон
[For English: REPLACE.en.md](REPLACE.en.md)
Некоторые CIDR зоны принадлежат сразу нескольким порталам (например,
`172.217.0.0/16` есть и у `google`, и у `yandex` — whois не может их
разделить автоматически). Чтобы не маршрутизировать чужой трафик
при выгрузке адресов одного портала, в его конфиге можно
задать «точечные» замены.
## Синтаксис
```json
{
...
"replace": {
"cidr4": {
"172.217.0.0/16": ["172.217.17.206/32", "172.217.17.207/32", "172.217.18.0/24"]
},
"cidr6": {
"2001::/32": ["2001:4860::/32"]
}
}
}
```
![Image](https://github.com/user-attachments/assets/6d04bd96-fb47-4da9-ae16-f2ba71cb49cc)
Ключи `replace.cidr4` / `replace.cidr6` — CIDR-зоны, которые **надо убрать**
из выдачи `cidr4`/`cidr6` этого портала. Значения — массивы CIDR-зон или
IP-адресов с маской, которые **подставляются вместо ключевой зоны**.
Некорректная структура (значение не `object` / не `array` / не строка)
приводит к ошибке загрузки и остановке сервера — чтобы опечатки не
молчали.
## Две фазы работы
### Reload-time (при обновлении данных портала)
В конце каждого цикла `reload`, если выставлен
`SYS_REPLACE_ESCALATE_IPS=true` (по умолчанию `true`), сервис проходит
по ключам `replace.cidr4`/`replace.cidr6` и **добавляет** в value-массивы
все `ip4`/`ip6` портала, попадающие в ключевую зону, с маской `/32`
(или `/128` для IPv6). К каждому value-массиву применяется
`minimizeSubnets` — поглощённые админом более узкой зоны записи
исчезают, повторный `reload` не плодит дубликатов. Результат
сохраняется в конфиг.
Таким образом value-массивы растут со временем по мере того, как
DNS-запросы находят новые IP портала внутри ключевых зон.
### View-time (при ответе HTTP-клиенту)
Все форматы, **кроме `json`**, выкидывают из `cidr4`/`cidr6` ключевые
зоны `replace` и подставляют вместо них value-массивы. После агрегации
между сайтами применяется `minimizeSubnets`, дубликатов в ответе нет.
`json` намеренно возвращает сырое состояние портала вместе с полем
`replace` — клиент может сам решать, как его интерпретировать.
## `SYS_REPLACE_AGGREGATE_SUBNETS` — агрегация без потерь
По умолчанию `false`.
Если `SYS_REPLACE_AGGREGATE_SUBNETS=true`, вместо `minimizeSubnets`
value-массивы прогоняются через **supernet-агрегацию**:
- 256 подряд идущих `/32` свёртываются в один `/24`;
- два смежных `/24` — в `/23`;
- и т.д.
Агрегация ограничена префиксом родительского ключа — итоговый блок
никогда не будет шире или равен самому ключу (иначе получился бы
бессмысленный `"1.0.0.0/8": ["1.0.0.0/8"]`).
Это **lossless**: покрываемые адреса не меняются, только форма записи.
Имеет смысл включать для порталов с тысячами IP-адресов (Adobe,
Google и т.п.), где без агрегации value-массив разрастается в
тысячи `/32` записей.
## `SYS_REPLACE_COLLAPSE_THRESHOLD_*` — плотностное схлопывание (lossy)
Четыре параметра, все по умолчанию `0` (выключены):
| ENV | Уровень | Bucket |
| --------------------------------------- | ---------- | ------ |
| `SYS_REPLACE_COLLAPSE_THRESHOLD_IP4_24` | v4 узкий | `/24` |
| `SYS_REPLACE_COLLAPSE_THRESHOLD_IP4_16` | v4 широкий | `/16` |
| `SYS_REPLACE_COLLAPSE_THRESHOLD_IP6_64` | v6 узкий | `/64` |
| `SYS_REPLACE_COLLAPSE_THRESHOLD_IP6_32` | v6 широкий | `/32` |
Значение — **минимальное количество покрытых адресов** в bucket'е.
Если в `/24` (для `_IP4_24`) покрыто ≥ N адресов, весь `/24`
считается принадлежащим порталу и заменяется одной зоной целиком.
Аналогично для `/16`, `/64`, `/32`.
Порядок применения — «пирамидой»:
1. Сначала срабатывает **узкий** уровень (`/24` или `/64`) — раздувает
плотные buckets до полных.
2. Затем **широкий** (`/16` или `/32`) считает покрытие уже с учётом
инфлейтнутых результатов и, если общая плотность внутри `/16`/`/32`
превышает порог, забирает и эту зону целиком.
Каждый уровень **пропускается**, если префикс родительского ключа
в `replace.cidr4`/`cidr6` уже `≥` размеру bucket'а — внутри узкого
родителя нет места для bucket'а такого же или большего размера.
**Это `lossy`**: в ответ попадут и соседние адреса тех же зон,
не принадлежащие порталу (обычно соседи по CDN или датацентру).
Пороги задают компромисс между точностью и размером вывода.
Работает только в связке с `SYS_REPLACE_AGGREGATE_SUBNETS=true`.
## Массовая разметка порталов
Если уже есть список «широких» CIDR-зон, которые встречаются у
нескольких порталов, можно одним скриптом разом посеять пустые
ключи в `replace.cidr4` у всех подходящих порталов — дальше
`reload` под включённой эскалацией сам заполнит value-массивы.
Инструмент и инструкция: [intersection/README.md](intersection/README.md).