Обсуждение статьи - http://forum.ubuntu.ru/index.php?topic=269925

Просьба к редакторам тоже там отписываться

thunderamur

OpenVPN

OpenVPN — свободная реализация технологии Виртуальной Частной Сети (VPN) с открытым исходным кодом для создания зашифрованных каналов типа точка-точка или сервер-клиенты между компьютерами. Она позволяет устанавливать соединения между компьютерами, находящимися за NAT-firewall, без необходимости изменения их настроек.

Варианты применения данной статьи

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

Исходные данные

Локальная сеть 1

192.168.1.0/24 192.168.1.1
Белый внешний IP (здесь будет сервер OpenVPN)
Внутренний IP сервера OpenVPN - 192.168.1.100

Локальная сеть 2

192.168.0.0/24 192.168.0.1
Динамический IP (или даже серый - не важно для клиента OpenVPN)
Внутренний IP клиента OpenVPN - 192.168.0.100. Клиент в данном случае будет являться шлюзом для устройств в своей подсети.

Настройка OpenVPN

Все действия проводятся с правами суперпользователя root.
sudo -i

Установка

И на сервере и на клиенте ставим один и тот же пакет.

apt-get install openvpn

Создание сервера

Создание ключей и сертификатов

Защита соединения в OpenVPN в данном случае строится на использовании сертификатов и ключей для сервера и для клиентов.

apt-get install easy-rsa
mkdir /etc/openvpn/easy-rsa
cp -r /usr/share/easy-rsa /etc/openvpn/easy-rsa/2.0

Переходим в созданную директорию, где и займёмся генерацией ключей и сертификатов

cd /etc/openvpn/easy-rsa/2.0

Редактируем файл переменных

nano vars

Здесь можно заполнить например так:

# Почти в самом низу файла, заполняем информацию о сертификатах по умолчанию (ваши значения).
export KEY_COUNTRY="RU"
export KEY_PROVINCE="Amur Region"
export KEY_CITY="Blagoveschensk"
export KEY_ORG="Organization"
export KEY_EMAIL="vash@email.tut"
export KEY_OU="MyOrganizationalUnit"
# PKCS11 я не использовал, поэтому оставил без изменений. Кто шарит нафига эта штука, допишите статью.
export PKCS11_MODULE_PATH=changeme
export PKCS11_PIN=1234

#Добавить
export KEY_ALTNAMES="VPNsRUS"

копируем конфиг openssl

cp openssl-1.0.0.cnf openssl.cnf

Загружаем переменные

source ./vars

Очищаем от старых сертификатов и ключей папку keys и создаем серийный и индексные файлы для новых ключей

./clean-all

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

./build-ca

Создаем ключ сервера

FIXME A challenge password []: Если вы решили ввести challenge password, то необходимо убедиться, что сохранили этот пароль в безопасном месте. Если вам понадобится когда-нибудь переустановить этот сертификат, то потребуется ввести этот пароль снова.
./build-key-server server

В конце соглашаемся с запросом на подпись и добавление сертификата в базу.

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

Создаем ключ Диффи-Хеллмана

./build-dh

Cоздаем ключ для tls-аутификации

openvpn --genkey --secret keys/ta.key

Перемещаем сертификаты

cp -r /etc/openvpn/easy-rsa/2.0/keys/ /etc/openvpn/

Создание файла конфигурации сервера

cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz /etc/openvpn/
cd /etc/openvpn
gunzip -d /etc/openvpn/server.conf.gz

nano /etc/openvpn/server.conf
port 1194
# Протокол может быть UDP или TCP, я выбрал 1-й вариант.
proto udp
# Если вы выберите протокол TCP, здесь должно быть устройство tap. Однако, это вариант я не проверял, поэтому ищите информацию отдельно. FIXME
dev tun

# Указываем где искать ключи
ca /etc/openvpn/keys/ca.crt
cert /etc/openvpn/keys/server.crt
key /etc/openvpn/keys/server.key  # This file should be kept secret
dh /etc/openvpn/keys/dh2048.pem
# Для 12.04 dh1024.pem

# Задаем IP и маску виртуальной сети. Произвольно, но если не уверены лучше делайте как показано здесь
server 10.8.0.0 255.255.255.0

# Указыем, где хранятся файлы с настройками IP-адресов клиентов (создадим ниже)
client-config-dir /etc/openvpn/ccd

# Запоминать динамически выданные адреса для VPN-клиентов и при последующих подключениях назначать те же значения.
ifconfig-pool-persist /etc/openvpn/ipp.txt

# Указываем сети, в которые нужно идти через туннель (сеть-клиента).
route 192.168.0.0 255.255.255.0

# Включаем TLS
tls-server
tls-auth /etc/openvpn/keys/ta.key 0
tls-timeout 120
auth SHA1
cipher AES-256-CBC

# Если нужно, чтобы клиенты видели друг друга раскомментируйте
;client-to-client

keepalive 10 120

# Сжатие трафика. Для отключения используйте на сервере и клиенте comp-lzo no
comp-lzo

# Максимум клиентов
max-clients 10

user nobody
group nogroup

# Не перечитывать ключи, не закрывать и переоткрывать TUN\TAP устройство, после получения SIGUSR1 или ping-restart
persist-key
persist-tun

status openvpn-status.log
log /var/log/openvpn.log
# Детальность логирования
verb 3
# Защита от повторов (максимум 20 одинаковых сообщений подряд)
mute 20

# Файл отозванных сертификатов. Разремить, когда такие сертификаты появятся.
;crl-verify /etc/openvpn/crl.pem

Создадим директорию для клиентских конфигов

mkdir /etc/openvpn/ccd

Можно запускать наш сервер OpenVPN

service openvpn restart

Смотрим список интерфейсов

ifconfig

Если среди прочих видим

tun0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
          inet addr:10.8.0.1  P-t-P:10.8.0.2  Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

значит VPN-сервер завелся. Если нет, то смотрим лог

tail -f /var/log/openvpn.log

Настройка маршрутизации на стороне сервера

Если сервер имеет «белый» IP то никакой маршрутизации на стороне сервера настраивать не нужно. Если сервер находится в локальной сети за NAT роутера то необходимо настроить маршрутизацию.
Для того, чтобы клиенты могли достучаться до сервера нужно пробросить порты с роутера на сервер. В разных моделях это делается по разному. Суть в том, чтобы стучась на внешний порт, например 12345 1), клиенты попадали на порт OpenVPN-сервера 1194 (или другой, который мы задали для нашего сервера). Кроме того устройствам в локальной сети нужно сообщить, что для доступа к сети за OpenVPN-сервером нужно обращаться к нему. Но проще задать этот маршрут на роутере, который обслуживает локалку.

Создаем файл в каталоге ccd с тем же именем, что и ключ для клиента, т.е. /etc/openvpn/ccd/client

# Маршрут в сеть клиента. Требуется для доступа к сетевым устройствам в сети клиента. Если не требуется - не прописывайте.
iroute 192.168.0.0 255.255.255.0

# Задаем маршрут для клиента, чтобы он видел сеть за OpenVPN-сервером.
# Если маршрут требуется для всех подключаемых клиентов, достаточно эту
# строку прописать в конфигурационный файл сервера server.conf 
push "route 192.168.1.0 255.255.255.0"

Включаем ipv4_forwarding

В /etc/sysctl.conf расскомментируем #net.ipv4.ip_forward=1 после чего

sysctl -p

Создание клиента

Создание ключей и сертификатов

Ключи клиента создаются на сервере

Переходим в созданную директорию, где и замёмся генерацией ключей и сертификатов

cd /etc/openvpn/easy-rsa/2.0

Загружаем переменные

source vars

Создаем ключ клиента

В данном случае название ключа - client. Каждый ключ должен быть со своим именем.
./build-key client

Если хотим защитить ключ паролем, то генерируем его другой командой

./build-key-pass client

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

Теперь нужно не забыть скопировать ключи (ca.crt, client.crt, client.key, ta.key) на клиента OpenVPN в /etc/openvpn/keys/
Если планируется на клиенте импортировать файл настроек .ovpn вместе с сертификатами и ключами, например, для Android, важно в конфигурации клиента исключить строку tls-auth, вместо нее добавить key-direction 1. В противном случае будет ошибка вида tls error: incoming packet authentication failed from [af_inet].

Создание файла конфигурации клиента

/etc/openvpn/client.conf

client
dev tun
proto udp

# Внеший IP, на или за которым находится ваш сервер OpenVPN и порт (на сервере или роутере, за которым стоит сервер)
remote 111.222.333.444 1194

# необходимо для DynDNS
resolv-retry infinite

ca /etc/openvpn/keys/ca.crt
cert /etc/openvpn/keys/client.crt
key /etc/openvpn/keys/client.key
tls-client
tls-auth /etc/openvpn/keys/ta.key 1
auth SHA1
cipher AES-256-CBC
remote-cert-tls server
comp-lzo
persist-key
persist-tun

status openvpn-status.log
log /var/log/openvpn.log
verb 3
mute 20

ИЛИ единый файл конфигурации клиента client.ovpn с сертификатами и ключами для импорта

client
dev tun
proto udp

# Внеший IP, на или за которым находится ваш сервер OpenVPN и порт (на сервере или роутере, за которым стоит сервер)
remote 111.222.333.444 1194

# необходимо для DynDNS
resolv-retry infinite

tls-client

# Строка tls-auth /etc/openvpn/keys/ta.key 1, как выше говорилось, заменяется на 
key-direction 1

auth SHA1
cipher AES-256-CBC
remote-cert-tls server
comp-lzo
persist-key
persist-tun

verb 3
mute 20

# Далее идут сертификаты и ключи которые берутся из соответствующих файлов сгенерированных выше

# Из ca.crt
<ca>
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
</ca>

# Из client.crt
<cert>
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
</cert>

# Из client.key
<key>
-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----
</key>

# Из ta.key
<tls-auth>
-----BEGIN OpenVPN Static key V1-----
...
-----END OpenVPN Static key V1-----
</tls-auth>

Можно запускать наш клиент OpenVPN

service openvpn restart

Настройка маршрутизации на стороне клиента

Машина с openvpn уже готова работать с сервером в чём можно убедится

ping -c 2 10.8.0.1
ping -c 2 192.168.1.100

Но для того, чтобы пользоваться туннелем в другой офис могли другие устройства в локальной сети нужно указать им, чтобы доступ в подсеть 192.168.1.0/24 осуществляется через 192.168.0.100. Или, что часто проще и быстрее прописать это правило маршрутизации на роутере, который является шлюзом для устройств в сети.

Включаем ipv4_forwarding

Также как в случае с сервером.

Настройка выхода в интернет с IP сервера

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

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

Если же вы хотите организовать доступ из VPN сети в интернет с IP адреса сервера, то вам нужно настроить на сервере NAT. Сделать это можно следующей командой (на сервере):

iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE

Здесь мы указали, что сеть 10.8.0.0/24 будет выходить наружу через интерфейс eth0.

Для того что бы настройки iptables сохранились после перезагрузки нужно их дополнительно сохранить:

iptables-save > /etc/iptables.up.rules
echo "pre-up iptables-restore < /etc/iptables.up.rules" >> /etc/network/interfaces

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

К конфиге клиента client.conf нужно добавить строчку

redirect-gateway def1

Отзыв сертификата

cd /etc/openvpn/easy-rsa/2.0
. ./vars
./revoke-full client2

Если все прошло штатно вы должны увидеть следующий вывод, сообщающий о том, что сертификат отозван:

error 23 at 0 depth lookup:certificate revoked

Скрипт revoke-full создаст CRL-файл (certificate revocation list, список отозванных сертификатов) с именем crl.pem в подкаталоге keys. Файл должен быть скопирован в каталог, в котором сервер OpenVPN может получить к нему доступ. Ранее в конфиге мы прописали, что этот файл должен находится в /etc/openvpn, туда и копируем.

Отключение автозапуска OpenVPN

Это бывает полезно, например для клиента с ключем защищенным паролем, т.к. всё равно при старте системы такое соединение не поднимется в виду отсутствия пароля для ключа. Да и в том случае, если вы сделали ключ с паролем, значит, скорее всего, вам не нужно постоянное соединение.
nano /etc/default/openvpn

Раскомментируем строчку

AUTOSTART="none"

Тест производительности OpenVPN

Условия теста:

  1. VPN-сервер на ВМ Virtualbox (1 ядро i5-4670)
  2. Сеть гигабит (без шифрования последовательная скорость передачи 120 МБ/с). Скорость буду указывать в мегабайтах, НЕ в мегабитах!
  3. Форвардинг на хоста
  4. Клиент Windows 7, OpenVPN 2.3 64, FX-6300

Результаты:

  1. Скорость всегда упиралась в ВМ, где процессор бы полностью занят. ЦП клиента был загружен не более 10% - 40% на 1/6 ядер.
  2. С конфигом выше - 14 МБ/с
  3. Отключаем сжатие ;comp-lzo - прибавка не более 1 МБ/с - до 15 МБ/с
  4. Отключаем аутентификацию auth none +2 МБ/с - до 17 МБ/с
  5. Отключаем шифрование cipher none +2 МБ/с - до 19 МБ/с
  6. Сжатие comp-lzo сжимает хорошо сжимаемые файлы в 2 раза хуже, чем zlib, зато почти не влияет не загрузку ЦП (в десятки раз быстрее). Проверял на копировании установленного в Windows Libreoffice 5. Сжатие в zip с помощью архиватора 7z дало результат около 35%, сжатие comp-lzo по статистике сетевого интерфейса - около 70%.

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

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

Источники

1)
может совпадать со внутренним, но в целях защиты лучше левый из 5-значной группы