OpenBSD FAQ - Виртуальные частные сети (VPN) [FAQ - На главную]



Вступление

OpenBSD поставляется с iked(8) - современным IKEv2 сервером, поддерживаемым разделение привилегий. Он может использоваться как сервер, принимающий запросы на соединение, или как клиент, инициирующий соединение с сервером. Утилита ikectl(8) используется для управления сервером, который настраивается при помощи iked.conf(5) файла.

ikectl(8) также позволяет управлять простым X.509 certificate authority(CA) для IKEv2.

IKEv1 сервер isakmpd(8) также доступен, и в паре с npppd(8) позволяет создать VPN IKEv1/L2TP, если IKEv2 не может быть использован.

Поддержка WireGuard так же есть и доступна при помощи wg(4). Как рассказывается в руководстве, он может быть настроен точно так же как и любой другой сетевой интерфейс в OpenBSD.

Аутентификация

iked(8) поддерживает следующие методы аутентификации: По умолчанию public RSA ключ генерируется при загрузке системы и находится в /etc/iked/local.pub, а private ключ хранится в /etc/iked/private/local.key.

Настройка сервера IKEv2

Создание межсетевых VPN-соединений

Это настраивается путем обмена сгенерированных по умолчанию public RSA ключей: /etc/iked/local.pub из первой системы («server1») должен быть скопирован в /etc/iked/pubkeys/fqdn/server1.domain на второй системе («server2»). Затем /etc/iked/local.pub из второй системы следует скопировать на первую систему в /etc/iked/pubkeys/fqdn/server2.domain. Замените «serverX.domain» своим собственным полным доменным именем.

С этого момента предположим, что server1 имеет публичный IP-адрес 192.0.2.1 и внутреннюю сеть 10.0.1.0/24, а server2 имеет публичный IP-адрес 198.51.100.1 и внутреннюю сеть 10.0.2.0/24.

Чтобы клиент(инициатор) мог связаться с сервером (респондером), на стороне сервера должен быть открыт UDP-порт для isakmp. Если одна иа из сторон находится за NAT, UDP-порт ipsec-nat-t также должен быть открыт на стороне сервера. Если оба узла имеют общедоступные IP-адреса, то протокол ESP должен быть разрешен.

pass in log on $ext_if proto udp from 198.51.100.1 to 192.0.2.1 port {isakmp, ipsec-nat-t} tag IKED
pass in log on $ext_if proto esp from 198.51.100.1 to 192.0.2.1 tag IKED
Пример конфига /etc/iked.conf для server1 (в этом примере он ответчающая сторона, т.е. сервер) может выглядеть следующим образом:
ikev2 'server1_rsa' passive esp \
        from 10.0.1.0/24 to 10.0.2.0/24 \
        local 192.0.2.1 peer 198.51.100.1 \
        srcid server1.domain
И простой конфиг для server2, выступающего в роли клиента, который инициирует создание VPN-тунеля:
ikev2 'server2_rsa' active esp \
        from 10.0.2.0/24 to 10.0.1.0/24 \
        peer 192.0.2.1 \
        srcid server2.domain
При помощи iked -dv можно проследить процесс создания тунеля. В этом примере сервер находится за NAT:
server1# iked -dv
...
ikev2_recv: IKE_SA_INIT request from initiator 198.51.100.1:500 to 192.0.2.1:500 policy 'server1_rsa' id 0, 510 bytes
ikev2_msg_send: IKE_SA_INIT response from 192.0.2.1:500 to 198.51.100.1:500 msgid 0, 451 bytes
ikev2_recv: IKE_AUTH request from initiator 198.51.100.1:4500 to 192.0.2.1:4500 policy 'server1_rsa' id 1, 800 bytes
ikev2_msg_send: IKE_AUTH response from 192.0.2.1:4500 to 198.51.100.1:4500 msgid 1, 720 bytes, NAT-T
sa_state: VALID -> ESTABLISHED from 198.51.100.1:4500 to 192.0.2.1:4500 policy 'server1_rsa'
На стороне клиента:
server2# iked -dv
...
ikev2_msg_send: IKE_SA_INIT request from 0.0.0.0:500 to 192.0.2.1:500 msgid 0, 510 bytes
ikev2_recv: IKE_SA_INIT response from responder 192.0.2.1:500 to 198.51.100.1:500 policy 'server2_rsa' id 0, 451 bytes
ikev2_msg_send: IKE_AUTH request from 198.51.100.1:4500 to 192.0.2.1:4500 msgid 1, 800 bytes, NAT-T
ikev2_recv: IKE_AUTH response from responder 192.0.2.1:4500 to 198.51.100.1:4500 policy 'server2_rsa' id 1, 720 bytes
sa_state: VALID -> ESTABLISHED from 192.0.2.1:4500 to 198.51.100.1:4500 policy 'server2_rsa'
Процесс создания IPsec flow можно наблюдать при помощи ipsecctl(8):
server1# ipsecctl -sa
FLOWS:
flow esp in from 10.0.2.0/24 to 10.0.1.0/24 peer 198.51.100.1 srcid FQDN/server1.domain dstid FQDN/server2.domain type use
flow esp out from 10.0.1.0/24 to 10.0.2.0/24 peer 198.51.100.1 srcid FQDN/server1.domain dstid FQDN/server2.domain type require
flow esp out from ::/0 to ::/0 type deny

SAD:
esp tunnel from 192.0.2.1 to 198.51.100.1 spi 0xabb5968a auth hmac-sha2-256 enc aes-256
esp tunnel from 198.51.100.1 to 192.0.2.1 spi 0xb1fc90b8 auth hmac-sha2-256 enc aes-256

server2# ipsecctl -sa
FLOWS:
flow esp in from 10.0.1.0/24 to 10.0.2.0/24 peer 192.0.2.1 srcid FQDN/server2.domain dstid FQDN/server1.domain type use
flow esp out from 10.0.2.0/24 to 10.0.1.0/24 peer 192.0.2.1 srcid FQDN/server2.domain dstid FQDN/server1.domain type require
flow esp out from ::/0 to ::/0 type deny

SAD:
esp tunnel from 192.0.2.1 to 198.51.100.1 spi 0xabb5968a auth hmac-sha2-256 enc aes-256
esp tunnel from 198.51.100.1 to 192.0.2.1 spi 0xb1fc90b8 auth hmac-sha2-256 enc aes-256
При этом обе внутренние сети должны быть в досягаемости друг друга. Трафик между ними должен появляться после декапсуляции на интерфейсе enc0 и может быть отфильтрован. В этом примере tag VPN был добавлен в правила:
# pfctl -vvsr|grep VPN
@16 pass log on enc0 tagged VPN
# tcpdump -nei pflog0 rnr 16
00:03:26.793522 rule 16/(match) pass in on enc0: 10.0.2.24 > 10.0.1.13: icmp: echo request
Пару предупреждений: Если для обоих сторон VPN-соединения удаленная внутренняя сеть должна быть в зоне досигаемости, или наоборот -- из внутренней сети должны быть доступны разные стороны VPN, должны быть установленны дополнительные flows с обеих сторон: Конфигурация сервера (отвечающей стороны) будет выглядеть следующим образом:
ikev2 'server1_rsa' passive esp \
        from 10.0.1.0/24 to 10.0.2.0/24 \
        from 10.0.1.0/24 to 198.51.100.1 \
        from 192.0.2.1 to 10.0.2.0/24 \
        local 192.0.2.1 peer 198.51.100.1 \
        srcid server1.domain
И конфигурация клиента (инициатора создания соединения) будет:
ikev2 'server2_rsa' active esp \
        from 10.0.2.0/24 to 10.0.1.0/24 \
        from 10.0.2.0/24 to 192.0.2.1 \
        from 198.51.100.1 to 10.0.1.0/24 \
        peer 192.0.2.1 \
        srcid server2.domain

Подключение к IKEv2 OpenBSD VPN

Подключение к IKEv2 VPN в качестве road warrior аналогично предыдущему случаю, за исключением того, что инициатор обычно планирует маршрутизировать свой интернет-трафик через респондента, который будет применять к нему NAT, так что трафик инициатора, как представляется, поступает от респондерского публичного IP-адреса.

В зависимости от варианта использования, поскольку весь трафик будет проходить через респондера, необходимо убедиться, что клиент (инициатор создания соединения) настроен на использование DNS-сервера, к которому он сможет обращаться (возможно, один на стороне респондера).

С клиентом OpenBSD

В наших примерах сеть 10.0.5.0/24 используется для работы VPN. Фактический внутренний IP адрес на интерфейсе lo1 будет автоматически установлен/настроен iked демоном. Предположим, что общедоступный IP-адрес клиента - 203.0.113.2.

Как и в предыдущем примере, обмена предоставляемых по умолчанию открытых ключей RSA достаточно для настройки простой аутентификации между обоими сторонами соединения: /etc/iked/local.pub из первой системы («server1») должен быть скопирован в /etc/iked/pubkeys/fqdn/server1.domain на второй системе («roadwarrior»). Затем /etc/iked/local.pub из системы roadwarrior необходимо скопировать в /etc/iked/pubkeys/fqdn/roadwarrior на первую систему. Замените «serverX.domain» своим собственным полным доменным именем.

Отвечающий (responder) iked.conf(5) создает потоки (flows) из любого пункта назначения в динамическую подсеть из пула IP-адресов, которая будет определена во время выполнения, и помечает пакеты при помощи ROADW:

ikev2 'responder_rsa' passive esp \
        from any to dynamic \
        local 192.0.2.1 peer any \
        srcid server1.domain \
        config address 10.0.5.0/24 \
        tag "ROADW"
Он так же должен предоставить клиенту(инициатору соедиения) IP-адрес. Это настраивается при помощи директивы config. При использовании параметра config address, to dynamic будет заменен назначенным динамическим IP-адресом.

Также необходимо разрешить IPsec с любого хоста (поскольку клиенты могут подключаться откуда угодно), разрешить трафик с тегом ROADW на enc0 и применить к нему NAT:

pass in log on $ext_if proto udp from any to 192.0.2.1 port {isakmp, ipsec-nat-t} tag IKED
pass in log on $ext_if proto esp from any to 192.0.2.1 tag IKED
pass log on enc0 tagged ROADW
match out log on $ext_if inet tagged ROADW nat-to $ext_if
Инициатор конфигурирует глобальный flow для отправки всего своего трафика респонденту, ассоциируя себя с ключом "roadwarrior":
ikev2 'roadwarrior' active esp \
        from dynamic to any \
        peer 192.0.2.1 \
        srcid roadwarrior \
        dstid server1.domain \
        request address any \
        iface lo1
Инициатор использует параметр request address any для запроса динамического IP-адреса у ответчика. Параметр iface lo1 указывает интерфейс, для которого будут установлены полученный адрес и соответствующие маршруты. Ответчик должен иметь правильную NAT-конфигурацию для "roadwarrior".

Изящная остановка VPN на стороне инициатора может быть достигнута при помощи ikectl decouple (iked все еще работает, ожидает ikectl couple чтобы он повторно подключился к ответчику) или при помощи ikectl reset sa && rcctl stop iked для незамедлительной остановки iked и чтобы гарантировать остановку flows.

Клиент для Android

Стандартный VPN-клиент для Android поддерживает только IKEv1. Если хотите использовать IKEv2, обратите внимание на strongSwan.

Также необходимо настроить в системе испрользованиее PKI- и X.509-сертификатов, чтобы инициатор мог проверить подлинность ответной стороны (респондера):

server1# ikectl ca vpn create
server1# ikectl ca vpn install
certificate for CA 'vpn' installed into /etc/iked/ca/ca.crt
CRL for CA 'vpn' installed to /etc/iked/crls/ca.crl
server1# ikectl ca vpn certificate server1.domain create
server1# ikectl ca vpn certificate server1.domain install
writing RSA key
server1# cp /etc/iked/ca/ca.crt /var/www/htdocs/
На устройстве c Android перейдите по http://192.0.2.1/ca.crt и импортируйте сертификат CA в клиенте strongSwan. С этого момента существует несколько вариантов аутентификации инициатора для ответчика:

Использование MSCHAP-V2 для EAP аутентификации

Конфигурация ответчика должна содержать список имен пользователей и их пароли, и использовать eap "mschap-v2" (который пока является единственным поддерживаемым методом EAP):
user 'android' 'password'
ikev2 'responder_eap' passive esp \
        from any to dynamic \
        local 192.0.2.1 peer any \
        srcid server1.domain \
        eap "mschap-v2" \
        config address 10.0.5.0/24 \
        config name-server 192.0.2.1 \
        tag "ROADW"
В клиенте strongSwan новый профиль настраивается при помощи: Используя эту конфигурацию устройство Android (клиент) сможет подключаться к ответчику, аутентифицировать его сертификат при помощи сертификата CA, аутентифицировать себя при помощи EAP логина/пароля, и получать адрес в сети 10.0.5.0/24. После этого весь его трафик пойдет через VPN, используя 192.0.2.1 в качестве своего DNS-сервера.

Использование аутентификации на основе X.509 сертификатов

Для этого метода сертификат генерируется для клиента, устанавливается в iked ca, экспортируется в виде архива, и .pfx-файл должен быть доступен online, чтобы клиент мог его установить. Пакеты файлов .pfx:
server1# ikectl ca vpn certificate client1.domain create
server1# cp /etc/ssl/vpn/client1.domain.crt /etc/iked/certs/
server1# ikectl ca vpn certificate client1.domain export
server1# tar -C /tmp -xzf client1.domain.tgz *pfx
server1# cp /tmp/export/client1.domain.pfx /var/www/htdocs/client1.domain.pfx
Открытый CA-сертификат и пакет клиентских сертификатов должны быть импортированы в клиенте strongSwan при настройке нового профиля.

Конфигурация ответной стороны немного проще, так как нет необходимости указывать eap или устанавливать имя пользователя/пароль:

ikev2 'responder_x509' passive esp \
        from any to dynamic \
        local 192.0.2.1 peer any \
        srcid server1.domain \
        config address 10.0.5.0/24 \
        config name-server 192.0.2.1 \
        tag "ROADW"
В клиенте strongSwan новый профиль настраивается с использованием: Как и в случае с EAP, Android-клиент теперь может подключаться к ответной стороне и пользоваться VPN.

С клиентом Windows

Windows 7 и более поздние версии предоставляют инициатор IKEv2, который также требует использования сертификатов X.509, которые необходимо экспортировать в виде пакетов .pfx / .p12 и импортировать в хранилище сертификатов локального компьютера (не учетной записи пользователя), оба для CA. и клиент, либо используя графическую консоль управления Microsoft (введите mmc в командной строке и добавьте оснастку «Сертификаты» в качестве учетной записи компьютера), либо команду certutil с Windows 10. Импортируйте c ca.crt в certificate authority и ClientIP.p12 в personal store. У проекта StrongSwan есть хорошая документация по этой теме со скриншотами. StrongSwan

В Windows нелегко разрешить установку параметра srcid для клиента, поэтому поле CN сертификата клиента должно соответствовать полному доменному имени клиента, отправляемому респонденту, или его IP-адресу по умолчанию. Также требуется, чтобы srcid на респонденте соответствовал srcid доменному имени респондента (или его IP, если не используется полное доменное имя) - в противном случае может возникнуть страшная error 3801. Проект Libreswan содержит ценные сведения valuable details o об этих требованиях requirements.

После импорта сертификатов настройте новое VPN-соединение с помощью:

Файл конфигурации ответной стороны будет похож на уже рассматриваемый случай с Android-клиентом.
user 'windows' 'password'
ikev2 'responder_eap' passive esp \
        from any to dynamic \
        local 192.0.2.1 peer any \
        srcid server1.domain.fqdn \
        eap "mschap-v2" \
        config address 10.0.5.0/24 \
        config name-server 192.0.2.1 \
        tag "ROADW"
По умолчанию весь трафик Windows теперь будет проходить через IKEv2 VPN.

На момент написания статьи в текущих версиях Windows по умолчанию используется слабое шифрование (3DES / SHA1). Это можно исправить при помощи команды в PowerShell Set-VpnConnectionIPsecConfiguration.

Подключение к IKEv1 / L2TP VPN

Иногда нет возможности использовать IKEv2 VPN, а только IKEv1. В этом случае можно установить пакет xl2tpd, который можно использовать в качестве L2TP-клиента.

Сначала необходимо включить службы isakmpd(8) и ipsec, чтобы демон запускался и файл конфигурации ipsec.conf(5) загружался при загрузке:

# rcctl enable ipsec
# rcctl enable isakmpd
# rcctl set isakmpd flags -K
Следующая конфигурация файла ipsec.conf(5) должна позволять подключаться к IKEv1-серверу на A.B.C.D с предоставленным PSK, разрешая только UDP-порт 1701 для L2TP:
ike dynamic esp transport proto udp from egress to A.B.C.D port l2tp \
        psk mekmitasdigoat
Запуск isakmpd(8) и загрузка ipsec.conf(5) с использованием ipsecctl(8) должны позволить вам визуализировать настроенные security associations (SA) и flows:
# rcctl start isakmpd
# ipsecctl -f /etc/ipsec.conf
# ipsecctl -sa
FLOWS:
flow esp in proto udp from A.B.C.D port l2tp to W.X.Y.Z peer A.B.C.D srcid my.client.fqdn dstid A.B.C.D/32 type use
flow esp out proto udp from W.X.Y.Z to A.B.C.D port l2tp peer A.B.C.D srcid my.client.fqdn dstid A.B.C.D/32 type require

SAD:
esp transport from A.B.C.D to W.X.Y.Z spi 0x0d16ad1c auth hmac-sha1 enc aes
esp transport from W.X.Y.Z to A.B.C.D spi 0xcd0549ba auth hmac-sha1 enc aes
Если это не так, может потребоваться настроить параметры первой (Main) и второй фазы (Quick), когда обе стороны обмениваются криптографическими параметрами, чтобы договориться о наилучшей доступной комбинации. В идеале, эти параметры должны быть предоставлены администратором удаленного сервера и должны использоваться в ipsec.conf(5):
ike dynamic esp transport proto udp from egress to A.B.C.D port l2tp \
        main auth "hmac-sha1" enc "3des" group modp1024 \
        quick auth "hmac-sha1" enc "aes" \
        psk mekmitasdigoat
После того как IKEv1-туннель поднят и работает, необходимо настроить L2TP-туннель. OpenBSD по умолчанию не предоставляет L2TP-клиента, поэтому требуется установка xl2tpd.
# pkg_add xl2tpd
Почитайте /usr/local/share/doc/pkg-readmes/xl2tpd, где содержатся инструкции о том, как правильно настроить L2TP-клиент.