Сети для самых маленьких. Часть 19: IPsec и IKEv2
Всё, что мы разбирали до сих пор, ходило по сети открытым текстом: заголовки, данные, пароли в PAP из четвёртой части, запросы DNS. Защиту мы встречали только выше транспорта — TLS, протокол шифрования внутри TCP-соединения, на котором работает HTTPS: он защищает данные одного приложения, и только если приложение его использует. IPsec делает защиту на сетевом уровне: шифрует и подписывает IP-пакеты целиком, так что приложения о ней не знают, а защищённым оказывается всё — любой протокол, любой порт. На IPsec построены туннели между офисами, подключение сотрудников к корпоративной сети и, как увидим в следующей части, большинство «VPN» в настройках телефона.
IPsec — это два слоя. IPsec в узком смысле — формат защищённых пакетов и правила их обработки: что шифровать, каким ключом, как проверять. IKE — Internet Key Exchange, протокол, по которому две стороны договариваются об алгоритмах, проверяют друг друга и вырабатывают ключи для первого слоя. Разберём снизу вверх.
Что защищает IPsec и как
Два протокола, оба — Next Header / Protocol в заголовке IP:
- ESP (Encapsulating Security Payload, протокол 50) — шифрование и проверка целостности. Используется практически всегда.
- AH (Authentication Header, протокол 51) — только целостность и подлинность, без шифрования, причём подпись покрывает и заголовок IP. Из-за этого AH несовместим с NAT, который заголовок меняет, и сегодня почти не встречается: ESP с проверкой целостности делает всё то же, кроме защиты самого IP-заголовка, которая никому не нужна.
И два режима, которые решают, что именно заворачивается:
исходный пакет: ┌─────────┬───────────────────────┐
│ IP │ TCP + данные │
└─────────┴───────────────────────┘
транспортный режим: ┌─────────┬─────┬────────────────────────┬───────┬─────┐
│ IP │ ESP │ TCP + данные │ ESP │ ICV │
│ (тот же)│ hdr │ ░░░ зашифровано ░░░░░░ │ trail │ │
└─────────┴─────┴────────────────────────┴───────┴─────┘
туннельный режим: ┌─────────┬─────┬────────┬───────────────┬───────┬─────┐
│ новый │ ESP │ IP │ TCP + данные │ ESP │ ICV │
│ IP │ hdr │ ░░░░░░░ зашифровано ░░░░░░░░░░ │ │
└─────────┴─────┴────────┴───────────────┴───────┴─────┘
Транспортный защищает только данные пакета, оставляя исходный заголовок IP: адреса видны, и защищена связь между двумя хостами. Туннельный шифрует исходный пакет целиком, включая его адреса, и приписывает новый заголовок IP с адресами шлюзов. Это режим для шлюз-шлюз (два офиса) и для удалённого доступа: внутренние адреса 192.168.x.x спрятаны внутри, а снаружи видны только адреса концов туннеля.
Пакет ESP
┌───────────────────┐
│ SPI (4) │ какой SA: по нему получатель находит ключи и алгоритмы
│ Sequence (4) │ номер пакета, растёт на 1: защита от повторов
├───────────────────┤
│ IV │ вектор инициализации для шифра
│ данные ░░░░░░░░░░ │ зашифровано: исходный пакет (туннель) или сегмент (транспорт)
│ padding ░░░░░░░░░ │ выравнивание до блока шифра
│ pad len │ next hdr│ next header: 4 = IPv4 внутри, 41 = IPv6, 6 = TCP (транспорт)
├───────────────────┤
│ ICV │ код целостности: подпись всего выше ключом целостности
└───────────────────┘
Получатель: по адресу назначения и SPI находит SA (ниже), проверяет, что Sequence ещё не видели (скользящее окно, обычно 64 или больше номеров), проверяет ICV ключом целостности, расшифровывает, читает next header в самом конце и узнаёт, что внутри — IPv4-пакет, который надо маршрутизировать дальше, или сегмент TCP для самого себя. Порядок важен: сначала целостность, потом расшифровка, чтобы не тратить время на подделку и не давать атакующему скармливать шифру мусор.
Алгоритмы: сегодня это AES-GCM (шифрование и целостность одним ключом, ICV 16 байт) или ChaCha20-Poly1305; старая связка — AES-CBC плюс HMAC-SHA256. 3DES, MD5, SHA1 — в списке «не использовать».
Накладные расходы туннельного режима с AES-GCM — около 50–60 байт на пакет (20 новый IP, 8 ESP, 8 IV, 16 ICV, выравнивание), плюс 8, если ESP в UDP. Поэтому у туннеля MTU 1400–1440, и MSS clamping из восьмой части в правилах для туннелей стоит почти всегда.
SA, SPI, SPD
Security Association — одностороннее соглашение «между A и B, для пакетов с таким SPI, такой алгоритм, такие ключи, такой режим, срок жизни столько-то секунд или байт». Одностороннее — значит, на каждое направление своя SA, и у туннеля их пара. SPI (32 бита) — номер, который получатель выбирает сам при создании SA, и отправитель ставит его в заголовок ESP; так одна машина различает сотни туннелей к ней.
Хранятся SA в SAD (базе SA). Рядом — SPD, база политик: правила «трафик с такими адресами, протоколом, портами — защищать такой SA / пропускать как есть / отбрасывать». Селекторы политик — это и есть то, что принято называть «какие сети ходят через туннель». Когда пакет уходит из машины, стек сверяет его с SPD; если политика «защищать», а SA ещё нет, стек просит IKE её создать и держит пакет, пока та не появится.
В Linux это подсистема xfrm, и всё перечисленное видно:
$ sudo ip xfrm state # SAD
src 198.51.100.2 dst 203.0.113.5
proto esp spi 0xc1a2b3d4 reqid 1 mode tunnel
replay-window 32 flag af-unspec
aead rfc4106(gcm(aes)) 0x... 128
anti-replay context: seq 0x0, oseq 0x1a, bitmap 0x00000000
src 203.0.113.5 dst 198.51.100.2
proto esp spi 0x9e8f7a6b reqid 1 mode tunnel
...
$ sudo ip xfrm policy # SPD
src 192.168.1.0/24 dst 10.0.0.0/24
dir out priority 375423
tmpl src 198.51.100.2 dst 203.0.113.5
proto esp reqid 1 mode tunnel
src 10.0.0.0/24 dst 192.168.1.0/24
dir in priority 375423
...
Две SA с разными SPI на два направления, политика «из 192.168.1.0/24 в 10.0.0.0/24 — в туннель между шлюзами», счётчик oseq — сколько пакетов ушло.
Ключи в SA откуда-то взялись. Можно вписать их руками (ip xfrm state add … key 0x…), и это полезно, чтобы понять механику, но в жизни так не делают: ключи должны быть случайными, меняться, и обе стороны должны проверить друг друга. Это работа IKE.
IKEv2
IKEv2 (RFC 7296) — протокол поверх UDP 500 (и 4500, об этом ниже), по которому стороны:
- договариваются об алгоритмах и вырабатывают общий секрет по Диффи-Хеллману;
- проверяют подлинность друг друга;
- создают SA для ESP (в терминах IKE — Child SA) и потом пересоздают их по сроку.
Первая версия, IKEv1 1998 года, делала то же самое за шесть-девять сообщений в двух фазах с разными режимами и не умела ни NAT, ни EAP, ни смену адреса без дополнений; IKEv2 всё это встроил и уложил в четыре сообщения. IKEv1 жив в старом оборудовании, но новые туннели на нём не строят.
IKE_SA_INIT: договориться и обменяться ключами
инициатор ответчик
│ │
├── IKE_SA_INIT ──────────────────────────────────────────────────────►│
│ SAi1: предложения (шифр, PRF, целостность, группа DH) │
│ KEi: открытое значение DH, Ni: случайное число │
│ [NAT_DETECTION_*: хеши своих адреса и порта] │
│ │
│◄── IKE_SA_INIT ──────────────────────────────────────────────────────┤
│ SAr1: выбранное предложение, KEr, Nr, [CERTREQ], [NAT_DETECTION_*] │
│ │
│ обе стороны: SKEYSEED = prf(Ni | Nr, g^ir) │
│ из него SK_d, SK_ai, SK_ar, SK_ei, SK_er, SK_pi, SK_pr │
│ дальше всё шифруется и подписывается │
Два сообщения открытым текстом. Инициатор перечисляет, что умеет (например: AES-GCM-256, PRF HMAC-SHA256, DH группа 19 — эллиптическая кривая P-256, или 14 — modp2048, или 31 — Curve25519), прилагает свою половину обмена Диффи-Хеллмана и случайное число. Ответчик выбирает один набор и прилагает свои. После этого у обеих сторон есть общий секрет g^ir, которого не было в эфире, и из него с помощью PRF (псевдослучайной функции на основе HMAC) выводится семь ключей: для вывода дальнейших ключей (SK_d), для целостности и шифрования IKE-сообщений в каждую сторону (SK_a*, SK_e*) и для аутентификации (SK_p*).
Защита от затопления: ответчик, видя слишком много незавершённых обменов, может вместо ответа прислать COOKIE и потребовать повторить запрос с ним — состояние он до этого не заводит, как SYN cookies в TCP.
Ключевое свойство: пока никто никого не проверил. Общий секрет есть и с самозванцем, стоящим посередине. Проверка — следующий шаг.
IKE_AUTH: доказать, кто ты, и создать первую Child SA
инициатор ответчик
│ │
├── IKE_AUTH (зашифровано SK_ei) ─────────────────────────────────────►│
│ IDi: кто я (адрес, FQDN, e-mail, DN сертификата) │
│ [CERT]: мой сертификат │
│ AUTH: подпись первого моего сообщения + Nr + prf(SK_pi, IDi) │
│ SAi2: предложения для ESP, TSi, TSr: селекторы трафика │
│ [CP: дай мне адрес и DNS] │
│ │
│◄── IKE_AUTH (зашифровано SK_er) ─────────────────────────────────────┤
│ IDr, [CERT], AUTH: подпись своего первого сообщения + Ni + … │
│ SAr2, TSi, TSr (возможно, суженные), [CP: адрес, DNS] │
│ │
│ IKE SA установлена, первая пара Child SA (ESP) установлена │
AUTH — то, что связывает ключи с личностью. Каждая сторона подписывает своё первое сообщение IKE_SA_INIT (то, что ушло открытым текстом), чужое случайное число и хеш своего идентификатора. Самозванец посередине подменил бы значения DH в первом сообщении, и подпись не сошлась бы. Чем подписывают:
- PSK, общий секрет: AUTH = prf(prf(PSK, «Key Pad for IKEv2»), данные). Просто, удобно между двумя шлюзами, но одна строка на обе стороны, которую нужно как-то передать и периодически менять.
- Сертификаты: подпись закрытым ключом RSA или ECDSA, сертификат в CERT, доверие через общий удостоверяющий центр. Стандарт для шлюз-шлюз в организациях и обязателен для сервера удалённого доступа: клиенты Windows, iOS, Android требуют у сервера сертификат с именем, совпадающим с адресом подключения.
- EAP для удалённого доступа: инициатор не присылает AUTH в первом IKE_AUTH, и обмен растягивается на несколько пар сообщений, внутри которых идёт EAP — тот самый протокол запросов-ответов из третьей части про Wi-Fi: EAP-MSCHAPv2 (логин и пароль, проверяется у сервера или через RADIUS, протокол, которым сетевое оборудование спрашивает у центральной базы, пускать ли пользователя) или EAP-TLS (сертификат пользователя). По итогам EAP обе стороны получают ключ MSK, и последняя пара IKE_AUTH несёт AUTH, вычисленный с ним. Сервер при этом всё равно подтверждает себя сертификатом.
В том же обмене создаётся первая Child SA — пара SA для ESP, по предложению SAi2 (шифр для ESP, может отличаться от IKE), и селекторы трафика TSi/TSr: инициатор говорит «я хочу защищать трафик от 192.168.1.0/24 к 10.0.0.0/24», ответчик соглашается или сужает до того, что разрешено ему. Сужение — частая причина «туннель поднялся, а пинг не идёт»: селекторы на двух концах не совпали, и SA создалась для пересечения, куда ваш трафик не попадает.
CP, configuration payload, — для удалённого доступа: клиент просит внутренний адрес, DNS, домен, и сервер их выдаёт, как DHCP, но внутри IKE. Так ноутбук получает 10.0.5.17 «внутри» корпоративной сети.
CREATE_CHILD_SA и INFORMATIONAL
Дальше IKE SA живёт долго (часы) и служит защищённым каналом для управления:
- CREATE_CHILD_SA — создать ещё одну пару ESP SA (для другого набора селекторов) или пересоздать существующую по истечении срока — rekey. Ключи ESP живут час или гигабайты и меняются незаметно для трафика: новая SA создаётся до того, как удалена старая. При желании в rekey включают новый обмен DH (PFS, perfect forward secrecy): компрометация ключа IKE не раскроет прошлые ESP-ключи.
- INFORMATIONAL — удаление SA, уведомления и две важные вещи. DPD (dead peer detection): пустое INFORMATIONAL, на которое другая сторона обязана ответить; нет ответа несколько раз — пир мёртв, SA удаляются, туннель переподнимается. MOBIKE (RFC 4555): клиент, у которого сменился адрес (телефон перешёл с Wi-Fi на сотовую сеть), шлёт UPDATE_SA_ADDRESSES, и все SA переезжают на новый адрес без нового рукопожатия. Это то, что делает IKEv2 удобным на мобильных.
NAT-T: IPsec через NAT
NAT из шестой части и ESP несовместимы с двух сторон: NAT переписывает адреса, а у ESP нет портов, по которым он мог бы вести таблицу трансляций; два клиента за одним NAT с ESP к одному серверу вообще не различимы. Поэтому в IKE_SA_INIT есть NAT detection: каждая сторона присылает хеш от своего адреса и порта, как она их видит. Получатель считает тот же хеш от адреса и порта, с которых пакет пришёл. Не совпало — по дороге NAT.
Тогда обе стороны переходят на UDP 4500: IKE продолжает там же с четырьмя нулевыми байтами впереди (non-ESP marker), а ESP-пакеты заворачиваются в UDP на тот же порт — UDP-encapsulated ESP. У NAT появляются порты, у клиентов за одним NAT — разные внешние порты, всё работает. Цена — 8 байт UDP на пакет и необходимость держать запись NAT живой: клиент шлёт keepalive, однобайтовый UDP-пакет 0xFF, каждые 20 секунд, ровно по причинам из девятой части.
$ sudo tcpdump -i eth0 -n 'udp port 500 or udp port 4500 or esp'
IP 198.51.100.2.500 > 203.0.113.5.500: isakmp: parent_sa ikev2_init[I]
IP 203.0.113.5.500 > 198.51.100.2.500: isakmp: parent_sa ikev2_init[R]
IP 198.51.100.2.4500 > 203.0.113.5.4500: NONESP-encap: isakmp: child_sa ikev2_auth[I]
IP 203.0.113.5.4500 > 198.51.100.2.4500: NONESP-encap: isakmp: child_sa ikev2_auth[R]
IP 198.51.100.2.4500 > 203.0.113.5.4500: UDP-encap: ESP(spi=0xc1a2b3d4,seq=0x1), length 132
IP 203.0.113.5.4500 > 198.51.100.2.4500: UDP-encap: ESP(spi=0x9e8f7a6b,seq=0x1), length 132
IP 198.51.100.2.4500 > 203.0.113.5.4500: isakmp-nat-keep-alive
tcpdump называет IKE старым именем isakmp. Видно всё, о чём была статья: INIT на 500, обнаружен NAT, AUTH уже на 4500 с маркером, ESP в UDP с SPI и номерами, keepalive. Что внутри ESP, не видно никому: ни адресов, ни портов, ни протокола — только размер и частота пакетов.
Файрволу для IPsec нужно: UDP 500, UDP 4500 и, если NAT нет, протокол ESP (50). AH (51) — если кто-то всё ещё его использует.
Политики или маршруты
Есть два способа решить, какой трафик идёт в туннель, и путаница между ними — вторая по частоте причина нерабочих туннелей после селекторов.
Policy-based — классика: SPD с селекторами перехватывает трафик, подходящий под политику, и отправляет в SA. Интерфейса у туннеля нет, в ip route он не виден, а трафик в него попадает, если совпал с селектором. Просто для «сеть A — сеть B», неудобно, когда нужны динамическая маршрутизация, несколько сетей или файрвол «на интерфейсе туннеля».
Route-based — туннель представлен интерфейсом (в Linux — XFRM interface или VTI), селекторы SA — «всё» (0.0.0.0/0), а что в туннель отправить, решает таблица маршрутов. Через такой интерфейс можно гонять протоколы динамической маршрутизации (OSPF внутри сети, BGP между сетями — роутеры по ним рассказывают друг другу о своих маршрутах, как мы упоминали в шестой части), ставить правила файрвола, видеть счётчики. Современные конфигурации чаще такие:
$ sudo ip link add ipsec0 type xfrm dev eth0 if_id 42
$ sudo ip link set ipsec0 up
$ sudo ip route add 10.0.0.0/24 dev ipsec0
и в SA/политиках указывается тот же if_id 42, чтобы стек связал интерфейс с туннелем.
Конфигурация и диагностика в strongSwan
Самая распространённая реализация IKE на Linux — strongSwan. Туннель шлюз-шлюз по сертификатам в swanctl.conf:
connections {
office-b {
remote_addrs = 203.0.113.5
local { auth = pubkey; certs = gw-a.pem; id = gw-a.example.com }
remote { auth = pubkey; id = gw-b.example.com }
children {
lan {
local_ts = 192.168.1.0/24
remote_ts = 10.0.0.0/24
esp_proposals = aes256gcm16-x25519
dpd_action = restart
start_action = start
}
}
proposals = aes256gcm16-prfsha256-x25519
version = 2
dpd_delay = 30s
}
}
Каждая строка — что-то из статьи: proposals — набор для IKE_SA_INIT, esp_proposals — для Child SA, local_ts/remote_ts — селекторы, auth = pubkey — сертификаты, dpd_delay — интервал INFORMATIONAL.
Состояние:
$ sudo swanctl --list-sas
office-b: #1, ESTABLISHED, IKEv2, 1a2b3c4d5e6f7a8b_i* 8b7a6f5e4d3c2b1a_r
local 'gw-a.example.com' @ 198.51.100.2[4500]
remote 'gw-b.example.com' @ 203.0.113.5[4500]
AES_GCM_16-256/PRF_HMAC_SHA2_256/CURVE_25519
established 1234s ago, rekeying in 12345s
lan: #1, reqid 1, INSTALLED, TUNNEL-in-UDP, ESP:AES_GCM_16-256
installed 1234s ago, rekeying in 2345s, expires in 3456s
in c1a2b3d4, 12345 bytes, 123 packets, 2s ago
out 9e8f7a6b, 23456 bytes, 234 packets, 2s ago
local 192.168.1.0/24
remote 10.0.0.0/24
ESTABLISHED — IKE SA есть, INSTALLED — Child SA в ядре, TUNNEL-in-UDP — сработал NAT-T, SPI на оба направления и счётчики. Если in растёт, а out нет — пакеты от нас в туннель не попадают: смотреть политики и маршруты. Если оба нули — трафик не подходит под селекторы. Если SA в состоянии CONNECTING — смотреть лог journalctl -u strongswan: там будет, на каком сообщении остановились (нет ответа на INIT — файрвол или адрес; AUTH failed — ключи, сертификаты, идентификаторы; NO_PROPOSAL_CHOSEN — не сошлись алгоритмы; TS_UNACCEPTABLE — селекторы).
Что запомнить
- IPsec защищает IP-пакеты: ESP (50) шифрует и подписывает, AH (51) только подписывает и почти не используется. Транспортный режим — между хостами, исходный заголовок остаётся; туннельный — весь пакет внутри нового, для шлюзов и удалённого доступа.
- SA — односторонняя: SPI, алгоритмы, ключи, срок; пара на туннель; SPD говорит, какой трафик куда. В Linux это
ip xfrm stateиip xfrm policy. - IKEv2: IKE_SA_INIT (алгоритмы, DH, nonces, открыто), IKE_AUTH (подпись первого сообщения через PSK, сертификат или EAP; селекторы; первая Child SA; адрес через CP), CREATE_CHILD_SA (ещё SA и rekey), INFORMATIONAL (DPD, удаление, MOBIKE).
- NAT ломает ESP; NAT-T обнаруживает NAT в INIT и уводит всё в UDP 4500 с keepalive раз в 20 секунд. Открывать UDP 500, 4500 и ESP.
- Туннель поднялся, а трафик не идёт — селекторы или политики/маршруты. MTU туннеля меньше на 50–70 байт, MSS clamping обязателен.
Дальше — Часть 20: VPN и прокси: что такое VPN в терминах уровней и интерфейсов, как на примере IKEv2 remote access клиент получает адрес, маршруты и DNS, что такое split tunneling и утечки DNS, как устроены HTTP CONNECT и SOCKS, и почему то, что называют VPN в расширениях браузера, обычно прокси.
Серия «Сети для самых маленьких»
- Модели OSI и TCP/IP — зачем сетевой стек разбит на уровни и как данные обрастают заголовками по пути пакета.
- Ethernet — кадр по байтам, MAC-адреса и как коммутатор решает, в какой порт отправить кадр.
- Wi-Fi — чем радио отличается от кабеля, как клиент подключается к точке доступа и как защищается эфир.
- PPPoE — как провайдер заворачивает сессию абонента в Ethernet и откуда берётся MTU 1492.
- IPv4: адреса, маски и подсети — как читать адрес и маску, делить сеть на подсети и решать, нужен ли шлюз.
- IPv4: заголовок, маршрутизация и NAT — как роутер выбирает маршрут для пакета и как вся квартира выходит в интернет с одного адреса.
- ARP — как по IP-адресу соседа узнать его MAC-адрес и почему соседа так легко подменить.
- ICMP — служебные сообщения IP, как на самом деле работают ping и traceroute и что ломается, когда их режут.
- UDP — восемь байт заголовка, порты и почему отправка без соединения иногда лучше.
- TCP — как из ненадёжного IP получается надёжный поток байтов и почему потеря пакета режет скорость.
- DHCPv4 — как машина без адреса получает адрес, маску, шлюз и DNS четырьмя сообщениями.
- DNS — как имя превращается в адрес: дерево зон, рекурсивные серверы, записи и кеширование.
- IPv6: адреса и заголовок — как записываются 128-битные адреса, какие они бывают и чем заголовок IPv6 отличается от IPv4.
- ICMPv6 и Neighbor Discovery — как в IPv6 без ARP и широковещания находят соседей и роутер.
- SLAAC — как хост собирает себе адрес IPv6 из объявления роутера без всякого сервера.
- DHCPv6 — зачем DHCP, если есть SLAAC, и как провайдер выдаёт домашнему роутеру целый блок сетей.
- VLAN — как один коммутатор и один кабель несут несколько независимых сетей.
- VXLAN — как растянуть сеть Ethernet через роутеры, завернув кадры в UDP.
- IPsec и IKEv2 (эта статья) — как шифруют пакеты на сетевом уровне и договариваются о ключах.
- VPN и прокси — куда уходит каждый пакет при включённом VPN и чем прокси отличается от VPN.
- OSPF — как роутеры одной сети сами строят общую карту и считают по ней кратчайшие пути.
- BGP — как десятки тысяч независимых сетей интернета договариваются о маршрутах.
- TLS и сертификаты — как защищают одно TCP-соединение и откуда браузер знает, что сервер настоящий.
Оставить комментарий могут только зарегистрированные пользователи.
Войдите на сайт или зарегистрируйтесь, чтобы оставить комментарий.