mirror of
https://github.com/rekryt/iplist.git
synced 2026-08-28 04:31:46 +00:00
124 lines
7 KiB
Markdown
124 lines
7 KiB
Markdown
# Замена пересекающихся 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"]
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||

|
||
|
||
Ключи `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).
|