Данная статья содержит краткое описание возможностей и руководство по настройке основных функций программного решения для построения виртуальных частных сетей - OpenVPN.Пару слов о VPNVPN (Virtual Private Network - виртаульная частная сеть) - логическая сеть для защищенной передачи данных по незащищенным каналам (вроде Интернет). Понятие VPN сугубо концептуальное, практические реализации этой идеи могут подразделяться на массу видов по целому ряду критериев в зависимости от типа реализации (программные, аппаратные, интегрированные), уровня модели OSI, на котором они работают, или целевому предназначению (Intranet, Remote Access и др.). Общим для каждого из этих решений я бы назвал основополагающую формулу "протокол туннелирования + протокол шифрования = VPN".
Наиболее распространенные протоколы туннелирования (
IP-in-IP,
PPPoE,
GRE,
PPTP,
L2TP) описаны в соответствующем цикле статей. Касательно протоколов шифрования замечу лишь, что по этому критерию большинство реализаций VPN можно подразделить на те, в которых используется IPSec, и те, в которых используется SSL/TLS.
OpenVPNOpenVPN - кросс-платформенная программная реализация VPN на основе протокола шифрования SSL/TLS. К достоинствам OpenVPN можно отнести простоту установки и настройки (дистрибутив для Windows имеет размер порядка 1 МБ); функционал OpenVPN позволяет создавать подключения через прокси-серверы; используется всего лишь один UDP-порт (который можно выбрать на собственное усмотрение), что в частности позволяет устанавливать соединение через NAT; предусмотрен механизм инкапсуляции не только IP-пакетов, но и Ethernet-фреймов.
Рассмотрению перечисленных функций OpenVPN посвящена остальная часть статьи. Несмотря на то, что описание процесса конфигурирования и использования OpenVPN достаточно хорошо освещены в различных книгах и руководствах, надеюсь, и эта заметка найдет своего читателя.
Установка OpenVPNВ качестве примера далее рассматривается использование OpenVPN на хостах под управлением различных ОС - Windows XP SP2 (win-бокс), OpenSUSE Linux 11.0 (linux-бокс), FreeBSD 7.1 (fbsd-бокс).
На fbsd установить OpenVPN можно из пакетов:
pkg_add -r openvpn
В OpenSUSE проще всего пройти на оффсайт и найти на
странице поиска ссылку на однокликовый установщик по ключевому слову openvpn. Найти инсталляционный файл для win-бокса также не составляет проблем (к примеру, я использовал
этот).
Простейший нешифрованный туннельДля начала можно рассмотреть простейший нешифрованный туннель со следующей схемой организации:

Оба хоста имеют реальные статические IP-адреса (ни один из них не находится за NAT). Перед установлением туннеля нужно проверить связь между хостами (
ping 192.168.0.1 и
ping 192.168.1.2). Если связи нет, проверить настройки фаерволов, таблицы маршрутизации и внести необходимые исправления. После этого на linux-боксе:
openvpn --remote 192.168.0.1 --dev tun0 --ifconfig 10.0.0.1 10.0.0.2
Как легко догадаться, в параметрах команды были указаны адрес удаленного хоста, имя интерфейса, соответствующего туннелю, а также заданы адреса локального (10.0.0.1) и удаленного (10.0.0.2) концов туннеля.
На win-боксе "Пуск" - "Выполнить" - cmd :
cd c:\Program Files\OpenVPN\bin
openvpn.exe --remote 192.168.0.2 --dev tun0 --ifconfig 10.0.0.2 10.0.0.1
Если все было сделано верно и не вывалится никаких ошибок, можно проверить связь, запустив
ping 10.0.0.1 на win-боксе или
ping 10.0.0.2 на linux и вывести на экран параметры вновь созданных интерфейсов с помощью
ipconfig /all на win и
ifconfig на linux. Если пронаблюдать процесс пингования с помощью какого-нибудь анализатора протоколов (например, я воспользовался wireshark на win), можно проследить как OpenVPN инкапсулирует IP-пакет с ICMP-запросом эха в UDP и отправляет его по сети без всякого шифрования:
Frame 1 (102 bytes on wire, 102 bytes captured)
Ethernet II, Src: 00:50:56:c0:00:01, Dst: 00:0c:29:7f:db:94
Internet Protocol, Src: 192.168.0.1 (192.168.0.1), Dst: 192.168.1.2 (192.168.1.2)
User Datagram Protocol, Src Port: openvpn (1194), Dst Port: openvpn (1194)
Data (60 bytes):
0000 45 00 00 3c b2 b8 00 00 80 01 74 06 0a 00 00 02
0010 0a 00 00 01 08 00 3f 5c 04 00 0a 00 61 62 63 64
0020 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74
0030 75 76 77 61 62 63 64 65 66 67 68 69
Содержимое UDP-датаграммы, которое wireshark не пожелал интерпретировать, и есть тот самый инкапсулированный IP-пакет - первый байт (45) - это версия (4) IP-протокола и длина IP-заголовка (пять 32-битных слов); второй байт (00) - это поле "тип сервиса", по-умолчанию с нулевым значением; третий и четвертый (00 3с) - это общая длина пакета 60 байт (hex: 00 3c = dec: 60) и так далее.
Если в приведенном выше примере какой-либо из хостов находится за NAT'ом или имеет динамический IP, то в командной строке противоположного хоста нужно указать вместо --remote ключ --float без параметров. Чтобы установить соединение по UDP-порту, отличному от установленного по-умолчанию (1194), нужно в команде задать ключ --port после которого в качестве параметра указать номер нужного порта. Чтобы в вышеприведенном примере использовать инкапсуляцию в UDP пользовательских Ethernet-фреймов, а не IP-пакетов, нужно использовать следующие команды:
openvpn --remote 192.168.0.1 --dev tap0 --ifconfig 10.0.0.1 255.255.255.0
на linux, или
cd c:\Program Files\OpenVPN\bin
openvpn.exe --remote 192.168.0.2 --dev tap0 --ifconfig 10.0.0.2 255.255.255.0
для win.
Разница в том, что использовать нужно тип интерфейса tap и в качестве второго параметра --ifconfig задается маска подсети. К слову сказать, на fbsd все делается абослютно так же, как на linux, за исключением того, что использование интерфейса tap потребует подгрузки необходимого модуля
kldload if_tap.ko либо пересборки ядра с соответствующей опцией.
Замечу также, что OpenVPN поддерживает транспорт посредством TCP, для этого предусмотрены режимы работы "tcp-server" и "tcp-client", которые задаются при помощи ключа --proto. Кроме этого, во второй версии программы предусмотрена возможность работы не только в режиме "p2p" (point-to-point - точка-точка), но и в режиме "server" (ключ --mode с соответствующим параметром), что позволяет одному процессу обслуживать несколько соединений. Для справки обо всех дополнительных возможностях советую обратиться к
man openvpn.
Шифрованный туннель с постоянным ключомПростейший способ защиты передаваемых по туннелю данных - использовать шифрование данных постоянным ключом. Для этого нужно сначала сгенерировать такой ключ на одном из хостов, затем скопировать его на другой. Сгенерировать ключ можно командой:
openvpn --genkey --secret static.key
на linux, или:
cd c:\Program Files\OpenVPN\bin
openvpn.exe --genkey --secret static.key
на win.
После того, как файл с ключом будет скопирован с одного хоста на другой (любым удобным способом, к примеру SMB, FTP или scp), можно создать на linux-боксе server.conf следующего содержания:
dev tun
ifconfig 10.0.0.1 10.0.0.2
secret /etc/openvpn/static.key
local 192.168.1.2
Здесь в поле "secret" указан путь к моему файлу с ключом, в поле "local" указан адрес локального интерфейса на который OpenVPN будет принимать соединения. Далее можно поместить созданный конфиг, скажем, в /etc/openvpn.
Теперь нужно создать соответствующий конфиг для клиента и сохранить его, к примеру, в c:\Program Files\OpenVPN\client.conf:
dev tun
ifconfig 10.0.0.2 10.0.0.1
secret "c:\Program Files\OpenVPN\static.key"
remote 192.168.1.2
Теперь можно на обоих машинах запустить OpenVPN, указав на соответствующий конфиг:
openvpn /etc/openvpn/server.conf
на linux, и
cd c:\Program Files\OpenVPN\bin
openvpn.exe ..\client.conf
на win.
Естественно, шифрование постоянным ключом не дает гарантий безопасности, поскольку перехватив определенный объем шифрованных пакетов, можно вычислить ключ, которым осуществлялось шифрование и расшифровать как ранее переданные пакеты, так и все последующие. О способах повысить степень защиты речь пойдет далее.
Использование сертификатовСертификаты предоставляют инструмент для обмена открытыми ключами, необходимыми для шифрования по асимметричному алгоритму RSA и привязки ключа к конкретному пользователю. Подлинность сертификатов подтверждается центром сертификации (CA - Certificate Authority). Устанавливая сроки действия сертификата и используя списки отозванных сертификатов можно контролировать доступ пользователей к ресурсам VPN. Чтобы воспользоваться инфраструктурой открытых ключей (PKI - Public Key Infrastructure), необходимо предпринять следующие шаги - создать собственный центр сертификации, сгенерировать сертификат сервера и пользовательские сертификаты. Проще всего это сделать с помощью скриптов, поставляемых в комплекте с OpenVPN. Рассмотрим процесс создания и использования PKI на примере следующей конфигурации:

В общем случае, конечно же, хосты не обязаны находиться в одной подсети, именно такие адреса были выбраны чисто для удобства описания. Я не случайно заменил хост linux на хост fbsd. Дело в том, что поставляемые в примерах скрипты у меня прекрасно заработали на linux, но потребовали хирургического вмешательства на fbsd.
Чтобы создать собственный CA на fbsd нужно для начала скопировать содержимое папки /usr/local/share/doc/openvpn/easy-rsa/2.0/ куда-нибудь вроде /usr/local/etc/openvpn/easy-rsa.
mkdir /usr/local/etc/openvpn
cp -R /usr/local/share/doc/openvpn/easy-rsa /usr/local/etc/openvpn/
cd /usr/local/etc/openvpn/easy-rsa/2.0/
После этого проверить с помощью
ls -la кому принадлежат все файлы в данной папке и установлены ли для них разрешения на исполнение. У меня по-умолчанию все файлы имели только разрешение на чтение. Если первое не так важно, поскольку действовать я все равно буду от рута, то без второго скрипты просто не исполнятся. Поэтому:
chmod -R 744 /usr/local/etc/openvpn/easy-rsa/2.0/*
Затем нужно отредактировать файлик vars с переменными, к которым обращаются скрипты, не оставляя пропусков (чтобы не присваивать параметру никаких значений, нужно вписать NA). В моем случае он выглядел так:
export EASY_RSA="`pwd`"
export KEY_CONFIG="$EASY_RSA/openssl.cnf"
export KEY_DIR="$EASY_RSA/keys"
export KEY_SIZE=1024
export CA_EXPIRE=365
export KEY_EXPIRE=365
export KEY_COUNTRY="UA"
export KEY_PROVINCE=NA
export KEY_CITY="KYIV"
export KEY_ORG=NA
export KEY_EMAIL="eugene@freebsd.mydomain"
Как легко догадаться, здесь указаны длина ключа, сроки действия сертификатов (CA и пользователей) в днях и данные о местоположении и принадлежности CA.
Далее нужно выполнить следующую последовательность команд из директории /usr/local/etc/openvpn/easy-rsa/2.0/
. ./vars
./clean-all
./build-ca
Здесь еще пара ньюансов. Во-первых, после первой точки в первой команде нужно поставить пробел. Во-вторых из-за того, что bash у меня лежал не там где в линуксе (/bin/bash), пришлось сделать символьный линк:
ln -s /usr/local/bin/bash /bin/bash
В процессе исполнения последнего скрипта нужно ответить на пару вопросов, я отвечал следующим образом:
Country Name (2 letter code) [UA]:
State or Province Name (full name) [NA]:
Locality Name (eg, city) [KYIV]:
Organization Name (eg, company) [NA]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) [NA CA]:freebsd
Email Address [admin@freebsd.mydomain]:
Теперь можно сгенерировать сертификат сервера (имя моего сервера "freebsd"):
./build-key-server freebsd
Отвечая на вопросы нужно не забыть указать пароль (я установил "secret") и утвердительно ответить на вопросы "Sign the certificate?" и "1 out of 1 certificate requests certified, commit?".
Следующий шаг - аналогичным образом сгенерировать сертификаты пользователей (в данном примере один пользователь - win):
./build-key win
Тут замечу, что секретные ключи клиента и сервера в общем случае могут отличаться, поэтому, создавая пользовательский ключ можно указать пароль к примеру, "notasecret". Если нужно защитить пользовательский сертификат паролем:
./build-key-pass win
В этом случае пользователю будет предлагаться ввести пароль каждый раз при установлении соединения. Теперь необходимо установить параметры механизма согласования ключей (алгоритм Диффи-Хэллмана):
./build-dh
И наконец, генерируется постоянный ключ TLS_AUTH, необходимый серверу и клиенту на начальном этапе установления соединения:
cd keys
openvpn --genkey ---secret ta.key
После этого можно проверить содержимое директории keys (
ls -la keys):
-rw-r--r-- 1 root wheel 3799 May 21 17:42 01.pem
-rw-r--r-- 1 root wheel 3473 May 21 17:44 02.pem
-rw-r--r-- 1 root wheel 1172 May 21 17:40 ca.crt
-rw------- 1 root wheel 887 May 21 17:40 ca.key
-rw-r--r-- 1 root wheel 245 May 21 17:46 dh1024.pem
-rw-r--r-- 1 root wheel 3799 May 21 17:42 freebsd.crt
-rw-r--r-- 1 root wheel 729 May 21 17:42 freebsd.csr
-rw------- 1 root wheel 887 May 21 17:42 freebsd.key
-rw-r--r-- 1 root wheel 196 May 21 17:44 index.txt
-rw-r--r-- 1 root wheel 20 May 21 17:44 index.txt.attr
-rw-r--r-- 1 root wheel 21 May 21 17:42 index.txt.attr.old
-rw-r--r-- 1 root wheel 100 May 21 17:42 index.txt.old
-rw-r--r-- 1 root wheel 3 May 21 17:44 serial
-rw-r--r-- 1 root wheel 3 May 21 17:42 serial.old
-rw------- 1 root wheel 636 May 21 17:47 ta.key
-rw-r--r-- 1 root wheel 3473 May 21 17:44 win.crt
-rw-r--r-- 1 root wheel 725 May 21 17:44 win.csr
-rw------- 1 root wheel 887 May 21 17:44 win.key
По соображениям безопасности, директорию /usr/local/etc/openvpn/easy-rsa/2.0/ лучше прибрать куда-нибудь подальше от посторонних глаз, а вместо нее создать в /usr/local/etc/openvpn/ директорию keys, в которую скопировать ca.crt, dh1024.pem, ta.key, freebsd.crt, freebsd.key. На клиентскую машину нужно скопировать win.crt, win.key, ca.crt, ta.key. Файлы .key содержат секретный ключ и не должны копироваться на другие машины. Файлы .crt содержат сертификаты с данными пользователя и его открытым ключом, сертификат можно открыто передавать по сети.
Простейший пример конфига server.conf на fbsd с использованием сертификатов для рассматриваемого примера:
dev tun
local 192.168.0.2
ifconfig 10.0.0.1 10.0.0.2
ca /usr/local/etc/openvpn/keys/ca.crt
cert /usr/local/etc/openvpn/keys/freebsd.crt
key /usr/local/etc/openvpn/keys/freebsd.key
dh /usr/local/etc/openvpn/keys/dh1024.pem
tls-auth /usr/local/etc/openvpn/keys/ta.key
tls-server
Соответственно, client.conf на win:
dev tun
remote 192.168.0.2
ifconfig 10.0.0.2 10.0.0.1
ca "C:\Program Files\OpenVPN\keysca.crt"
cert "C:\Program Files\OpenVPN\keyswin.crt"
key "C:\Program Files\OpenVPN\keyswin.key"
tls-auth "C:\Program Files\OpenVPN\keysta.key"
tls-client
Поднимается VPN как и прежде:
openvpn /usr/local/etc/openvpn/server.conf
на fbsd, и
cd c:\Program Files\OpenVPN\bin
openvpn.exe ..\client.conf
на win.
Конфигурация с одним сервером и несколькими клиентами
Если не ошибусь, теоретический лимит клиентов составляет 128, однако, проверить это на практике лично у меня не было возможности. Итак, к делу. По описанной выше процедуре необходимо сгенерировать ключи и сертификаты для клиентов и сервера, после чего скопировать ключи и сертификаты на клиентские хосты.
Затем нужно создать файлы конфигурации на каждом из хостов. Для примера такие:
#server.conf
local 192.168.0.2
dev tun
daemon
server 10.0.0.0 255.255.255.0
max-cliens 5
ca /usr/local/etc/openvpn/keys/ca.crt
cert /usr/local/etc/openvpn/keys/freebsd.crt
key /usr/local/etc/openvpn/keys/freebsd.key
dh /usr/local/etc/openvpn/keys/dh1024.pem
tls-auth /usr/local/etc/openvpn/keys/ta.key
tls-server
keepalive 10 120
log-append /var/log/openvpn.log
#winclient.conf
client
pull
dev tun
remote 192.168.0.2
ca "C:\Program Files\OpenVPN\keysca.crt"
cert "C:\Program Files\OpenVPN\keyswin.crt"
key "C:\Program FilesOpen\VPN\keyswin.key"
tls-auth "C:\Program Files\OpenVPN\keysta.key"
tls-client
tls-remote freebsd
#linuxclient.conf
client
pull
dev tun
remote 192.168.0.2
ca /etc/openvpn/keys/ca.crt
cert /etc/openvpn/keys/linux.crt
key /etc/openvpn/keys/linux.key
tls-auth /etc/openvpn/keys/ta.key
tls-client
tls-remote freebsd
Теперь можно запустить OpenVPN на всех хостах:
openvpn /usr/local/etc/openvpn/server.conf
на fbsd
cd c:\Program Files\OpenVPN
bin\openvpn.exe winclient.conf
на win
openvpn /etc/openvpn/linuxclient.conf
на linux.
Автозагрузка OpenVPNДля автозагрузки созданной в предыдущем примере конфигурации, нужно добавить в /etc/rc.conf на fbsd строки:
openvpn_enable="YES"
openvpn_configfile="/usr/local/etc/openvpn/server.conf"
В линуксе нужно отредактировать следуюющую строку в /etc/init.d/openvpn, чтобы указать местоположение конфига:
confidr=/etc/openvpn
После этого нужно создать символьный линк:
ln -s /etc/init.d/openvpn /etc/init.d/rc3.d/S20openvpn
или добавить автозагрузку OpenVPN на 3-м ранлевеле в Yast.
Отзыв сертификатаВ случае, когда какого-либо клиента нужно лишить возможности подключения к VPN, можно отозвать его сертификат. Для этого нужно воспользоваться скриптами из easy-rsa. Например, для клиента win:
./vars
./revoke-full win
После чего скопировать вновь созданный (в директории keys) список отозванных сертификатов crl.pem куда-нибудь в /usr/local/etc/openvpn и указать на него в конфиге server.conf строкой:
crl-verify /usr/local/etc/openvpn/crl.pem
Что можно еще почитатьОбязательно советую ознакомиться с man openvpn, кроме этого рекомендую книгу "Linux Networking Cookbook" издательства O'Reilly, а также "Openvpn: Building And Integrating Virtual Private Networks" от PACKT Publishing.