# IPsec и IKEv2 - стандарт корпоративных VPN _Протоколы · LinuxLab Knowledge Base_ **TL;DR:** IPsec - L3-VPN-стандарт. ESP инкапсулирует и шифрует, IKEv2 обменивается ключами. Tunnel-mode даёт новый IP-заголовок для site-to-site; transport-mode - host-to-host. На Linux это strongSwan. ## Зачем IPsec Стандарт корпоративных и operator-grade VPN с 90-х. Работает на L3, не зависит от прикладного протокола. Поддерживается у всех вендоров: Cisco, Juniper, Mikrotik, Linux, Windows, macOS, iOS - совместимость без танцев. Сегодня живёт в: - Site-to-site между дата-центрами и облаками. AWS VPN и Azure VPN Gateway - это IPsec под капотом - Operator-grade VPN у телекомов и банков - Нативный VPN на iOS и macOS (галочка в настройках, без приложения) - "Always-on" корп-VPN с EAP-аутентификацией Минус один: исторически сложен. strongSwan-конфиг даже на простой кейс - десятки строк. У [[wireguard|WireGuard]] на ту же задачу уйдёт строк пять. Но IPsec даёт сертификаты, EAP, mode-config, IKEv2 mobility (MOBIKE) и полноценную PKI. ## Архитектура: ESP, AH, IKE Три протокола: - **ESP** (Encapsulating Security Payload, IP-protocol 50) - шифрует и аутентифицирует payload. Используется почти всегда. - **AH** (Authentication Header, IP-protocol 51) - только аутентификация без шифрования. Ломает NAT (включает IP-заголовок в HMAC). Почти нигде не встречается. - **IKE** (Internet Key Exchange, UDP 500/4500) - переговоры: аутентификация peers, генерация ключей для ESP. **IKEv1** (1998) устарел; **IKEv2** (2005, RFC 7296) - современный и проще. ## Transport vs Tunnel mode ``` Transport mode (host-to-host): [IP] [ESP] [TCP/UDP/payload] ^ оригинальный IP сохраняется Tunnel mode (site-to-site): [new-IP] [ESP] [original-IP] [TCP/UDP/payload] ^ внешний IP - между gateway'ами ^ внутренний IP - конечные хосты ``` - **Transport** - peer-to-peer на одном уровне. Применяется в host-to-host-сценариях или с GRE поверх. - **Tunnel** - gateway-to-gateway или client-to-gateway. Когда говорят просто "VPN" - почти всегда имеют в виду tunnel-mode IPsec. ## IKEv2: два обмена Минимальный handshake укладывается в **4 пакета**: 1. **IKE_SA_INIT**: peers договариваются о crypto suite (encryption, PRF, integrity, DH-group), делают Diffie-Hellman, обмениваются nonce'ами. Производит SK_d (parent key). 2. **IKE_AUTH**: аутентификация (сертификаты/PSK/EAP), обмен identity, создание первого CHILD_SA (= ESP-туннель). Дополнительно: - **CREATE_CHILD_SA** - обновление ключей (rekey) или новый туннель в той же IKE_SA. - **INFORMATIONAL** - DPD (dead peer detection) и удаление SA. IKEv1 в main mode требовал 6 пакетов, aggressive mode - 3, но с известными уязвимостями. ## strongSwan - основной демон на Linux ```bash apt install strongswan strongswan-pki libcharon-extra-plugins ``` Современный конфиг - **swanctl** (взамен старого `ipsec.conf` через starter): `/etc/swanctl/conf.d/site-a-to-b.conf`: ```hcl connections { site-a-to-b { version = 2 local_addrs = 203.0.113.10 remote_addrs = 198.51.100.20 local { auth = pubkey certs = my-cert.pem id = "CN=site-a" } remote { auth = pubkey id = "CN=site-b" } children { net { local_ts = 10.10.0.0/24 remote_ts = 10.20.0.0/24 esp_proposals = aes256gcm16-prfsha384-modp3072 start_action = trap # автостарт по первому пакету } } proposals = aes256-sha384-modp3072 } } ``` Загрузить и запустить: ```bash swanctl --load-all swanctl --initiate --child net swanctl --list-sas # активные туннели ``` ## NAT traversal (NAT-T) ESP это IP-protocol 50, а не TCP или UDP. NAT'ы и фаерволы его обычно дропают. На этот случай придумали **NAT-T**: ESP заворачивается в **UDP-4500**, выглядит снаружи как обычный UDP-пакет и спокойно проходит через NAT. IKE сам это детектит: - Сначала handshake идёт на UDP-500 - Если по пути виден NAT - оба peer'а переключаются на UDP-4500 для ESP В фаерволе нужно открыть **UDP 500 + UDP 4500** (плюс ESP-50, если NAT'а нет). ## EAP для клиентов Корпоративный кейс: тысячи клиентов с username/password или Active Directory. IPsec их аутентифицирует через **EAP** (RFC 3748): - **EAP-MSCHAPv2** - пароль (legacy, но всё ещё работает с AD) - **EAP-TLS** - клиентский сертификат, как у [[openvpn|OpenVPN]] - **EAP-RADIUS** - strongSwan делегирует решение RADIUS-серверу Связка IKEv2 + EAP - это нативный VPN на iOS, macOS и Windows 10+. В этом редком сценарии IPsec оказывается проще конкурентов: ставить ничего не надо, всё уже встроено в систему. ## strongSwan vs Libreswan vs racoon - **strongSwan** - активная разработка, лучшая поддержка IKEv2, EAP и плагинов. По умолчанию на современных Debian и Ubuntu. - **Libreswan** - fork от FreeS/WAN, дефолт на RHEL и CentOS. По фичам близок к strongSwan, синтаксис конфига чуть отличается. - **racoon (ipsec-tools)** - давно мёртв. Не используй. ## Сравнение с другими VPN | Признак | IPsec/IKEv2 | [wireguard](/kb/wireguard.md) | [openvpn](/kb/openvpn.md) | |---------|-------------|---------------|-------------| | Стандарт RFC | да (десятки) | нет (черновик) | нет | | Где живёт | в ядре + IKE userspace | в ядре | userspace | | Сертификаты/PKI | да | нет | да | | EAP / RADIUS | да | нет | да | | NAT-T | да (UDP 4500) | работает изначально | UDP/TCP | | iOS/macOS native | да | нужно приложение | нужно приложение | | Cisco/Juniper interop | да | нет | нет | | Конфиг сложность | высокая | минимальная | средняя | | Performance | в ядре, быстрая | в ядре, быстрая | userspace, медленнее | ## Когда что-то пошло не так - **`establishing CHILD_SA failed`** - traffic-selector mismatch. `local_ts/remote_ts` у одной стороны не совпадает с `remote_ts/local_ts` у другой. Подсети должны зеркально отражаться. - **`IKE_AUTH failed: AUTHENTICATION_FAILED`** - неверная PSK, неправильный CN в сертификате или плохие EAP-credentials. Проверь `id =` с обеих сторон. - **NAT-T не активируется, хотя NAT по пути есть** - peer его не замечает. Лечится `forceencaps = yes`: трафик принудительно идёт на UDP-4500. - **`peer not responding`** - UDP 500/4500 где-то заблокирован. Снимай дамп: `tcpdump -i any -nn 'udp port 500 or udp port 4500'`. - **MTU-issues, средние пакеты теряются** - добавь `tfc_padding` или явный `fragmentation = yes` в IKE. В ядре полезно зажать MSS: `iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu`. - **Один туннель поднимается, второй между теми же хостами - нет**. Скорее всего конфликт SPI или overlap у traffic-selector'ов. `ip xfrm state` покажет SA, `ip xfrm policy` - selectors. ## Команды ```bash swanctl --list-conns ``` Все загруженные коннекшены: что strongSwan сейчас держит как конфиг ```bash swanctl --list-sas ``` Активные SA: реально ли поднялись туннели ```bash swanctl --initiate --child net ``` Поднять CHILD_SA вручную, не дожидаясь первого пакета ```bash ip xfrm state ``` ESP SA на уровне ядра: SPI, src/dst и сами ключи (без значений) ```bash ip xfrm policy ``` Selectors: какие подсети уходят в IPsec. Сравнивать со swanctl ```bash tcpdump -i any -nn 'udp port 500 or udp port 4500 or proto 50' ``` Дамп IKE-handshake и ESP-пакетов на проводе ```bash openssl pkcs12 -info -in client.p12 ``` Распарсить P12 перед импортом в iOS/macOS: покажет CN и расширения ## См. также - [WireGuard - современный UDP-VPN](/kb/wireguard.md) - [OpenVPN - TLS-based VPN](/kb/openvpn.md) - [GRE-туннели и IPIP - point-to-point поверх IP](/kb/gre-tunnel.md) - [MTU и Path MTU Discovery (PMTUD)](/kb/mtu-and-pmtud.md) - [NAT и masquerade](/kb/nat.md)