14.10. VPN через IPsec

Написал Nik Clayton.

Создание VPN между двумя сетями, соединенными через интернет, с использованием шлюзов FreeBSD.

14.10.1. Принципы работы IPsec

Написал Hiten M. Pandya.

Этот раздел является руководством по настройке IPsec и его применению для организации криптованного соединения между двумя сетями, на шлюзах которых используется FreeBSD. Перед изучением настройки IPsec необходимо ознакомиться с процессом сборки ядра (Гл. 8).

IPsec -- это семейство протоколов, работающих поверх слоя Internet Protocol (IP). Описывающие его стандарты постоянно расширяются, обзор основных стандартов и их взаимосвязь обсуждается в RFC2411. IPsec позволяет двум или более хостам связываться способом, защищающим данные от модификации и/или от несанкционированного доступа (отсюда и название протокола). Реализация IPsec во FreeBSD основана на реализации KAME, поддерживающей как семейство протоколов IPv4, так и IPv6.

Замечание: FreeBSD 5.X и старше содержит заимствованную из OpenBSD поддержку ''криптоакселераторов'', известную как ''Fast IPsec''. Эта поддержка использует доступное через подсистему crypto(4) криптографического оборудование для повышения производительности IPsec. Это новая подсистема и она не поддерживает всех возможностей, доступных в KAME версии IPsec. Для её использования необходимо добавить в файл настройки ядра следующий параметр:

options      FAST_IPSEC  # new IPsec (cannot define w/ IPSEC)

Обратите внимание, что на данный момент совместное использование ''Fast IPsec'' вместе с KAME реализацией IPsec невозможно. Более подробную информацию можно найти на странице справочника fast_ipsec(4).

В числе прочих в IPsec входят следующие протоколы:

ESP и AH могут быть использованы как вместе так и по отдельности, в зависимости от обстоятельств. Следует заметить, что эти протоколы не заменяют, а дополняют друг друга.

IPsec может быть использован или для непосредственного шифрования трафика между двумя хостами (транспортный режим), или для построения ''виртуальных туннелей IPsec'' между двумя корпоративными (туннельный режим). Подробная информация о подсистеме IPsec в FreeBSD приведена на странице справочника ipsec(4).

Для включения поддержки IPsec в ядре, к файлу настройки ядра необходимо добавить следующие параметры:

options   IPSEC        #IP security
options   IPSEC_ESP    #IP security (crypto; define w/ IPSEC)

Если необходимо проведение отладки работы IPsec, то дополнительно необходимо добавить следующий параметр:

options   IPSEC_DEBUG  #debug for IP security
     

14.10.2. Постановка задачи

Не существует стандарта на виртуальную частную сеть (VPN). Обычно под VPN понимают организацию виртуальных каналов между двумя корпоративными сетями, позволяющими хостам из этих сетей обмениваться трафиком так, как будто эти сети подключенены напрямую к одному маршрутизатору. Распространенной практикой при построении VPN является использование шифрования и других криптографических методов для защиты передаваемой по VPN информации от просмотра и модификации. VPN могут быть реализованы множеством различных способов, каждый из которых имеет свои сильные и слабые стороны. В этом разделе представлен сценарий и стратегия реализации VPN для случая использования GIF-туннелей (для организации межсетевого взаимодействия) и IPsec (для защиты передаваемых данных).

14.10.3. Сценарий: объединение двух сетей через интернет

Мы будем исходить из следующих условий:

Пусть топология сети выглядит следующим образом:

Здесь присутствуют два публичных IP-адреса, обозначенных A.B.C.D и W.X.Y.Z. Для использования приведенных в данной главе конфигураций эти буквенные обозначения следует заменить на настоящие публичные IP-адреса. Так же для определенности будем считать, что у обеих шлюзов внутренний адрес заканчивается на .1 и диапазоны приватных адресов двух сетей различны (192.168.1.x и 192.168.2.x соответственно). Все компьютеры локальных сетей настроены на использование в качестве шлюза по умолчанию компьютера с адресом, оканчивающимся на .1.

С сетевой точки зрения замысел состоит в том, чтобы каждая сеть видела компьютеры из другой сети так, как если бы они были непосредственно подключены к одному маршрутизатору (правда немного медленному и иногда теряющему пакеты).

Это означает, что компьютер 192.168.1.20 может проверить доступность компьютера 192.168.2.34, с помощью команды

ping 192.168.2.34

и это будет работать без каких-либо дополнительных настроек как на одном, так и на другом компьютере. Из-за особенностей протокола SMB для обеспечения возможности компьютерам с Windows® ''видеть'' компьютеры в другой сети и просматривать их сетевые ресурсы (точно так же как в своей сети) на шлюзах необходимо установить дополнительное програмное обеспечение (это выходит за рамки данной главы, дополнительная информация содержится в главе Разд. 23.9 ). Весь трафик между сетями при этом будет передаетя в зашифрованном виде.

Создание VPN между этими двумя сетями будет выполнено в несколько этапов:

  1. Создание ''виртуального'' сетевого подключения между двумя сетями через интернет. Тестирование подключения с помощью ping(8), для проверки работоспособности сетевой чести.

  2. Применение политики безопасности для шифрации передаваемого между сетями трафика. Тестирование с помощью tcpdump(1) для проверки криптографической части.

  3. Настройка дополнительных программ на шлюзах FreeBSD, чтобы компьютеры Windows из одной сети ''видели'' компьютеры в другой через VPN.

14.10.3.1. Шаг 1: Создание и тестирование ''виртуального'' сетевого подключения

Предположим, на шлюзе сети #1 (с публичным адресом A.B.C.D, приватным адресом 192.168.1.1) запускается команда проверки доступности приватного адреса шлюза #2:

ping 192.168.2.1

Что необходимо для того, что бы она завершилась успешно?

  1. Шлюз должен знать, как достичь 192.168.2.1. Другими словами, у него должен быть маршрут к 192.168.2.1.

  2. Приватные IP адреса, такие как диапазон 192.168.0.0/16 не маршрутизируются в интернете, то есть маршрутизаторы провайдеров не передают пакеты с адресами из этих сетей. Поэтому каждый пакет, отправляемый на 192.168.2.1 должен быть ''завернут'' в другой пакет. Исходным адресом нового пакета должен быть A.B.C.D, а адресом назначения W.X.Y.Z. Этот процесс называется инкапсуляцией.

  3. Когда этот пакет достигнет W.X.Y.Z, его необходимо будет ''развернуть'' (декапсулировать) и полученный исходный пакет доставить по адресу 192.168.2.1 (в данном случае это тот же самый хост).

Это и есть создание ''туннеля'' между двумя сетями. Два конца ''туннеля'' -- это IP адреса A.B.C.D и W.X.Y.Z. Туннель используется для передачи трафика с приватными IP адресами через интернет.

Туннели различаются по способам инкапсуляции. В данной главе описывается использование инкапсуляции IPIP (она описана в RFC2003), так как она шире всего поддерживается во FreeBSD так и в других ОС семейства UNIX®.

В FreeBSD такой туннель создается с помощью устройства generic interface, или gif. Как можно догадаться, для настройки интерфейса gif на каждом хосте нужно указать четырьмя IP адреса: два для публичных IP (внешних) и два для приватных IP (внутренних).

В ядре обеих компьютеров FreeBSD должна иметься поддержка устройства gif. Это можно обеспечить добавлением строки

pseudo-device gif

к файлу настройки ядра на обеих компьютерах, с последующей компиляцией, установкой и перезагрузкой. Альтрнативный метод -- загрузка модуля ядра для данного устройства с помощью команды

kldload if_gif

Настройка туннеля это двухшаговый процесс. Во-первых, необходимо задать сведения о внешнем (или публичном) IP адресе, затем о приватном (внутреннем).

Во FreeBSD 4.3 и младше первый шаг делается с помощью gifconfig(8). Начиная с FreeBSD 4.4 функциональность, предоставляемая утилитой gifconfig(8), была внесена в ifconfig(8). Второй шаг выполняется с помощью комманды ifconfig(8).

Итак, на шлюзе сети #1 для настройки туннеля необходимо выполнить следующие две команды:

для FreeBSD 4.3 и более ранних:

gifconfig gif0 A.B.C.D W.X.Y.Z
ifconfig gif0 inet 192.168.1.1 192.168.2.1 netmask 0xffffffff
     

для FreeBSD 4.4 и старше:

ifconfig gif0 create
ifconfig gif0 tunnel A.B.C.D W.X.Y.Z
ifconfig gif0 inet 192.168.1.1 192.168.2.1 netmask 0xffffffff
     

На шлюзе #2 выполняются аналогичные команды, но с IP адресами в обратном порядке:

Для FreeBSD 4.x и более ранних:

gifconfig gif0 W.X.Y.Z A.B.C.D
ifconfig gif0 inet 192.168.2.1 192.168.1.1 netmask 0xffffffff
     

Для FreeBSD 5.X и старше:

ifconfig gif0 create
ifconfig gif0 tunnel W.X.Y.Z A.B.C.D
ifconfig gif0 inet 192.168.2.1 192.168.1.1 netmask 0xffffffff
     

Для просмотра текущих настроек интерфеса на FreeBSD 4.3 и младше используется команда

gifconfig gif0

а на FreeBSD 4.4 и старше

ifconfig gif0

Например, на шлюзе сети #1 вы увидите:

# gifconfig gif0
gif0: flags=8011<UP,POINTTOPOINT,MULTICAST> mtu 1280
inet 192.168.1.1 --> 192.168.2.1 netmask 0xffffffff
physical address inet A.B.C.D --> W.X.Y.Z
     

Из этого листинга видно что был создан туннель между физическими адресами A.B.C.D и W.X.Y.Z, и на туннель установленный IP адреса 192.168.1.1 (на ближнем конце) и 192.168.2.1 (на дальнем конце). При создании туннеля автоматически происходит добавление записи к таблице маршрутизации, вы можете проверить запись командой netstat -rn. Вот часть вывода этой команды, содержащей данную запись, на шлюзе сети #1.

# netstat -rn
Routing tables

Internet:
Destination      Gateway       Flags    Refs    Use    Netif  Expire
...
192.168.2.1      192.168.1.1   UH        0        0    gif0
...
     

Символ ''H'' в поле ''Flags'' означает, что это маршрут к хосту. Это означает, что шлюз #1 знает, как достичь шлюза #2, но не знает как достичь остальной части соответствующей сети (аналогичные утверждения верны и для другого шлюза). Эту проблему мы будем решать позже.

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

Если вы разрешаете весь трафик через VPN, то это сильно облегчит тестирование. Вы всегда можете усилить защиту позже. Если вы используете на шлюзах ipfw(8), то команды аналогичные следующим

ipfw add 1 allow ipencap from A.B.C.D to W.X.Y.Z
ipfw add 1 allow ipencap W.X.Y.Z to A.B.C.D
ipfw add 1 allow ip from any to any via gif0

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

Выполненных действий достаточно для проведения тестирования достижимости приватного адреса одного шлюза с другого с помощью команды ping. Например, на шлюзе #1 можно выполнить команду

ping 192.168.2.1

и получить ответ, и, аналогично на другом шлюзе.

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

route add 192.168.2.0 192.168.2.1 netmask 0xffffff00
     

Она говорит, что для достижения хостов в сети 192.168.2.0/24 пакеты нужно переправлять хосту 192.168.2.1 (а как его достичь, первому шлюзу уже известно). Разумеется, на другом шлюзе требуется выполнить аналогичную команду, но с адресами 192.168.1.x. Теперь IP трафик с хостов в одной сети может быть доставлен хостам в другой сети.

Выполнение указанных команд можно автоматизировать с использованием стартовых скриптов FreeBSD. Конфигурирование устройства gif на шлюзе #1 выполняется с помощью следующих параметров в файле /etc/rc.conf:

gifconfig_gif0="A.B.C.D W.X.Y.Z"
ifconfig_gif0="inet 192.168.1.1 192.168.2.1 netmask 0xffffffff"
     

Формирование правил маршрутизации на шлюзе #1 производится с помощью следующих записей:

static_routes="vpn"
route_vpn="192.168.2.0 192.168.2.1 netmask 0xffffff00"
     

Аналогичные записи добавляются в файл /etc/rc.conf и на шлюзе #2

VPN между двумя сетями создана на две трети, поскольку наша сеть (Network) уже виртуальная (Virtual), но еще частная (Рrivate). Вы этом можно легко убедиться, выполняя в разных сессиях на шлюзе #1 команды ping(8) и tcpdump(1):

tcpdump -n host 192.168.2.1 and proto ipencap

В другой сессии на этом же хосте запустите

ping 192.168.2.1

Вы увидите примерно такие строки:

16:10:24.018080 IP: A.B.C.D > W.X.Y.Z: IP 192.168.1.1 > 192.168.2.1: ICMP: echo request
16:10:24.018109 IP: W.X.Y.Z > A.B.C.D: IP 192.168.2.1 > 192.168.1.1: ICMP: echo reply
16:10:25.018814 IP: A.B.C.D > W.X.Y.Z: IP 192.168.1.1 > 192.168.2.1: ICMP: echo request
16:10:25.018847 IP: W.X.Y.Z > A.B.C.D: IP 192.168.2.1 > 192.168.1.1: ICMP: echo reply
16:10:26.028896 IP: A.B.C.D > W.X.Y.Z: IP 192.168.1.1 > 192.168.2.1: ICMP: echo request
16:10:26.029112 IP: W.X.Y.Z > A.B.C.D: IP 192.168.2.1 > 192.168.1.1: ICMP: echo reply
     

Для получения большего объема данных пакета и более детального его анализа можно использовать параметры tcpdump(1) -s и -Xv.

Видно, что ICMP-сообщения пересылаются в обе стороны незашифрованными. Конечно же это неприемлемо. Поэтому следующий раздел будет посвящен защите соединения между двумя сетями от просмотра третьей стороной.

Резюме:

  • На обоих шлюзах настройте ядро с ''pseudo-device gif'' или загрузите модуль ядра if_gif.

  • В файл /etc/rc.conf на шлюзе #1 добавляются следующие следующие строки (с подстановкой настоящих IP-адресо где необходимо).

    gifconfig_gif0="A.B.C.D W.X.Y.Z"
    ifconfig_gif0="inet 192.168.1.1 192.168.2.1 netmask 0xffffffff"
    static_routes="vpn"
    route_vpn="192.168.2.0 192.168.2.1 netmask 0xffffff00"
         
    
  • Модифицируется скрипт сетевого экрана (/etc/rc.firewall, или подобный) на обоих хостах, в него добавляется (с подстановкой настоящих IP-адресо где необходимо)

    ipfw add 1 allow ipencap from A.B.C.D to W.X.Y.Z
    ipfw add 1 allow ipencap W.X.Y.Z to A.B.C.D
    ipfw add 1 allow ip from any to any via gif0
    
  • Выполняются аналогичные изменения в /etc/rc.conf на шлюзе #2, с изменением порядка IP адресов.

14.10.3.2. Шаг 2: Защита соединения

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

Здесь будут рассмотрены два аспекта настройки.

  1. У хостов должен быть способ согласования используемого алгоритма шифрования. Как только хосты договорятся об этом, можно говорить об установленном между ними ''безопасном соединении''.

  2. Должен быть механизм определения, какой трафик необходимо шифровать. Незачем, конечно, шифровать всё, достаточно зашифровать только трафик, идущий через VPN. Правила, определяющие, что подлежит шифрованию, называются ''политикой безопасности''.

Безопасное соединение и политика безопасности поддерживаются ядром, но их настройки измененяются программами пользователя. Но в первую очередь необходимо включить поддержку протоколов IPsec и Encapsulated Security Payload (ESP) в ядре. Это делается добавлением в файл настройки ядра параметров:

options IPSEC
options IPSEC_ESP

с последующими перекомпилированием, переустановкой и перезагрузкой. Как и раньше, необходимо провести эту операцию на общих шлюзах.

Есть два варианта настройки параметров безопасности (security associations): можно настроить их вручную для обоих хостов (задав алгоритм шифрования, ключи для шифрования и так далее) или использовать даемоны, реализующие Internet Key Exchange protocol (IKE), которые выполнят эту настройку за вас. Мы рассотрим оба способа, хотя рекомендуем последнеий из них, как более безопасный.

Редактирование и отображение политики и параметров безопасности выполняется с помощью команды setkey(8). Она используется для настройки таблиц политики безопасности ядра так же, как route(8) используется для настройки таблиц маршрутизации ядра. setkey также может отображать текущие параметры безопасности (если продолжить аналогию дальше, то это соответствует netstat -r).

Ручная настройка параметров безопасности

При ручной настройке параметров безопасности ядру необходимо сообщить для каждого VPN соединения какой алгоритм мы будет использоваться для шифрования трафика (и используемый при этом секретный ключ) и какой алгоритм будет использоваться при дешифрации входящего трафика (и используемый при этом секретный ключ). При использовании криптографической проверки целостности заголовка необходимо так же указать используемые алгориты и ключи, которые будут использоватся для создания и проверки подписи заголовка. Следует заметить, что и алгоритмы, и ключи используемые для формирования исходящих пакетов могут не совпадать с алгоритмами и/или ключами, используемыми для принимаемых пакетов. Это значит, что можно отправляемые пакеты шифровать и подписывать одним набором алгоритмов и ключей, а принимаемые пакеты расшифровывать и проверять целостность с помощью другого набора. Естественно, другая сторона должна действовать согласованно и использовать первый набор алгоритоов и ключей для дешифрации принимаемого трафика, а второй надор алгоритмов и ключей -- для формирования исходящего трафика.

В setkey(8) предусмотрен язык определения параметров безопасности. Можно вводить инструкции по настройке со стандартного ввода или использовать параметр -f для чтения таких инструкций из файла с заданным именем.

Для шифрования всего VPN трафика с публичного адреса шлюза #1 (A.B.C.D) на публичный адрес шлюза #2 (W.X.Y.Z) будет использоваться алгоритмом 3DES с ключем ''secret789012345678901234'' (длина ключа ровно 24 символа, для данного алгоритма нельзя использовать ключи другой длины), для дешифрования получаемого трафика будет использоваться тот же алгоритм, но с другим ключем -- ''Secret789012345678901234''.

Загололвки будут подписываться и проверяться с помощью алгоритма HMAC-SHA1. Для формирования подписи будет использоваться ключ ''sEcret78901234567890'' (для этого алгоритма длина ключа должна составлять 20 символов), а проверка будет выполняться с ключом ''seCret78901234567890''.

Замечание: Конечно, не стоит использовать в качестве ключа такие простые варианты -- здесь применяются обычные правила выбора паролей.

Задание этих ключей и алгоритмов производится следующей последовательностью инструкций setkey(8):

add A.B.C.D W.X.Y.Z esp 0x10001 -E 3des-cbc "secret789012345678901234";
add W.X.Y.Z A.B.C.D esp 0x10002 -E 3des-cbc "Secret789012345678901234";
add A.B.C.D W.X.Y.Z ah 0x10001 -A hmac-sha1 "sEcret78901234567890";
add W.X.Y.Z A.B.C.D ah 0x10002 -A hmac-sha1 "seCret78901234567890";


Можно поместить эти команды в файл (например, /etc/ipsec.conf) и выполнить команду

# setkey -f /etc/ipsec.conf

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

add указывает setkey(8), что к базе данных политики безопасности необходимо добавить новое правило. Остальная часть строки указывает когда и как оно будет использоваться. A.B.C.D и W.X.Y.Z это IP адреса хостов, трафик между которыми попадает под данное правило политики безопасности. Параметр esp сообщает ядру, что эти параметры политики безопасности устанавливаются для протокола ESP.

Параметр 0x10001 является 32-битным индексом SPI, он назначается администратором по своему усмотрению. Этот индекс будет помещться в отправлемые IPsec пакеты и и по нему удаленный хост будет выбирать необходимые алгоритм и ключ для дешифрования полученных пакетов и проверки целостности. Поэтому для каждой пары хостов должно соблюдаться совпадение используемого индекса SPI, алгоритма и ключа.

Параметр -E указывает какие алгоритм и ключ будет для шифрования (в нашем случае это 3DES с ключем "secret789012345678901234").

Аналогичным образом указываются параметры политики безопасности и и для протокола AH, но в этом случае используется параметр -A. Он указывает какие алгоритм и ключ будут использоваться для вычисления криптографической контрольной суммы (подписи) данных пакетов. Следует отметить, что данный параметр можно указывать и для протокола ESP, совместно с параметром -E. В этом случае будет генерироваться дополнительная криптографическая контрольная сумма для содержимого пакета (в отличии от AH, когда контрольная сумма вычисляется не только для содержимого, но и для заголовка пакета). Совместное использование обеих криптографических контрольных сумм допустимо, но является избыточным. Поэтому мы ограничиваемся генерацией только одной криптографической контрольной суммы средствами протокола AH.

Автоматическая настройка параметров безопасности

Существует множество даемонов для управления параметрами безопасности в FreeBSD. Здесь будет описано использование одного из них, racoon -- он доступен в виде порта security/racoon в Коллекции Портов FreeBSD. Этот даемон должен работать на обоих шлюзах. На каждом из хостов в его настройках указывается IP адрес другого конца VPN и выбранный вами секретный ''предварительный'' ключ (должен быть одним и тем же на обоих шлюзах).

Эти два даемона подключаются друг к другу и убеждаются, что они именно те, за кого себя выдают (используя секретный предварительный ключ). Затем даемоны генерируют новые секретные ключи и используют их для шифрования трафика через VPN. Они периодически изменяют эти ключи, так что даже если атакующий сломает один из ключей (что теоретически почти невозможно) это практически ничего ему не даст -- за это время ключ, скорее всего, уже был сменен на другой.

Настройки racoon сохраняются в ${PREFIX}/etc/racoon/racoon.conf. Можно использовать следующий пример конфигурационного файла, мало отличающийся от дистрибутивного примера ${PREFIX}/etc/racoon/racoon.conf.dist.

path include "/usr/local/etc/racoon" ;
path pre_shared_key "/usr/local/etc/racoon/psk.txt" ;
path certificate "/usr/local/etc/cert" ;
# "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.
}

remote anonymous
{
        exchange_mode aggressive,main;
        my_identifier address;
        peers_identifier address;
        proposal_check obey;    # obey, strict or claim

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

sainfo anonymous
{
        pfs_group 1;
        encryption_algorithm 3des ;
        authentication_algorithm hmac_sha1;
        compression_algorithm deflate ;
}


Другим компонентом настройки racoon, который потребуется изменить, является предварительный ключ. При настройке по умолчанию racoon ищет его в файле ${PREFIX}/etc/racoon/psk.txt. Необходимо отметить, что предварительный ключ не используется для шифрования пользовательского трафика через VPN соединение. Это просто маркер, позволяющий управляющими ключами даемонам доверять друг другу.

Замечание: Следует заметить, что если по какой-либо причине два даемона будут использовать различные предварительные ключи, то они просто не смогу установить полноценное соединение, а в диагностике это будет выглядеть как непонятная ошибка протокола IKE.

psk.txt содержит строку для каждого удаленного шлюза, с которым происходит соединение. В этом примере два шлюза и, следовательно, каждый файл psk.txt будет содержать ровно одну строку (каждый конец VPN общается только с другим концом.

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

W.X.Y.Z            secret

То есть публичный IP-адрес противоположной стороны, пробел и текстовая строка c секретной фразой. Конечно, в качестве ключевой фразы слово ''secret'' использовать не стоит, а следует применить обычные правила выбора паролей.

На шлюзе #2 строка будет выглядеть аналогично:

A.B.C.D            secret

То есть публичный IP адрес удаленной стороны и та же самая секретная фраза. Перед запуском racoon режим доступа к файлу psk.txt должен быть установлен в 0600 (т.е. запись и чтение только для root).

Необходимо запустить racoon на обоих шлюзах. Также потребуется добавить правила сетевого экрана для разрешения IKE трафика, передающегося по UDP через порт ISAKMP (Internet Security Association Key Management Protocol). Как и раньше, стоит их расположить насколько возможно ближе к началу набора правил.

ipfw add 1 allow udp from A.B.C.D to W.X.Y.Z isakmp
ipfw add 1 allow udp from W.X.Y.Z to A.B.C.D isakmp
     

После запуска даемона racoon можно попробовать выполнить команду ping с одного шлюза на другой. Соединение все еще не зашифровано, но racoon уже будет согласовывать параметры безопасности между двумя хостами. Это может занять некоторое время и тогда перед началом ответа команды ping будет заметна небольшая задержка.

Как только параметры безопасности установлены, вы можете просмотреть их используя setkey(8). Запуск

setkey -D

на любом из хостов предоставит информацию о текущих параметрах безопасности.

Полдела сделано. Теперь следует настройть политику безопасности.

Настройка политики безопасности

Для создания разумной политики безопасности давайте вспомним, что уже было настроено c обоих концов соединения.

Каждый отправляемый IP пакет имеет заголовок, содержащий информацию о пакете. Заголовок включает IP адреса источника и назначения. Как уже говорилось, приватные IP адреса (такие, как 192.168.x.y) не могут появиться в интернет. Они должны быть сначала включены внутрь другого пакета, в котором IP-адреса источника и назначения являются публичными.

То есть исходящий пакет, который выглядит примерно так:

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

Эту инкапсуляцию производит устройство gif. Теперь у пакета есть реальный IP адрес, а исходный пакет включен в этот пакет в виде данных и его можно передавать через интернет. Но еще необходимо зашифровать передаваемы по VPN трафик.

Попробуем сначала словами описать требуемую политику. Можно сформулировать следующие требования:

  • Если пакет отправляется с A.B.C.D, и предназначен для W.X.Y.Z, расшифровать его, используя необходимые параметры безопасности.

  • Если пакет отправляется с W.X.Y.Z, и предназначен для A.B.C.D, расшифровать его, используя необходимые параметры безопасности.

Это почти то, что нужно, но ещё совсем. Если сделаеть именно так, то будет зашифрован весь трафик от W.X.Y.Z и к нему, даже если он не является частью VPN. Правильная политика такова:

  • Если пакет отправляется с A.B.C.D, в нем инкапсулирован другой пакет и адрес назначения W.X.Y.Z, зашифровать его, используя необходимые параметры безопасности.

  • Если пакет отправляется с W.X.Y.Z, в нем инкапсулирован другой пакет и адрес назначения A.B.C.D, рашифровать его, используя необходимые параметры безопасности.

Различие тонкое, но необходимое.

Политика безопасности также устанавливается с использованием setkey(8), с помощью ее языка. Как и в случае определения параметров безопасности, соответствующие инструкции можно водить или со стандартного ввода, или использовать параметр -f для чтения таких инструкций из файла с заданным именем.

Настройка на шлюзе #1 (с публичным IP-адресом A.B.C.D) для включения шифрования всего предназначенного W.X.Y.Z трафика VPN выглядит так:

spdadd A.B.C.D/32 W.X.Y.Z/32 ipencap -P out ipsec esp/transport//require;
     

Можно поместить эту инструкцию в файл (например, /etc/ipsec.conf) и выполнитб команду

# setkey -f /etc/ipsec.conf

spdadd указывает setkey(8), что данное правило надо добавить к базе данных политики безопасности. Остальная часть строки указывает какие пакеты будут попадать под данную политику. A.B.C.D/32 и W.X.Y.Z/32 -- это IP адреса и сетевые маски, определяющие сети или хосты, к которым она будет применяться (в данном случае -- это наши шлюзы). Параметр ipencap сообщает ядру, что эта политика должна применяться только к пакетам, инкапсулирующим другие пакеты по протоколу IPIP. Параметр -P out сообщает, что эта политика применяется к исходящим пакетам, а параметр ipsec -- то, что пакет обработан стеком IPsec.

Оставшаяся часть строки определяет, как именно эти пакеты будут обработаны. В данном случае будет использоваться протокол esp, причем transport показывает, что дальнейшая инкапсуляция в IPsec будет осуществлена без использования дополнительного заголовка IP. Мы используем именно этот режим (транспортный режим IPsec), поскольку для тунелирования используется gif.

Этот способ дает более гибкие и широкие возможности для организации VPN. В частности, он позволяет передавать мультикастовый трафик и использовать на данных туннелях протоколы динамической маршрутизации (OPSF, RIP, RIPv2). При организации туннеля только средствами IPsec (использование самого IPsec в туннельном режиме, без использования GIF-туннеля) данные возможности недоступны, а маршрутизация сетей между туннелями должна будет обеспечиваться правилами политик безопасности IPsec, что делает невозможным их динамическую модификацию и согласование с таблицей маршрутизации.

Использование других технологий организации туннелей (например, GRE) позволяет передавать по туннелю также протоколы, отличные от IP (например IPX), что в рамках только IPsec не возможно в принципе.

Параметр require требует шифровать пакеты, попадающих под это правило.

Замечание: Т.к. для шифрования необходимо наличие ключей, то если ключи не были установлены автоматически по протоколу IKE или вручную утилитой setkey(8), то исходящего трафика просто не будет. Никаких диагностическихсообщений или сообщений об ошибках в этом случае не генерируется.

Таким образом мы только шифруем содержимое передаваемых пакетов, никак не защищая заголовок от подделки или модификации. Для включения криптографической защиты и заголовка передаваемых пакетов (естественно это потребует дополнительных накладных расходов, т.е. размер заголовка будет увеличен) необходимо дополнитьь инструкцию spdadd:

spdadd A.B.C.D/32 W.X.Y.Z/32 ipencap -P out ipsec esp/transport//require ah/transport//require;

Замечание: Обратите внимание, что сначала описываются правила, касающиеся esp, а потом уже ah, этот порядок очень важен!

Это правило соответствует только исходящим пакетам. Для входящих пакетов потребуется похожее правило.

spdadd W.X.Y.Z/32 A.B.C.D/32 ipencap -P in ipsec esp/transport//require;

Или, при использовании криптографической защиты заголовка

spdadd W.X.Y.Z/32 A.B.C.D/32 ipencap -P in ipsec esp/transport//require ah/transport//require;

Обратите внимание, что вместо out используется in и IP адреса переставлены.

Второму шлюзу (с публичным IP-адресом W.X.Y.Z) ребуются похожий набор правил.

spdadd W.X.Y.Z/32 A.B.C.D/32 ipencap -P out ipsec esp/transport//require;
spdadd A.B.C.D/32 W.X.Y.Z/32 ipencap -P in ipsec esp/transport//require;

Или, при использовании криптографической защиты заголовка

spdadd W.X.Y.Z/32 A.B.C.D/32 ipencap -P out ipsec esp/transport//require ah/transport//require;
spdadd A.B.C.D/32 W.X.Y.Z/32 ipencap -P in ipsec esp/transport//require ah/transport//require;

Наконец, нужно дополнить правила межсетевого экрана для прохождения пакетов IPsec и IPENCAP в обе стороны. На обеих хостах потребуется добавить следующие правила:

ipfw add 1 allow esp from A.B.C.D to W.X.Y.Z
ipfw add 1 allow esp from W.X.Y.Z to A.B.C.D
ipfw add 1 allow ipencap from A.B.C.D to W.X.Y.Z
ipfw add 1 allow ipencap from W.X.Y.Z to A.B.C.D
     

Или, при использовании криптографической защиты заголовка

ipfw add 1 allow ah from A.B.C.D to W.X.Y.Z
ipfw add 1 allow ah from W.X.Y.Z to A.B.C.D
ipfw add 1 allow ipencap from A.B.C.D to W.X.Y.Z
ipfw add 1 allow ipencap from W.X.Y.Z to A.B.C.D
     

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

Исходящие пакеты теперь будут выглядеть примерно так:

Или, при использовании криптографической защиты заоловка

После получения пакетов на удаленном конце VPN-соединения, они будут расшифрованы (используя установленные параметры безопасности). Затем они будут переданы интерфейсу gif, который ''развернет'' второй слой, оставив пакет с внутренними адресами, который сможет попасть во внутреннюю сеть.

Проверить безопасность можно таким же запуском команды ping(8), который использовался ранее. Паралельный запуск в двух разных сессиях шлюзе #1 команд

tcpdump -n host W.X.Y.Z

и

ping 192.168.2.1

покажет примерно такой вывод команды tcpdump(1):

16:10:24.018080 IP: A.B.C.D > W.X.Y.Z: ESP(spi=0x0dcc9c1f,seq=0x12)
16:10:24.018109 IP: W.X.Y.Z > A.B.C.D: ESP(spi=0x0a87484f,seq=0x1c)
16:10:25.018814 IP: A.B.C.D > W.X.Y.Z: ESP(spi=0x0dcc9c1f,seq=0x13)
16:10:25.018847 IP: W.X.Y.Z > A.B.C.D: ESP(spi=0x0a87484f,seq=0x1d)
16:10:26.028896 IP: A.B.C.D > W.X.Y.Z: ESP(spi=0x0dcc9c1f,seq=0x14)
16:10:26.029112 IP: W.X.Y.Z > A.B.C.D: ESP(spi=0x0a87484f,seq=0x1e)

Видно, что теперь tcpdump(1) показывает ESP пакеты. Если просмотреть их содержимое, используя параметры -X и -s, то будет видно нечто непонятное, поскольку применяется шифрование.

Поздравляем. Настройка VPN между двумя сетями окончена.

Резюме

  • Настроить оба ядра с параметрами:

    options IPSEC
    options IPSEC_ESP
         
    
  • Установить security/racoon. Отредактировть ${PREFIX}/etc/racoon/psk.txt на обоих шлюзах, добавив запись для каждого IP адреса удаленного хоста и общий предварительный секретный ключ, который будет известен им обеим. Убедиться, что режим доступа к файлу 0600.

  • Добавить к /etc/rc.conf на каждом хосте следующие строки:

    ipsec_enable="YES"
    ipsec_file="/etc/ipsec.conf"
         
    
  • Создать /etc/ipsec.conf на каждом хосте с необходимыми строками spdadd. На шлюзе #1 они будут такими:

    spdadd A.B.C.D/32 W.X.Y.Z/32 ipencap -P out ipsec
      esp/transport//require;
    spdadd W.X.Y.Z/32 A.B.C.D/32 ipencap -P in ipsec
      esp/transport//require;
    

    Или, при использовании криптографической защиты заголовка:

    spdadd A.B.C.D/32 W.X.Y.Z/32 ipencap -P out ipsec
      esp/transport//require ah/transport//require;
    spdadd W.X.Y.Z/32 A.B.C.D/32 ipencap -P in ipsec
      esp/transport//require ah/transport//require;
    

    А на шлюзе #2 таким:

    spdadd W.X.Y.Z/32 A.B.C.D/32 ipencap -P out ipsec
      esp/transport//require;
    spdadd A.B.C.D/32 W.X.Y.Z/32 ipencap -P in ipsec
      esp/transport//require;
    

    Или, при использовании криптографической защиты заголовка:

    spdadd W.X.Y.Z/32 A.B.C.D/32 ipencap -P out ipsec
      esp/transport//require ah/transport//require;
    spdadd A.B.C.D/32 W.X.Y.Z/32 ipencap -P in ipsec
      esp/transport//require ah/transport//require;
    
  • Добавить к сетевым экранам обоих хостов правила для прохождения IKE и IPsec трафика:

    ipfw add 1 allow udp from A.B.C.D to W.X.Y.Z isakmp
    ipfw add 1 allow udp from W.X.Y.Z to A.B.C.D isakmp
    ipfw add 1 allow esp from A.B.C.D to W.X.Y.Z
    ipfw add 1 allow esp from W.X.Y.Z to A.B.C.D
         
    

    Или, при использовании криптографической защиты заголовка:

    ipfw add 1 allow udp from A.B.C.D to W.X.Y.Z isakmp
    ipfw add 1 allow udp from W.X.Y.Z to A.B.C.D isakmp
    ipfw add 1 allow ah from A.B.C.D to W.X.Y.Z
    ipfw add 1 allow ah from W.X.Y.Z to A.B.C.D
             
    

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

14.10.4. Взаимодействие с файрволом

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

options      IPSEC_FILTERGIF         #filter ipsec packets from a tunnel

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

14.10.5. Проблемы с MTU

Применение инкапсуляции IPIP, использование протоколов шифрации ESP и вычисления контрольных сумм AH добавляет дополнительную служебную информацию к обрабатываемым пакетам. Размер пакета после этого может превысить MTU исходящего интерфеса. Обычно на туннельном интерфейсе указывают размер MTU, меньший используемого по умолчанию (1500 байт) на величину дополнительных заголовков (IPsec и IPIP). В этом случае для слишком больших пакетов будет генерироваться ICMP сообщение ''Fragmentation Needed''. К сожалению, некоторые хосты и шлюзы в интернете полностью отфильтровывают все виды ICMP-сообщений, и в этом случае связь с хостом, отфильтровыващим эти ICMP-сообщения (или находящимся за таким шлюзом или межсетевым экраном) через туннель будет невозможна из-за неработоспособности алгоритма Path MTU discovery. Альтернативой является указание на туннельном интерфейсе стандартного MTU (1500 байт), в этом случае фрагментация будет происходить после формирования IPsec заголовков, а обратная сборка пакетов -- на другом шлюзе, перед проверкой IPsec заголовков и дешифрованием пакета. В этом случае ценой больших накладных расходов (дополнительный процессорный ресурс на фрагментацию и сборку пакетов, дополнительный трафик) и возможным ухудшением связи (увеличение вероятности потери пакета) проблема коммуникации с такими хостами всё же может быть решена.

Этот, и другие документы, могут быть скачаны с ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/.

По вопросам связанными с FreeBSD, прочитайте документацию прежде чем писать в <questions@FreeBSD.org>.
По вопросам связанным с этой документацией, пишите <doc@FreeBSD.org>.
По вопросам связанным с русским переводом документации, пишите в рассылку <frdp@FreeBSD.org.ua>.
Информация по подписке на эту рассылку находится на сайте проекта перевода.