Популяризация OpenBSD, часть 4 (просто об ipsec. Строим безопасный туннель между шлюзами)

Полезные советы и программы от пользователей нашего форума.

Модератор: Модераторы разделов

Аватара пользователя
kasak
Сообщения: 887
ОС: OpenBSD

Популяризация OpenBSD, часть 4

Сообщение kasak »

Я решил написать очередную статейку про замечательную ось OpenBSD, на этот раз речь пойдёт о построении ipsec туннелей с использованием ikev1 и ikev2.
Напомню что все мои статьи ориентированы на новичков в области системного администрирования, поэтому я излагаю всё максимально просто.

Я не буду сейчас втирать вам какую-то дичь про шифрование, режимы IKE, не буду грузить терминами, не буду говорить про то, чего не нужно знать для построения туннелей. Если вы профессионал, то данная статья вас не заинтересует. Но если вы не умеете организовывать туннели и хотите понять как это делается простым языком - эта статья для вас.

Безусловно можно сделать всё очень просто при помощи openvpn, но поскольку циклы моих статей направлены на популяризацию OpenBSD, на мой взгляд куда проще и быстрее сделать всё средствами чистой системы без установки постороннего софта, кроме того, несмотря на иногда кажущуюся сложность, на практике построить тоннель очень просто!

Минимум того что вам необходимо знать - Я покажу сначала старый проверенный метод на ikev1, потом на ikev2. Для нас разница будет лишь в том что ikev2 проще.
Сначала шлюзам нужно будет обменяться ключами, после чего будут установлены шифрованные потоки по которым и будет направлен шифрованный трафик.

Для ikev1 обмен ключами будет происходить через демон isakmpd а потоки будет создавать ядро скушав конфигурационный файл /etc/ipsec.conf. Для ikev2 будет достаточно одного лишь OpenIKED. Но об этом позже.

В OpenBSD 5.9 нужные протоколы (esp, ah) в ядре включены изначально.
Если в pf включен полностью порезан входящий трафик то нужно разрешить 500 порт по UDP ну и на всякий случай 4500 UDP.

Здесь и далее конфигурация нашей сети будет выглядеть вот так:

LAN1 (192.168.1.0/24) ---------- Gate1 (1.1.1.1) ---- Internet ---- Gate2 (2.2.2.2) ----------- LAN2 (192.168.2.0/24)

Для ikev1 можно организовать обмен ключами через PKI (то есть вручную сгенерировать CA сертификат и им вручную же подписать пару сертификатов для наших шлюзов, но это далеко не простой путь, поэтому для ikev1 мы прибегнем к простому и проверенному способу аутентификации по открытому ключу. Посмотрите что лежит в /etc/isakmpd/

-rw-r--r-- 1 root wheel 451 May 5 2014 local.pub

Это открытый ключ. Мы должны положить его на удалённый сервер, а с удалённого сервера забрать такой же себе. Это можно сделать через scp:

Код: Выделить всё

doas scp 2.2.2.2:/etc/isakmpd/local.pub /etc/isakmpd/pubkeys/ipv4/2.2.2.2


На удалённом сервере делаем всё прямо противоположно:

Код: Выделить всё

doas scp 1.1.1.1:/etc/isakmpd/local.pub /etc/isakmpd/pubkeys/ipv4/1.1.1.1


Что было сейчас сделано? Я думаю любой даже начинающий сисадмин знает как пользоваться scp но на всякий случай напомню. Нам нужно положить файлик local.pub с удалённого сервера на наш сервер, doas в начале нужно за тем чтобы хватило привилегий на запись в папку /etc/isakmpd/pubkeys/ipv4/ Кроме того при копировании ключа мы даём ему имя совпадающее с айпи адресом удалённого сервера откуда мы копируем ключ. Это нужно сделать обязательно!

Теперь нужно запустить isakmpd в флагом -K. Этот флаг нужен для того чтобы isakmpd не искал файлик политик, нам он в данном случае не нужен.

Код: Выделить всё

doas rcctl enable isakmpd
doas rcctl set isakmpd flags -K
doas rcctl start isakmpd


Перейдём к созданию потоков. Редактируем файл /etc/ipsec.conf:

Код: Выделить всё

ike from 1.1.1.1 to 192.168.2.0/24 peer 2.2.2.2 srcid 1.1.1.1
ike from 192.168.1.0/24 to 192.168.2.0/24 peer 2.2.2.2 srcid 1.1.1.1


На обратной стороне зеркально:

Код: Выделить всё

ike from 2.2.2.2 to 192.168.1.0/24 peer 1.1.1.1 srcid 2.2.2.2
ike from 192.168.2.0/24 to 192.168.1.0/24 peer 1.1.1.1 srcid 2.2.2.2


Конечно же можно было в конфиге прописать макросы, например gate1="1.1.1.1" и сделать всё покороче, но я специально не стал этого делать для наглядности. Разберём отдельно каждую часть.

На самом деле строка могла быть куда больше, однако я опустил ВСЕ лишние опции, например active или esp. Эти опции ike считает дефолтными а значит лишний раз вписывать их не нужно. Я встречал много статей где зачем-то вбивались куча лишних аргументов.

Первая строка - туннель от 1.1.1.1 до 192.168.2.0 - соответственно туннель от самого шлюза до удалённой локалки. peer - адрес удалённого шлюза. srcid - я на всякий случай опционально вписал этот аргумент, чтобы гарантированно совпадали srcid у источников и совпадать они должны с названиями файлов в /etc/isakmpd/pubkeys/ipv4.

Можно было вообще упростить это ещё больше:
ike from 1.1.1.1 to 2.2.2.2
ike from 192.168.1.0/24 to 2.2.2.2
ike from 192.168.1.0/24 to 192.168.2.0/24

Тут первая строка - это туннель непосредственно между шлюзами. В первой строке мы как бы подсовываем аргумент peer однозначно давая понять откуда и куда всё это подключается.

Всё это нужно включить через

Код: Выделить всё

doas ipsecctl -f /etc/ipsec.conf

А в конец файла /etc/rc.conf/local добавить

Код: Выделить всё

ipsec="YES"

Для автоматической подгрузки этих правил при включении системы.
Вот вобщем то и всё. Через ipsecctl -sf (означает show flows) посмотрим на потоки:

Код: Выделить всё

flow esp in from 2.2.2.2 to 192.168.1.0/24 peer 2.2.2.2 srcid 1.1.1.1/32 dstid 2.2.2.2/32 type use
flow esp out from 192.168.1.0/24 to 2.2.2.2 peer 2.2.2.2 srcid 1.1.1.1/32 dstid 2.2.2.2/32 type require
flow esp in from 192.168.2.0/24 to 1.1.1.1 peer 2.2.2.2 srcid 1.1.1.1/32 dstid 2.2.2.2/32 type use
flow esp out from 1.1.1.1 to 192.168.2.0/24 peer 2.2.2.2 srcid 1.1.1.1/32 dstid 2.2.2.2/32 type require
flow esp in from 192.168.2.0/24 to 192.168.1.0/24 peer 2.2.2.2 srcid 1.1.1.1/32 dstid 2.2.2.2/32 type use
flow esp out from 192.168.1.0/24 to 192.168.2.0/24 peer 2.2.2.2 srcid 1.1.1.1/32 dstid 2.2.2.2/32 type require


Такая картина нам открывается на шлюзе 1.1.1.1.
Первые две строки это поток который нам прислал удалённый шлюз, остальные четыре мы описали сами в /etc/ipsec.conf.

На этом по ikev1 у меня всё!

Чтобы организовать ikev2 нам потребуется только лишь один iked.
Не нужен больше isakmpd и файл ipsec.conf.

Начнём с чистого листа! Всё что у нас есть это два шлюза и сети в той конфигурации что описана выше, и pf.conf с открытыми 500 и 4500 UDP портами.
iked допускает больше возможностей для обмена ключами, кроме того в комплекте идёт супер удобная утилита для генерации CA и сертификатов для организации "public key infrastructure". В примере выше мы использовали публичные ключи, тут можно поступить так же но, для разнообразия, ниже я покажу как сделать всё по-человечески. Но дополнительно расскажу что можно вообще ничего не генерировать и не копировать я просто сделать с двух сторон вот так:

Код: Выделить всё

ikev2 active from 1.1.1.1 to 192.168.2.0/23 from 192.168.1.0/24 to 192.168.2.0 psk "secretkey"

И этого будет достаточно. Это называется аутентификация по общему ключу. Однако так делать не рекомендуется, разве что в целях тестирования.

Мы же создадим инфраструктуру ключей:

Код: Выделить всё

ikectl ca vpn create
###Создаём CA сертификат.
ikectl ca vpn certificate 1.1.1.1 create
ikectl ca vpn certificate 2.2.2.2 create
###Создаём сертификаты узлов (они сразу же подпишутся нашим CA)
ikectl ca vpn install
### Инсталлируем CA на наш первый шлюз
ikectl ca vpn certificate 1.1.1.1 install
### Инсталлируем наш сертификат на 1.1.1.1
ikectl ca vpn certificate 2.2.2.2 export
### Экспортируем готовый набор сертификатов для 2.2.2.2
scp 2.2.2.2.tgz user@2.2.2.2:/home/user
### Копируем его на удалённый узел. user следует разумеется заменить на реальную учётку.
tar -C /etc/iked -xzpf 2.2.2.2.tgz
### Это установит всё необходимое на второй узел.


Каждый раз при генерировании сертификата он будет спрашивать все данные. Надеюсь всем понятно что в Common Name нужно вводить ip адрес либо то что будет использоваться вместо ip адреса в srcid.

Теперь когда у нас есть ключи с обоих сторон можно создать конфиг для iked!
/etc/iked.conf(со стороны 1.1.1.1):

Код: Выделить всё

ikev2 from 1.1.1.1 to 192.168.2.0/24 from 192.168.1.0/24 to 192.168.2.0/24 peer 2.2.2.2 srcid 1.1.1.1

со стороны 2.2.2.2:

Код: Выделить всё

ikev2 active from 2.2.2.2 to 192.168.1.0/24 from 192.168.2.0/24 to 192.168.1.0/24 peer 1.1.1.1 srcid 2.2.2.2


Что изменилось относительно ipsec.conf. В отличие от ipsec.conf наш iked по умолчанию принимает не активный режим а пассивный. Поэтому со стороны 1.1.1.1 никаких доп опций нет, он как бы ждёт запросов, а со стороны 2.2.2.2 мы добавили active, он будет инициировать соединение. Кроме того теперь можно не вводить по сто раз srcid и peer а сразу же вписать всё одной строкой.
Что касается опций, srcid по умолчанию использует hostname, а оно как правило не является ip адресом. Можно вместо этого генерить сертификаты опираясь не на ip адрес а на hostname, но мне для наглядности проще показать это в виде ip адресов.
Для запуска всего хозяйства достаточно запустить один только iked:

Код: Выделить всё

doas rcctl enable iked
doas rcctl start iked

посмотреть на потоки можно так же через ipsecctl -sf

Как видно - в iked всё куда проще и удобнее чем в связке isakmpd + ipsec.conf.

НО!!! Вот тут мне придётся описать очень плохой итог и объяснение зачем я описывал отдельно и isakmpd и iked вместо того чтобы оставить один только удобный iked.
На сегодняшний день (OpenBSD 5.9) При тестировании iked я столкнулся с проблемой. Между локалками трафик ходит хорошо, Но при попытке пинга локальных адресов с самого шлюза не доходит ответ.
То есть icmp request исправно доходит до удалённой точки, но при возвращении icmp reply отправляется не на enc0 а на egress, и в результате не доходит до нужной точки.
Если вы не поняли о чём я сейчас говорю то не заморачивайтесь и делайте всё по isakmpd, потом разберётесь. Но если вам понятны мои слова, то возможные пути обхода есть.
Первый путь решить проблему в лоб. Убрать вообще из iked.conf маршрут from 1.1.1.1 to 192.168.2.0/24 и вместо этого сделать в pf.conf:
match out on enc0 from (egress) to 192.168.2.0/24 nat-to (192.168.1.1)
Это обманет шлюз и будет отсылать все пакеты с локального адреса. Но это разумеется костыль.
Ещё мысли, мне кажется можно попробовать добавить дополнительный маршрут from 2.2.2.2 to 192.168.1.0/24 на шлюзе 1.1.1.1 и наоборот на 2.2.2.2, возможно это решит проблему но доказательств этому у меня нет, как к сожалению в данный момент нету подопытных локалок на которых можно проверить эту теорию.
Кроме того к моему сожалению iked имеет свойство время от времени переставать работать, не подавая при этом каких-либо признаков неисправности. То биш flows и sad созданы, лог чист, всё вроде бы должно работать, но по какой-то причине не работает :( Проблему решает перезапуск iked, Однако же это конечно совсем не то что нужно. Тестирование проводилось как раз на pki, возможно при использовании local.pub или psk такой проблемы не будет, однако же как я говорил у меня нету подопытных сетей для проведения тестирования всего этого поэтому я и описал два способа. Первый - проверенный, где всё работает как следует. Второй тоже проверенный но тут есть проблемы. Возможно у кого-то будет желание поэкспериментировать и открыть для себя радости OpenIKED, и возможно даже отписаться как удалось решить проблему. Я же в свою очередь отредактирую данную статью если ситуация изменится.

Всем спасибо за внимание!
Linux kasakoff 5.10.7-200.fc33.x86_64 #1 SMP Tue Jan 12 20:20:11 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
Спасибо сказали:

Аватара пользователя
nerve
Сообщения: 280
ОС: OpenBSD

Re: Популяризация OpenBSD, часть 4

Сообщение nerve »

kasak писал(а):
26.05.2016 12:05
LAN1 (192.168.1.0/24) ---------- Gate1 (1.1.1.1) ---- Internet ---- Gate2 (2.2.2.2) ----------- LAN2 (192.168.2.0/24)

Код: Выделить всё

ike from 1.1.1.1 to 192.168.2.0/24 peer 2.2.2.2 srcid 1.1.1.1
ike from 192.168.1.0/24 to 192.168.2.0/24 peer 2.2.2.2 srcid 1.1.1.1

На обратной стороне зеркально:

Код: Выделить всё

ike from 2.2.2.2 to 192.168.1.0/24 peer 1.1.1.1 srcid 2.2.2.2
ike from 192.168.2.0/24 to 192.168.1.0/24 peer 1.1.1.1 srcid 2.2.2.2

Между локалками трафик ходит хорошо, Но при попытке пинга локальных адресов с самого шлюза не доходит ответ.

можно попробовать добавить дополнительный маршрут from 2.2.2.2 to 192.168.1.0/24 на шлюзе 1.1.1.1 и наоборот на 2.2.2.2 << наоборот

вот так будет доступ с роутеров к противоположным сетям:
ike from 1.1.1.1 to 192.168.2.0/24 peer 2.2.2.2 srcid 1.1.1.1
ike from 192.168.1.0/24 to 2.2.2.2 peer 2.2.2.2 srcid 1.1.1.1
ike from 192.168.1.0/24 to 192.168.2.0/24 peer 2.2.2.2 srcid 1.1.1.1

ike from 192.168.2.0/24 to 1.1.1.1 peer 1.1.1.1 srcid 2.2.2.2
ike from 2.2.2.2 to 192.168.1.0/24 peer 1.1.1.1 srcid 2.2.2.2
ike from 192.168.2.0/24 to 192.168.1.0/24 peer 1.1.1.1 srcid 2.2.2.2

есть еще третий проверенный вариант: MANUAL FLOWS + MANUAL SECURITY ASSOCIATIONS.
Спасибо сказали:

Аватара пользователя
kasak
Сообщения: 887
ОС: OpenBSD

Re: Популяризация OpenBSD, часть 4

Сообщение kasak »

nerve писал(а):
30.05.2016 13:32
вот так будет доступ с роутеров к противоположным сетям:
ike from 1.1.1.1 to 192.168.2.0/24 peer 2.2.2.2 srcid 1.1.1.1
ike from 192.168.1.0/24 to 2.2.2.2 peer 2.2.2.2 srcid 1.1.1.1
ike from 192.168.1.0/24 to 192.168.2.0/24 peer 2.2.2.2 srcid 1.1.1.1

ike from 192.168.2.0/24 to 1.1.1.1 peer 1.1.1.1 srcid 2.2.2.2
ike from 2.2.2.2 to 192.168.1.0/24 peer 1.1.1.1 srcid 2.2.2.2
ike from 192.168.2.0/24 to 192.168.1.0/24 peer 1.1.1.1 srcid 2.2.2.2

Это iked или isakmpd ? я же тоже предложил добавить ещё один маршрут но в теории я не проверил.
Linux kasakoff 5.10.7-200.fc33.x86_64 #1 SMP Tue Jan 12 20:20:11 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
Спасибо сказали: