IPSec Туннель между двумя FreeBSD машинами


Перевод: Сгибнев Михаил

В следующей статье будут рассмотрены проблемы конфигурирования IPSec VPN на FreeBSD. При настройке VPN соединения обнаружилось несколько моментов: VPN можно настроить несколькими способами и поэтому вместе с конфигурационными файлами, представленными здесь, будут приводиться ссылки на другие ресурсы, посвященные этому вопросу. Не обращайте большого внимания на возможные несоответствия между различными ресурсами, просто выберите тот способ, который больше подходит именно Вам. Вторым моментом было то, что не все мое оборудование поддерживало VPN, поэтому обязательной мерой является влючение вывода отладочной информации.

Я буду демонстрировать туннель между двумя FreeBSD машинами, действующими как VPN шлюзы. Хотя данный пример и рассматривает FreeBSD, в качестве базовой системы, эту же методику можно применить для подсоединения к любому другому IPSec VPN шлюзу. Если это Ваш первый опыт, то попробуйте сперва соединить две FreeBSD машины. Как только вы наберете достаточный опыт в поиске и устранении неисправностей, начинайте эксперементировать с другими системами. Успех ваших экспериментов будет зависеть от VPN шлюза, с которым Вы соединяетесь и как далеко производитель оборудования отклонился от IPSec стандарта, добавляя дополнительные особенности.

Для того, что бы начать использование IPSec в Вашей системе, необходимо соответствующим образом сконфигурировать ядро. Если это будет Вашим первым опытом в когфигурации ядер, возможно придется почитать "the kernel config section of the handbook"

Если Вы предполагаете, что поддержка IPSec уже установлена, то проверить это можно следующей командой:

sysctl -a | grep ipsec

Если ничего не обнаружено, то IPSec в ядре нет. Соответственно, если Вы строите туннель между двумя FreeBSD машинами, IPSec должен поддерживаться обоими машинами.

Конфигурируем ядро:

cp /usr/src/sys/i386/conf/GENERIC /usr/src/sys/i386/conf/IPSEC

Вносим следующие добавления в файл конфигурации, воспользовавшись для этого своим любимым текстовым редактором:

optionsIPSEC
optionsIPSEC_ESP
optionsIPSEC_DEBUG

Так же удостоверьтесь, что наличествует строка инициации псевдо-устройства gif:

pseudo-device gif

(Пр. п. - в ядрах 5.х ветки это утройство вынесено в секцию "Pseudo devices" и обозначается как "device gif")

После внесения всех изменений компилируем ядро:

cd /usr/src
make buildkernel KERNCONF=IPSEC && make installkernel KERNCONF=IPSEC

(Пр. п. - Я использую 5.1 и предпочел пойти стандартным путем - "config New_kern && cd ../compile/New_kern && make depend && make && make install")

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

После установки поддержки IPSec Вы можете использовать AH и ESP и понимать SAD и SPD. Однако, Вы должны будете создать правило, которое будет сохранено в SPD, и SA, которое будет сохранено в SAD. Есть возможность сделать это вручную, используя команду setkey, но все же лучше использовать протокол обмена ключами, чтобы создать правильные SA. IKE, также известный как ISAKMP, является протоколом обмена ключами для IPSec.

В настоящее время, есть два возможных способа установить поддержку IKE на вашей FreeBSD системе; оба найдены в разделе /ports/security коллекции портов. Первый называется racoon и второй, соответственно, isakmpd. Я нашел, что синтаксис, используемый racoon более прост для новичка и в Интернете присутствует большее количество информации по настройке.
Устанавливаем racoon

cd /usr/ports/security/racoon
make install clean

После окончания установки у нас есть все необходимое для настройки VPN. Политики, написанные нами, будут ограничены допустимыми параметрами racoon, которые описаны в racoon.conf.

Вот сводная таблица параметров:

Feature racoon
Authentication Methods rsasig
preshared-key
gssapi_krb
Encryption Algorithms 3DES (default phase1)
DES (default phase2)
blowfish
CAST128
idea
3idea
rc5
rc4
twofish
rijndael
Integrity Algorithms HMAC-SHA1 (default)
HMAC-MD5
Encryption Modes transport
tunnel
DH Groups 1 (default phase2)
2 (default phase1)
5
PFS supported
IKE SA default lifetime 1 minute
IPSEC SA default lifetime 30 seconds


Помните, что правила должны быть строго идентичны на обоих машинах. Если другой VPN шлюз работает под управлением другого программного продукта, изучите документацию, чтобы видеть, какие параметры поддерживаются обоими шлюзами.

Я решил использовать следующую политику:

authentication method pre-shared secret of "dontguessme"
encryption algorithm blowfish
authentication algorithm HMAC-SHA1
encryption mode tunnel
DH group 5
PFS yes
Phase 1 lifetime 24 hour
Phase 2 lifetime 60 min

Всякий раз, когда я конфигурирую VPN, я всегда записываю параметры политики, что бы не забыть. Итак, вот схема наших соединений:

Рисунок 1 - логическая диаграмма VPN

Вы обратите внимание, что каждый шлюз имеет 2 сетевых карты и 2 IP адреса. Внешний IP адрес подключен к Internet. Внутренний IP будет адресом из приватного диапазона. Обратите внимание, что я не дал Вам мои реальные внешние адреса, но маркировал их как A.A.A.A и B.B.B.B для этой статьи.

Советую потратить несколько минут на то, чтобы нарисовать схему и записать политику на бумаге - это поможет сэкономить часы, проведенные в поисках неисправности. Очень просто написать неправильный IP в неправильный файл конфигурации и скакать потом потрясая бубном с тоскливыми воплями.
Запуск racoon
Запускаем racoon на Gateway A. racoon установленный из системы портов закинул два образцово-показательных конфигурационных файла в /usr/local/etc/racoon:

cd /usr/local/etc/racoon
ls
psk.txt.dist racoon.conf.dist

Сперва продублируем эти файлы:

cp racoon.conf.dist racoon.conf

Ну, посмотрим, что у него внутри:

# $KAME: racoon.conf.in,v 1.18 2001/08/16 06:33:40 itojun Exp $

# "path" must be placed before it should be used.
# You can overwrite which you defined, but it should not
# use due to confusing.
path include "/usr/local/etc/racoon" ;
#include "remote.conf" ;

# search this file for pre_shared_key with various ID key.
path pre_shared_key "/usr/local/etc/racoon/psk.txt" ;

Так как я использую известный ключ, как метод начального опознавания, я оставлю вышеупомянутые строки как есть.

# racoon will look for certificate file in the directory,
# if the certificate/certificate request payload is received.
path certificate "/usr/local/etc/cert" ;

Эти 3 строки я удалил, так как не буду использовать CA.

# "log" specifies logging level.
#It is followed by either "notify", "debug"
# or "debug2".
#log debug;

# "padding" defines some parameter of padding. You should not touch these.
padding
{
maximum_length 20;# maximum padding length.
randomize off;# enable randomize length.
strict_check off;# enable strict check.
exclusive_tail off;# extract last one octet.
}

Вышеуказанные строки оставляем так, как есть.

# if no listen directive is specified, racoon will listen to all
# available interface addresses.
listen
{
#isakmp ::1 [7000];
#isakmp 202.249.11.124 [500];
#admin [7002]; # administrative's port by kmpstat.
#strict_address; # required all addresses must be bound.
}

Смотрим последние четыре строки с # перед ними: я расскомментировал тот, который с IP адресом, но вставил на его место IP адрес Gateway A.

# Specification of default various timer.
timer
{
# These value can be changed per remote node.
counter 5;# maximum trying count to send.
interval 20 sec;# maximum interval to resend.
persend 1;# the number of packets per a send.

# timer for waiting to complete each phase.
phase1 30 sec;
phase2 15 sec;
}

Этот раздел должен остаться как есть.

remote anonymous
{
#exchange_mode main,aggressive;
exchange_mode aggressive,main;
doi ipsec_doi;
situation identity_only;

#my_identifier address;
my_identifier user_fqdn "
sakane@kame.netЭтот e-mail защищен от спам-ботов. Для его просмотра в вашем браузере должна быть включена поддержка Java-script
";
peers_identifier user_fqdn "
sakane@kame.netЭтот e-mail защищен от спам-ботов. Для его просмотра в вашем браузере должна быть включена поддержка Java-script
";
#certificate_type x509 "mycert" "mypriv";

nonce_size 16;
lifetime time 1 min;# sec,min,hour
initial_contact on;
support_mip6 on;
proposal_check obey;# obey, strict or claim

proposal {
encryption_algorithm 3des;
hash_algorithm sha1;
authentication_method pre_shared_key ;
dh_group 2 ;
}
}

remote ::1 [8000]
{
#exchange_mode main,aggressive;
exchange_mode aggressive,main;
doi ipsec_doi;
situation identity_only;

my_identifier user_fqdn "
sakane@kame.netЭтот e-mail защищен от спам-ботов. Для его просмотра в вашем браузере должна быть включена поддержка Java-script
";
peers_identifier user_fqdn "
sakane@kame.netЭтот e-mail защищен от спам-ботов. Для его просмотра в вашем браузере должна быть включена поддержка Java-script
";
#certificate_type x509 "mycert" "mypriv";

nonce_size 16;
lifetime time 1 min;# sec,min,hour

proposal {
encryption_algorithm 3des;
hash_algorithm sha1;
authentication_method pre_shared_key ;
dh_group 2 ;
}
}

Все, что отмечено как "remote" - это первая фаза правила. Обратите внимание, что Вы можете иметь сколько угодно секций "remote". Если у Вас множество шлюзов, использующих разные политики, то Вы можете создать "remote" для каждого из них, указав соответствующий IP адрес. Если у шлюза, запросившего соединение нет соответствующей записи "remote", то к нему будет применена политика "remote anonymous".

sainfo anonymous
{
pfs_group 1;
lifetime time 30 sec;
encryption_algorithm 3des ;
authentication_algorithm hmac_sha1;
compression_algorithm deflate ;
}

sainfo address 203.178.141.209 any address 203.178.141.218 any
{
pfs_group 1;
lifetime time 30 sec;
encryption_algorithm des ;
authentication_algorithm hmac_md5;
compression_algorithm deflate ;
}

sainfo address ::1 icmp6 address ::1 icmp6
{
pfs_group 1;
lifetime time 60 sec;
encryption_algorithm 3des, cast128, blowfish 448, des ;
authentication_algorithm hmac_sha1, hmac_md5 ;
compression_algorithm deflate ;
}

sainfo является правилом, определяющим вторую фазу соединения. Также, как и с правилом "remote", вы можете иметь записи как для каждого шлюза, осуществляющего попытку соединения, так и анонимную запись.

Взглянем на отредактированный файл конфигурации, где удалено все лишнее:

# $KAME: racoon.conf.in,v 1.18 2001/08/16 06:33:40 itojun Exp $

path include "/usr/local/etc/racoon" ;

path pre_shared_key "/usr/local/etc/racoon/psk.txt" ;

# "log" specifies logging level. It is followed by either "notify", "debug"
# or "debug2".
#log debug;

# "padding" defines some parameter of padding. You should not touch these.
padding
{
maximum_length 20;# maximum padding length.
randomize off;# enable randomize length.
strict_check off;# enable strict check.
exclusive_tail off;# extract last one octet.
}

# if no listen directive is specified, racoon will listen to all
# available interface addresses.
listen
{
isakmp A.A.A.A [500];
}

# Specification of default various timer.
timer
{
# These value can be changed per remote node.
counter 5;# maximum trying count to send.
interval 20 sec;# maximum interval to resend.
persend 1;# the number of packets per a send.

# timer for waiting to complete each phase.
phase1 30 sec;
phase2 15 sec;
}

remote B.B.B.B
{
#exchange_mode main,aggressive;
exchange_mode aggressive,main;
doi ipsec_doi;
situation identity_only;

nonce_size 16;
lifetime time 60 min;# sec,min,hour
initial_contact on;
support_mip6 on;
proposal_check obey;# obey, strict or claim

proposal {
encryption_algorithm blowfish;
hash_algorithm sha1;
authentication_method pre_shared_key ;
dh_group 5 ;
}
}

sainfo B.B.B.B
{
pfs_group 5;
lifetime time 24 hour;
encryption_algorithm blowfish ;
authentication_algorithm hmac_sha1;
compression_algorithm deflate ;
}

Сравните файл конфигурации с рисунком и Вы увидите, что большинство параметров конфигурации помещено в этот файл. Обратите внимание, что я использовал внешний IP Gateway A в директиве listen, и сделал remote и sainfo политики для внешнего IP Gateway B. Так как у нас есть требование идентичности файлов конфигурации, то мы просто копируем этот файл на маршрутизатор B и соответствующим образом заменяем IP адреса.

Создаем первичный ключ:

$ vi /usr/local/etc/racoon/psk.txt

#peer's external ippre-shared secret
B.B.B.Bdontguessme

Этот файл должен находиться на обоих шлюзах. IP адреса, соответственно, должны быть указаны зеркально - на Gateway A указывается IP Gateway B.

Не забудьте изменить права доступа на этот файл:

$ chmod 600 /usr/local/etc/racoon/psk.txt

Ну, вроде все готово к запуску. Но обратим внимание на еще один маленький момент. racoon при установке создает сценарий запуска:

$ more /usr/local/etc/rc.d/racoon.sh

#!/bin/sh

case "$1" in
start)
if [ -x /usr/local/sbin/racoon ]; then
/usr/local/sbin/racoon -f /usr/local/etc/racoon/racoon.conf
&& echo -n ' racoon'
fi
;;

stop)
/usr/bin/killall racoon && echo -n ' racoon'
;;

*)
echo "Usage: `basename $0` { start | stop }"
exit 64
;;
esac

Между строками с if и fi находится строка запуска racoon с ключом f. Но советую Вам указать там и ключ l или logging, для того, чтобы контролировать работу этой службы. Измененная строка выглядит так:

/usr/local/sbin/racoon -f /usr/local/etc/racoon/racoon.conf -l
/var/log/racoon.log && echo -n ' racoon'

Учтите, что вышеуказанное - одна строка! Файл журнала будет создан автоматически.

Одна последняя вещь - это команда, которая говорит системе, какие пакеты нужно послать по туннелю. Например, на Gateway A, любые пакеты, посылаемые 192.168.1.x (область Gateway B) должны пройти VPN туннель. На Gateway A, я включаю эту строку:

/sbin/route add -net 192.168.1.0/24 10.0.0.1

На противоположном шлюзе команда будет выглядеть так:

/sbin/route add -net 10.0.0.0/8 192.168.1.1

Произведем финальные изменения в /etc/rc.conf для Gateway A:

ipsec_enable="YES"
ipsec_file="/etc/ipsec.conf"
gif_interfaces="gif0"
ifconfig_gif0="10.0.0.1 netmask 255.0.0.0 192.168.1.1 netmask 255.255.255.0"
gifconfig_gif0="A.A.A.A netmask 255.255.240.0 B.B.B.B netmask 255.255.240.0"

Первые две строки обеспечивают запуск IPSec во время начальной загрузки. Команда gif_interfaces создает псевдо устройство, которое представляет собой туннель. Технически, наличие его не обязательно для нормальной работы, но облегчает понимание. Последние две строки указывают адреса для нашего туннеля. Помните, что в туннельном режиме оригинальный пакет содержит IP адреса реального источника и адресата, которые являются обычно адресами из частного диапазона. Новый заголовок IP, созданный ESP содержит внешние адреса IP двух VPN шлюзов.

Команда ifconfig_gif0 содержит внутренние IP адреса этих двух шлюзов, и команда gifconfig_gif0 содержит внешние IP адреса этих двух шлюзов.

Последний файл, который мы должны создать - ipsec.conf. Сначала, этот файл кажется ненужным, поскольку это создает политику, сохраненную в SPD. Вы можете ошибочно думать, что указали все необходимое еще в racoon.conf, хотя на самом деле вы указали как производить соединение, а параметры самого соединения будут помещены в SAD. Однако, racoon не может разместить политику в SPD за Вас; это - задача утилиты setkey. Смысл создания /etc/ipsec.conf в том, что Вы не должны будете выполнять setkey вручную каждый раз после перезагрузки.

Мой файл /etc/ipsec.conf на Gateway A выглядит так:

$ more /etc/ipsec.conf

#delete all existing entries from the SAD and SPD databases
flush;
spdflush;

#add the policy to the SPD database
spdadd 10.0.0.0/8 192.168.1.0/24 any -P out ipsec
esp/tunnel/A.A.A.A-B.B.B.B/require;

spdadd 192.168.1.0/24 10.0.0.0/8 any -P in ipsec
esp/tunnel/B.B.B.B-A.A.A.A/require;

Строки начинающиеся с "spdadd" и начинающиеся с "esp..." - это разные строки, а не одна длинная. Первая строка политики говорит о том, что всякий раз, когда пакеты от сети 10.0.0.0 направляются в сеть 192.168.1.0, они должны быть зашифрованы и направлены в туннель, который идет от Gateway A в Gateway B. На Gateway B адреса будут зеркально изменены.

Обновлено: 12.03.2015