<a id="adc-snat-pool"></a>

# Настройка пула SNAT (SNAT Pool)

## Введение

Пул SNAT (SNAT Pool, Source Network Address Translation Pool) — это набор IP-адресов,
которые Angie ADC использует для подмены исходных IP-адресов клиентов
при передаче трафика на серверы. SNAT-пулы применяются в высоконагруженных средах
c большим количеством одновременно открытых сессий. Они позволяют обойти ограничение
на количество одновременных подключений (около 65000 на один IP-адрес). Ограничение связано с количеством
доступных клиентских сокетов (TCP- и UDP-портов), используемых для установки соединений.
SNAT-пулы могут использоваться как для L4-, так и для L7-балансировки.

#### NOTE
Также возможен подход, основанный на горизонтальном масштабировании
за счет установки нескольких Angie ADC и распределения трафика между ними.
Этот подход позволяет решить проблему не только с ограничением количества сессий, но и снять
ограничение на производительность системы, например когда при больших объемах трафика необходимо
обрабатывать данные на скоростях более 10 Гбит/с.

## Ручная настройка SNAT-пулов

Настройка вручную создаваемых SNAT-пулов происходит в три этапа:

1. Выбор пула адресов и их настройка.
2. Настройка маршрутизации.
3. Настройка правил балансировки.

Пример простой схемы c одним Angie ADC представлен на рисунке ниже:

![Схема c одним Angie ADC](../../_images/adc_help/image40_SNAT.png)

Рис. 2

### 1. Выбор пула адресов и их настройка

Размер пула адресов напрямую зависит от количества сессий, которые требуется одновременно поддерживать.
Чем больше сессий должно работать одновременно, тем больше IP-адресов должно входить в пул.

Выбор адресов условно свободный, можно использовать адреса из разных подсетей.
Мы не рекомендуем использовать чужие валидные адреса, чтобы избежать случайных пересечений с адресами клиентов.
Также лучше выбирать адреса не из произвольного диапазона, а выделить конкретную подсеть,
которая будет полностью использоваться в пуле. Это упростит дальнейшую настройку маршрутизации.

В примере ниже мы будем использовать подсеть `192.168.12.20/30`, включающую в себя четыре адреса.
Так как все четыре адреса будут использоваться в качестве адресов отправителя пакетов на участке сети
между Angie ADC и апстримами, то необходимо все эти четыре адреса назначить на сетевой интерфейс системы,
например на loopback-интерфейс.

Пример конфигурации представлен ниже. Адреса назначаются с маской `/32`. Это нужно,
чтобы система обрабатывала возвращающийся от серверов трафик и устанавливала полноценные соединения.

```console
angie-va#
angie-va# conf t
angie-va(config)# int lo
angie-va(config-if)# ip add 192.168.12.20/32
angie-va(config-if)# ip add 192.168.12.21/32
angie-va(config-if)# ip add 192.168.12.22/32
angie-va(config-if)# ip add 192.168.12.23/32
```

#### NOTE
В этом примере между апстримами и Angie ADC размещен маршрутизатор. Ситуация, когда апстримы и один
из интерфейсов Angie ADC размещены в одной подсети, будет рассмотрена отдельно (см. [Заключение](#adc-snat-pool-conclusion) ниже).

### 2. Настройка маршрутизации

В этом примере мы будем использовать протокол BGP для динамической маршрутизации. Настройка других протоколов динамической маршрутизации выполняется аналогично.

В BGP можно анонсировать все четыре адреса из пула независимо (четыре префикса с маской `/32`).
Однако BGP позволяет производить суммаризацию (агрегирование) анонсируемых префиксов,
поэтому есть способ лучше — выполнить анонс всего пула целиком в виде одного префикса
с маской `/30`.

Создадим агрегированный маршрут для всей подсети, используемой в качестве пула SNAT:

```console
angie-va# conf t
angie-va(config)# ip route 192.168.12.20/30 Null0
angie-va(config)# exi
angie-va# sho ip ro sta
Codes: K - kernel route, C - connected, L - local, S - static,
R - RIP, O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
T - Table, v - VNC, V - VNC-Direct, F - PBR,
f - OpenFabric, t - Table-Direct,
> - selected route, * - FIB route, q - queued, r - rejected, b - backup
t - trapped, o - offload failure
S>* 192.168.12.20/30 [1/0] unreachable (blackhole), weight 1, 00:01:21
```

Получившийся маршрут необходимо анонсировать по протоколу BGP:

```console
angie-va# conf t
angie-va(config)# router bg 1
angie-va(config-router)# add ipv4 un
angie-va(config-router-af)# red sta
angie-va(config-router-af)# end
angie-va#
```

Настройку BGP-соседей опустим для краткости (подробнее о настройке BGP см. [BGP-маршрутизация](https://angie.software//adc/docs/routing/routing_bgp/index.md#adc-bgp)).

#### NOTE
На представленной выше схеме BGP-соседом должен стать маршрутизатор Internal router, так как трафик от серверов будет возвращаться через него.

Убедимся, что BGP-соседи получают корректный маршрут:

```console
internal_router#sho ip bg
BGP table version is 6, local router ID is 192.168.0.150
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
r RIB-failure, S Stale, m multipath, b backup-path, f RT-Filter,
x best-external, a additional-path, c RIB-compressed,
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found
Network Next Hop Metric LocPrf Weight Path
*>i 192.168.12.20/30 192.168.0.147 0 100 0 ?
internal_router#
```

### 3. Настройка правил балансировки

Для распределения клиентов по адресам из пула можно использовать различные модули,
например Geo, Geo IP, Map, Split Clients. Рассмотрим несколько типовых сценариев
с описанием используемых модулей.

#### Сценарий A: использование модуля Split Clients

Стандартная ситуация, когда на Angie ADC попадают подключения пользователей из интернета напрямую.
Предполагается, что пользователи распределяются равномерно по всему пространству адресов.
В этом случае для настройки можно использовать [модуль Split Clients](https://angie.software//adc/docs/configuration_lb/reference/http/http_split_clients.md#adc-http-split-clients)
(применяется в контексте `http`). `Split_clients` работает как при L7-, так и при L4-балансировке.

Пример конфигурации:

```none
split_clients "${remote_addr}AAA" $variant {
    25% 192.168.12.20;
    25% 192.168.12.21;
    25% 192.168.12.22;
    25% 192.168.12.23;
}
```

#### NOTE
К адресу клиента добавлен текст `AAA`. Это нужно для изменения значения, выдаваемого хэш-функцией.
Если потребуется поменять распределение клиентов по адресам из пула, можно поменять добавляемый текст.

#### Сценарий B: использование модуля Map

Возможна ситуация, когда перед Angie ADC с точки зрения трафика, идущего от клиентов, расположен другой балансировщик:

![Схема c одним Angie ADC](../../_images/adc_help/image41_SNAT.png)

Рис. 3

Если этот балансировщик использует SNAT-пул, то переменная `remote_addr`
может не обеспечить достаточного разнообразия. Это может привести к коллизиям —
перекосу в распределении клиентов по адресам из пула SNAT.
Решить указанную проблему можно, например, используя [модуль Map](https://angie.software//adc/docs/configuration_lb/reference/http/http_map.md#adc-http-map), с помощью которого
можно в явном виде задать соответствие «старого» и «нового» адресов отправителя.
Метод `map` работает как при L7-, так и при L4-балансировке.

Пример конфигурации (восемь адресов из предыдущего пула привязываются к четырем адресам пула SNAT):

```nginx
map $remote_addr $variant {
    "10.10.10.0" "192.168.12.20";
    "10.10.10.1" "192.168.12.20";
    "10.10.10.2" "192.168.12.21";
    "10.10.10.3" "192.168.12.21";
    "10.10.10.4" "192.168.12.22";
    "10.10.10.5" "192.168.12.22";
    "10.10.10.6" "192.168.12.23";
    "10.10.10.7" "192.168.12.23";
}
```

#### Сценарий C: модуль Split Clients и хэш переменной $request_id

Для балансировки HTTP-трафика можно использовать подход, при котором не важно,
используется ли какой-либо NAT/PAT или прокси между реальным клиентом и Angie ADC.
Для распределения клиентов будет использоваться [модуль Split Clients](https://angie.software//adc/docs/configuration_lb/reference/http/http_split_clients.md#adc-http-split-clients)
и хэш от переменной `$request_id`. Значение переменной генерируется автоматически
и, по сути, является случайным числом.
Этот метод имеет ограниченную область применения — L7-балансировка для протокола HTTP.

Пример конфигурации:

```nginx
split_clients "${request_id}" $variant {
    25% 192.168.12.20;
    25% 192.168.12.21;
    25% 192.168.12.22;
    25% 192.168.12.23;
 }
```

#### NOTE
При использовании этого метода разные сессии одного и того же клиента могут привязываться к различным адресам из пула.
Это не должно быть большой проблемой, так как современные веб-системы используют
заголовок `X-Forwarded-For` для определения адреса клиента и не смотрят на адрес отправителя в IP-пакете.

Теперь с помощью директивы [proxy_bind](https://angie.software//angie/docs/configuration/modules/http/http_proxy.md#proxy-bind) укажем, где и как использовать указанное распределение клиентов.
Директиву можно задать в контекстах `http`, `server` или `location`.

Пример:

```console
location / {
proxy_pass http://backend ;
proxy_bind ${variant};
}
```

<a id="adc-snat-pool-conclusion"></a>

## Заключение

Предложенные выше способы ручного создания SNAT-пула позволят уверенно перешагнуть ограничение
в 65000 одновременных сессий как для L4-, так и для L7-балансировки. Однако следует все же понимать,
что ограничение количества одновременно поддерживаемых сессий зависит не только от количества сокетов,
но и от объемов использования целого ряда других системных ресурсов.

Чтобы адаптировать используемый подход к ситуации, когда один из интерфейсов Angie ADC расположен
в одной подсети с апстрим-серверами, потребуется следующее:

- не использовать динамическую маршрутизацию;
- настроить адреса из пула на физическом интерфейсе, а не на loopback-интерфейсе
  (адреса должны быть из той же IP-подсети, в которой расположены серверы);
- для обеспечения отказоустойчивости можно использовать несколько Angie ADC,
  а IP-адреса из пула указать как виртуальные дополнительные адреса для VRRP, вместо того чтобы назначать их
  непосредственно на физический интерфейс.
