Конспект по установке OpenVPN
Intro
В качестве VPN я долгое время использовал PPP over SSH.
Для одного-двух человек все работало и работает просто отлично (да и
настраивается все из подручных материалов за 10 минут).
Но когда мне понадобилось VPN решение для 10+ человек, к тому же
работающих на Linux/Win, то пришлось поискать что-то другое.
Действительно, CIPE,
которым я пользовался для соединения офисов требует отдельного порта
для каждого туннеля, работает не очень надежно (модуль ядра падает при
сканировании UDP портов), к тому же нужно допиливать исходники для
сборки под новые Linux kernel 2.6.
IPSec всем хорош, но клиенты часто несовместимы между
собой, а настройка под Win очень нетривиальна. Да и часто бывает, что несколько разных клиентов не
уживаются вместе на одной машине.
Порывшись в
сети и поспрашивая знакомых, решил прикрутить OpenVPN.
Плюсы OpenVPN:
- Open Source
- Поддержка множественных клиентов через один порт
- Поддержка разных осей и несложная настройка
- Продуманная многоуровневая система авторизации
Книги, рекомендованые на сайте OpenVPN содержат информацию в
разбросанном виде, ровно как и FAQ/HOWTO, именно поэтому я и написал
этот конспект.
Сборка
Как обычно все из
исходников. Забираем отсюда.
Для сборки потребуется библиотека LZO,
живет здесь.
Все стандартно и прямолинейно, т.е. ./configure && make && make
install (не забыть сказать ldconfig после сборки библиотеки) сначала
LZO, а потом и OpenVPN.
Настройка
Отдельно настраивается клиент и сервер.
OpenVPN работает через TUN/TAP драйвер. В Win все устанавливается
автоматом, для Linux нужно включить поддержку TUN/TAP в ядре (штатное
ядро скорее всего уже собрано как надо):
# modprobe tun
Для старых дистрибутивов без udev/devfs нужно сделать файл устройства:
# mkdir /dev/net
# mknod /dev/net/tun c 10 200
И сервер и клиент используют одни и те же бинари.
Настройка сервера (Unix)
Хотя OpenVPN может авторизовать юзверей только по login/pass, я
рекомендую использовать многоуровневую схему:
- подпись пакетов [HMAC]
- авторизация клиента/сервера сертификатами
- дополнительная авторизация по username/pass
- запуск с возможностью отзыва сертификата клиента
В исходниках есть все необходимые скрипты для работы с сертификатами,
копируем все (у меня все скрипты живут в /usr/local/scripts):
# cp /untarred/sources/openvpn-2.1.1/easy-rsa/2.0 /usr/local/scripts/easy-rsa
Для большей безопасности лучше хранить все связанное с
сертификатами на другой машине.
Далее
cd /usr/local/scripts/easy-rsa
Имеет смысл отредактировать файл vars и изменить параметры для
генерации сертификатов (KEY_EXPIRE, KEY_COUNTRY etc).
Генерим CA:
# . ./vars
NOTE: If you run ./clean-all, I will be doing a rm -rf on /usr/local/scripts/easy-rsa/keys
# ./clean-all
#./build-ca
Using configuration from /usr/local/scripts/easy-rsa/openssl-0.9.6.cnf
Generating a 1024 bit RSA private key
............++++++
....++++++
writing new private key to 'ca.key'
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [US]:
... bla-bla-bla
Теперь делаем сертификат и ключ для сервера
# ./build-key-server server
Using configuration from /usr/local/scripts/easy-rsa/openssl-0.9.6.cnf
Generating a 1024 bit RSA private key
...................................++++++
..............++++++
writing new private key to 'server.key'
You are about to be asked to enter information that will be incorporated
into your certificate request.
... bla-bla-bla
Certificate is to be certified until Jan 16 07:14:28 2020 GMT (3650 days)
Sign the certificate? [y/n]:Y
1 out of 1 certificate requests certified, commit? [y/n]Y
Write out database with 1 new entries
Data Base Updated
Генерим как минимум два клиентских ключа, ключ client0 нужен только
для отзыва сертификата (об этом ниже), ключи client1, client2 etc -
для реальных пользователей:
# ./build-key client0 (и потом 1,2,3...)
Using configuration from /usr/local/scripts/easy-rsa/openssl-0.9.6.cnf
Generating a 1024 bit RSA private key
....++++++
...................++++++
writing new private key to 'client1.key'
You are about to be asked to enter information that will be incorporated
into your certificate request.
... bla-bla-bla ...
Certificate is to be certified until Jan 16 07:16:09 2020 GMT (3650 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
Для того, чтобы создать список отозванных сертификатов,
отзовем client0, просто для того, чтобы
создать непустой файл crl.pem (без файла или с нулевым файлом сервер
вообще не будет никого авторизовать):
UPD1:
Много воды утекло с момента написания статьи и теперь
(начиная с какой-то там версии) openvpn сервер проверяет дату до которой
действителен список отозванных сертификатов. По умолчанию это один
месяц со дня создания файла. Если список просрочен, то ни один клиент
не сможет законнектиться. Будьте вниметельны!
Если вы не планируете раз в месяц обновлять список отозванных
сертификатов, рекомендую в файл ./openssl.cnf внести правку:
default_crl_days = 3650
И теперь уже сделать:
#./revoke-full client0
Затем делаем файл с Diffie Hellman parameters:
# ./build-dh
warning, not much extra random data, consider using the -rand option
Generating DH parameters, 1024 bit long safe prime, generator 2
This is going to take a long time
....................................
....................................
++*++*++*
и ключик для HMAC
# openvpn --genkey --secret keys/ta.key
На сервере создаем каталог для сертификатов и конфигурации
# mkdir /etc/openvpn
И из каталога /usr/local/scripts/easy-rsa/keys (машина, на которой
делали сертификаты) копируем на сервер в /etc/openvpn следующие файлы:
ca.crt
ca.key
dh1024.pem
server.crt
server.csr
server.key
ta.key
crl.pem
Создаем файл конфигурации для сервера, /etc/openvpn/server.conf:
port 26111 # лучше использовать нестандартный порт
proto udp # или TCP
dev tun0 # tun - для IP routing
# то, что нагенерили
ca ca.crt
cert server.crt
key server.key
dh dh1024.pem
tls-auth ta.key 0
# отозванные сертификаты, полный путь к файлу!
crl-verify /etc/openvpn/crl.pem
server 10.48.9.0 255.255.255.0
#daemon # после успешного запуска нужно раскомментировать
writepid /var/lock/subsys/openvpn.pid
ifconfig-pool-persist /var/tmp/ipp.txt
push "route 10.0.0.0 255.255.255.0" # все IP сетки ЗА сервером, в
;push "route ... " # которые будем ходить
keepalive 10 120
comp-lzo
user nobody
group nobody # nogroup для Debian!
persist-key
persist-tun
status /var/tmp/openvpn-status.log
verb 3
script-security 3
# дополнительно авторизуем по login/pass
auth-user-pass-verify /etc/openvpn/auth-htaccess-file.plx via-env
# полезно для Win клиентов
;push "domain-name-servers x.x.x.x"
;push "dhcp-option DOMAIN mydomain.net"
;push "dhcp-option DNS 10.0.0.1"
UPD2:
Иногда бывает нужно пробросить какие-то сетки в сторону
клиента. Делается это через ccd примерно так:
/etc/openvpn/server.conf:
...
client-config-dir /etc/openvpn/ccd
и, например, для клиента, имеющего сертификат client1 пишем в /etc/openvpn/ccd
...
iroute 192.168.0.0 255.255.255.0
Но этого недостаточно, сам openvpn теперь завернет сетку нужному
клиенту, но система абсолютно ничего не знает куда пересылать пакеты
адресованные этой сетке.
Решения вопроса два. Первый это поднять tun0 ДО запуска openvpn и
завернуть сетку туда, в rc.local или где там оно у вас добавляем перед
запуском openvpn:
/sbin/ip tuntap add dev tun0 mode tun
/sbin/ifconfig tun0 up
/sbin/route add -net 192.168.0.0 netmask 255.255.255.0 tun0
Теперь система знает куда отсылать пакеты для 192.168.0.0/24.
Другой вариант использовать up.sh скрипт, добавляем в /etc/openvpn/server.conf:
...
up /etc/openvpn/up.sh
И сам /etc/openvpn/up.sh:
/sbin/ip route add 192.168.0.0/24 via $4
Теперь после запуска openvpn система опять же будет знать про 192.168.0.0/24
Про дополнительную авторизацию.
В прилагаемых примерах предлагается использовать PAM, MySQL или
LDAP. Поскольку все мои пользователи уже имеют доступ на запароленный
Squid, удобнее оказалось использовать те же учетные данные.
Я сочинил простенький скрипт /etc/openvpn/auth-htaccess-file.plx:
#!/usr/local/bin/perl
use strict;
use IPC::Open2;
use IO::Handle;
# штатная Squid'овская авторизовалка
my $ncsa_auth = '/usr/local/squid/bin/ncsa_auth';
# база пользователей
my $users_file = '/etc/squid/users';
my $pass = $ENV{password}; $ENV{password}= q{};
my $user = $ENV{username}; $ENV{username}= q{};
my ($reader, $writer) = (IO::Handle->new, IO::Handle->new);
open2($reader, $writer, "$ncsa_auth $users_file" ) or die;
print $writer "$user $pass\n";
my $output = <$reader>;
close $reader;
close $writer;
chomp ($output);
exit 0 if ($output eq 'OK');
exit 1;
Он просто скармливает username/passwd ncsa_auth'у точно также, как и сам Squid и если
ncsa_auth отвечает 'OK', пускаем юзверя.
Пробуем запустить сервер (не забываем modprobe tun!):
# cd /etc/openvpn
# openvpn ./server.conf
Если все нормально, в консоле будет нечто типа
Mon Jan 18 09:38:26 2010 OpenVPN 2.1.1 i686-pc-linux-gnu [SSL] [LZO2]
built on Jan 15 2010
Mon Jan 18 09:38:26 2010 Diffie-Hellman initialized with 1024 bit key
Mon Jan 18 09:38:26 2010 Control Channel Authentication: using
'ta.key' as a OpenVPN static key file
Mon Jan 18 09:38:26 2010 Outgoing Control Channel Authentication:
Using 160 bit message hash 'SHA1' for HMAC authentication
Mon Jan 18 09:38:26 2010 Incoming Control Channel Authentication:
Using 160 bit message hash 'SHA1' for HMAC authentication
Mon Jan 18 09:38:26 2010 TLS-Auth MTU parms [ L:1542 D:166 EF:66 EB:0 ET:0 EL:0 ]
Mon Jan 18 09:38:26 2010 ROUTE default_gateway=1.1.1.1
Mon Jan 18 09:38:26 2010 TUN/TAP device tun0 opened
Mon Jan 18 09:38:26 2010 TUN/TAP TX queue length set to 100
Mon Jan 18 09:38:26 2010 /sbin/ifconfig tun0 10.48.9.1 pointopoint 10.48.9.2 mtu 1500
Mon Jan 18 09:38:26 2010 /sbin/route add -net 10.48.9.0 netmask
255.255.255.0 gw 10.48.9.2
Mon Jan 18 09:38:26 2010 Data Channel MTU parms
[ L:1542 D:1450 EF:42 EB:135 ET:0 EL:0 AF:3/1 ]
Mon Jan 18 09:38:26 2010 GID set to nobody
Mon Jan 18 09:38:26 2010 UID set to nobody
Mon Jan 18 09:38:26 2010 Socket Buffers: R=[108544->131072] S=[108544->131072]
Mon Jan 18 09:38:26 2010 UDPv4 link local (bound): [undef]:26111
Mon Jan 18 09:38:26 2010 UDPv4 link remote: [undef]
Mon Jan 18 09:38:26 2010 MULTI: multi_init called, r=256 v=256
Mon Jan 18 09:38:26 2010 IFCONFIG POOL: base=10.48.9.4 size=62
Mon Jan 18 09:38:26 2010 IFCONFIG POOL LIST
Mon Jan 18 09:38:26 2010 Initialization Sequence Completed
Теперь можно откомментировать '#daemon' в /etc/openvpn/server.conf
Для автозапуска сервера удобно использовать что-то вроде /etc/init.d/openvpn:
#!/bin/sh
#
# Source function library.
. /etc/rc.d/init.d/functions
# See how we were called.
case "$1" in
start)
echo -n "Starting OpenVPN: "
cd /etc/openvpn
/usr/local/sbin/openvpn /etc/openvpn/server.conf
echo "openvpn"
;;
stop)
echo -n "Stopping OpenVPN: "
kill `cat /var/lock/subsys/openvpn.pid`
echo "openvpn"
;;
restart)
$0 stop
$0 start
;;
*)
echo "Usage: $0 {start|stop|restart|status}"
exit 1
esac
exit 0
В заключение про настройку firewall.
По умолчанию iptables блокирует
трафик со всех сетевых устройств, поэтому нужно разрешить это явно:
IPTABLES=/sbin/iptables
$IPTABLES -A INPUT -i tun+ -j ACCEPT
$IPTABLES -A OUTPUT -o tun+ -j ACCEPT
$IPTABLES -A INPUT -i tap+ -j ACCEPT
$IPTABLES -A OUTPUT -o tap+ -j ACCEPT
$IPTABLES -A FORWARD -i tun+ -j ACCEPT
$IPTABLES -A FORWARD -o tun+ -j ACCEPT
$IPTABLES -A FORWARD -i tap+ -j ACCEPT
$IPTABLES -A FORWARD -o tap+ -j ACCEPT
И конечно разрешить routing:
echo 1 > /proc/sys/net/ipv4/ip_forward
$IPTABLES -A FORWARD -i tun+ -j ACCEPT
$IPTABLES -A FORWARD -o tun+ -j ACCEPT
$IPTABLES -A FORWARD -i tap+ -j ACCEPT
$IPTABLES -A FORWARD -o tap+ -j ACCEPT
Настройка клиента (Unix)
Бинари используются те же самые и все файлы сертификатов и
конфигурации - в /etc/openvpn.
Копируем клиентские файлы:
ca.crt
ta.key
client1.crt
client1.csr
client1.key
Файл конфигурации для клиента, /etc/openvpn/client.conf:
client
# daemon # раскомментировать после отладки
dev tun
proto udp
remote my-vpn-mashine.domain.com 26111 # name или IP
resolv-retry infinite
nobind
persist-key
persist-tun
ca /etc/openvpn/ca.crt
cert /etc/openvpn/client1.crt
key /etc/openvpn/client1.key
tls-auth /etc/openvpn/ta.key 1
ns-cert-type server
comp-lzo
verb 3
auth-user-pass stdin # спросить login/pass при старте
Запускаем клиента:
# openvpn /etc/openvpn/client.conf
Mon Jan 18 09:56:59 2010 OpenVPN 2.1_rc11 i486-pc-linux-gnu
[SSL] [LZO2] [EPOLL] [PKCS11] built on Sep 18 2008
Enter Auth Username: fantomas
Enter Auth Password: xxxxxxxx
Mon Jan 18 09:57:04 2010 /usr/bin/openssl-vulnkey -q -b 1024 -m
Mon Jan 18 09:57:04 2010 Control Channel Authentication: using '/etc/openvpn/ta.key' as a OpenVPN stati
c key file
Mon Jan 18 09:57:04 2010 Outgoing Control Channel Authentication: Using 160 bit message hash 'SHA1' for
HMAC authentication
Mon Jan 18 09:57:04 2010 Incoming Control Channel Authentication: Using 160 bit message hash 'SHA1' for
HMAC authentication
Mon Jan 18 09:57:04 2010 LZO compression initialized
Mon Jan 18 09:57:04 2010 Control Channel MTU parms [ L:1542 D:166 EF:66 EB:0 ET:0 EL:0 ]
Mon Jan 18 09:57:04 2010 Data Channel MTU parms [ L:1542 D:1450 EF:42 EB:135 ET:0 EL:0 AF:3/1 ]
Mon Jan 18 09:57:04 2010 Local Options hash (VER=V4): '504e774e'
Mon Jan 18 09:57:04 2010 Expected Remote Options hash (VER=V4): '14168603'
Mon Jan 18 09:57:04 2010 Socket Buffers: R=[111616->131072] S=[111616->131072]
Mon Jan 18 09:57:04 2010 UDPv4 link local: [undef]
Mon Jan 18 09:57:04 2010 UDPv4 link remote: 195.1.1.1:26111
Mon Jan 18 09:57:04 2010 TLS: Initial packet from 195.1.1.1:26111, sid=9d859aed 85f320a8
Mon Jan 18 09:57:04 2010 WARNING: this configuration may cache passwords in memory -- use the auth-noca
che option to prevent this
Mon Jan 18 09:57:04 2010 VERIFY OK: depth=1, /C= ...
Mon Jan 18 09:57:04 2010 VERIFY OK: nsCertType=SERVER
Mon Jan 18 09:57:05 2010 Data Channel Encrypt: Cipher 'BF-CBC' initialized with 128 bit key
Mon Jan 18 09:57:05 2010 Data Channel Encrypt: Using 160 bit message hash 'SHA1' for HMAC authenticatio
n
Mon Jan 18 09:57:05 2010 Data Channel Decrypt: Cipher 'BF-CBC' initialized with 128 bit key
Mon Jan 18 09:57:05 2010 Data Channel Decrypt: Using 160 bit message hash 'SHA1' for HMAC authenticatio
Mon Jan 18 09:57:06 2010 TUN/TAP device tun0 opened
Mon Jan 18 09:57:06 2010 TUN/TAP TX queue length set to 100
Mon Jan 18 09:57:06 2010 Initialization Sequence Completed
Все работает!
Хочу обратить внимание на штатный скрипт запуска OpanVPN, который не
всегда корректно работает, например в Debian при сарте машины
запрашивается username/passwd и если они неверные, то процесс openvpn
продолжает работать, удерживая устройство tun0.
Настройка клиента (Win)
Ставим openvpn-2.1.1-install.exe. В версиию 2.1.1 входит удобный GUI.
В C:\Program Files\OpenVPN\config\ копируем файлы (в этом примере
client2 - винюки):
ca.crt
ta.key
client2.crt
client2.csr
client2.key
Там же создаем client.ovpn:
client
dev tun
proto udp
remote my-vpn-mashine.domain.com 26111
resolv-retry infinite
nobind
pull
persist-key
persist-tun
ca ca.crt
cert client1.crt
key client1.key
tls-auth ta.key 1
ns-cert-type server
comp-lzo
verb 3
auth-user-pass stdin
Запускаем GUI, потом правой кнопкой на трее, выбираем 'Connect'.
Вкратце все! Дополнения и уточнения принимаются.
Tags: linux vpn openvpn crypto
Назад в оглавление
|