VPN решает одну задачу администратора - дать пакетам пройти через недоверенную сеть так, будто хосты сидят в одном защищённом сегменте. На экзамене 303 вас спрашивают про три реализации, которые покрывают весь спектр подходов: OpenVPN (TLS поверх UDP, гибкий, на user-space), IPsec через strongSwan (стандарт ESP/IKE в ядре, классика site-to-site), и WireGuard (минималистичный туннель в ядре на современной криптографии). В этом уроке разберём, как каждое решение строит туннель, как ими управлять и когда что выбирать.

Как это работает
Любой VPN делает две вещи: аутентифицирует стороны и шифрует трафик между ними. Различаются они тем, на каком уровне живут и как договариваются о ключах.
OpenVPN - это процесс в пространстве пользователя. Он создаёт виртуальный интерфейс tun (L3, пакеты IP) или tap (L2, кадры Ethernet), а сам туннель строит поверх UDP (или TCP) с помощью TLS. То есть рукопожатие и обмен ключами - это обычный TLS-handshake с сертификатами, как у HTTPS, только данные внутри - не HTTP, а ваши IP-пакеты. Гибкость огромная (push-маршруты, DNS, любые порты), но за всё платит производительность: каждый пакет дважды пересекает границу ядро/user-space.
IPsec - это набор протоколов прямо в ядре. Шифрованием данных занимается ESP, а согласованием ключей - демон IKE (в нашем случае strongSwan, бинарь charon). IKE работает в две фазы. Фаза 1 (IKE_SA) поднимает защищённый управляющий канал между шлюзами и взаимно их аутентифицирует - по PSK или сертификатам. Фаза 2 (CHILD_SA) внутри этого канала согласует конкретные SA для трафика: какие подсети, какие алгоритмы. В IKEv2 (актуальный стандарт, IKEv1 - легаси) обе фазы быстрые и переживают смену IP клиента (MOBIKE).
WireGuard живёт в ядре (модуль wireguard, в mainline с 5.6) и сознательно лишён переговоров о параметрах. Криптография фиксирована: Curve25519 для ключей, ChaCha20-Poly1305 для данных, BLAKE2s для хэшей. Нет фаз, нет согласования шифров - каждый peer описан своим публичным ключом и списком AllowedIPs. AllowedIPs - это одновременно и список разрешённых для приёма от peer'а адресов (криптороутинг), и то, какие пакеты в этот peer отправлять. Состояния туннеля по сути нет: пришёл валидный пакет - peer считается живым.
Команды и примеры
Сначала OpenVPN. PKI удобнее строить через easy-rsa.
Debian/Ubuntu: apt install openvpn easy-rsa. RHEL/Fedora: dnf install openvpn easy-rsa (на RHEL включите EPEL).
Код: Выделить всё
make-cadir ~/easyrsa && cd ~/easyrsa
./easyrsa init-pki
./easyrsa build-ca # корневой CA, задаёте пароль
./easyrsa gen-req server nopass # CSR сервера без пароля на ключ
./easyrsa sign-req server server # CA подписывает серверный сертификат
./easyrsa gen-dh # параметры DH (или tls-crypt вместо них)
openvpn --genkey secret ta.key # ключ tls-crypt от DoS и сканеров
./easyrsa gen-req client1 nopass
./easyrsa sign-req client client1
Код: Выделить всё
port 1194
proto udp
dev tun
ca ca.crt
cert server.crt
key server.key
dh dh.pem
tls-crypt ta.key
server 10.8.0.0 255.255.255.0
topology subnet
push "redirect-gateway def1 bypass-dhcp" # весь трафик клиента в туннель
push "dhcp-option DNS 10.8.0.1"
push "route 192.168.50.0 255.255.255.0" # доступ к внутренней подсети
data-ciphers AES-256-GCM
keepalive 10 120
user nobody
group nogroup
persist-key
persist-tun
Теперь strongSwan. Ставим: apt install strongswan или dnf install strongswan. Современный конфиг - swanctl (vici), а не устаревший ipsec.conf. Файл /etc/swanctl/conf.d/site.conf для site-to-site:
Код: Выделить всё
connections {
net-net {
version = 2
local_addrs = 203.0.113.10
remote_addrs = 198.51.100.20
local { auth = pubkey; certs = leftCert.pem; id = gwA.example.com }
remote { auth = pubkey; id = gwB.example.com }
children {
net-net {
local_ts = 10.1.0.0/16
remote_ts = 10.2.0.0/16
esp_proposals = aes256gcm16-x25519
start_action = trap
}
}
proposals = aes256-sha256-x25519 # параметры IKE_SA (фаза 1)
}
}
Код: Выделить всё
systemctl enable --now strongswan # на старых сборках strongswan-starter
swanctl --load-all # подгрузить ключи, сертификаты, конфиги
swanctl --initiate --child net-net # поднять туннель вручную
swanctl --list-sas # проверить IKE_SA и CHILD_SA
Код: Выделить всё
wg genkey | tee server.key | wg pubkey > server.pub
wg genkey | tee client.key | wg pubkey > client.pub
Код: Выделить всё
[Interface]
Address = 10.9.0.1/24
ListenPort = 51820
PrivateKey = <server.key>
[Peer]
PublicKey = <client.pub>
AllowedIPs = 10.9.0.2/32 # что принимаем ИМЕННО от этого клиента
Частые грабли
- Забыли включить форвардинг и не настроили masquerade. Без net.ipv4.ip_forward=1 в sysctl и без правила nat в nftables клиент видит только сам шлюз, а не сеть за ним. Касается всех трёх решений.
- OpenVPN: путаница ca.crt и dh.pem, неправильные права на ключи. И ещё классика - забыли tls-crypt/tls-auth, и логи забиты попытками сканеров достучаться до 1194.
- strongSwan: рассинхрон traffic selectors (local_ts/remote_ts) между шлюзами - туннель встаёт по IKE, но CHILD_SA не поднимается. И не забывайте swanctl --load-all после правки - демон не перечитывает конфиг сам.
- WireGuard: слишком широкий AllowedIPs у одного peer перехватывает маршруты других - это таблица криптороутинга, а не просто фильтр. За NAT без PersistentKeepalive туннель молча отваливается, потому что у WireGuard нет keepalive по умолчанию.
- MTU. Инкапсуляция съедает байты, и большие пакеты начинают фрагментироваться или теряться. Симптом - ping проходит, а ssh и https висят. Лечится снижением MTU на интерфейсе (для WireGuard часто 1420).
- Поднимите две виртуалки: gw (шлюз с белым адресом) и client.
- Соберите WireGuard-туннель между ними: сгенерируйте по паре ключей, опишите peers, поднимите wg-quick на обеих сторонах, проверьте wg show и ping по адресам 10.9.0.x.
- Включите ip_forward и masquerade на gw, добавьте за ним третью машину lan, добейтесь, чтобы client пинговал lan через туннель.
- Параллельно разверните OpenVPN: постройте PKI через easy-rsa, выпустите сертификаты сервера и клиента, запустите openvpn-server@server.
- Сравните: захватите трафик tcpdump на внешнем интерфейсе и убедитесь, что WireGuard - это UDP/51820, а OpenVPN - UDP/1194, и оба нечитаемы.
- Снимите цифры: командой iperf3 прогоните пропускную способность через оба туннеля и сравните задержку и throughput.
- Разорвите соединение (drop правилом на client), верните и посмотрите, какой туннель восстановился быстрее и без переинициализации.
- Чем фаза IKE_SA отличается от CHILD_SA в IKEv2 и что согласуется в каждой?
- Почему AllowedIPs в WireGuard называют криптороутингом, а не просто фильтром, и к чему ведёт пересечение диапазонов у двух peers?
- Что делает директива push redirect-gateway в OpenVPN и какие ещё условия нужны, чтобы весь трафик клиента реально пошёл в туннель?
- В чём принципиальная разница в производительности OpenVPN и WireGuard и откуда она берётся?
- Зачем нужен tls-crypt (или tls-auth) в OpenVPN и от чего он защищает?
- Какие алгоритмы жёстко зашиты в WireGuard и почему отказ от согласования шифров - это сознательное архитектурное решение?