Конспект по установке 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 (без файла или с нулевым файлом сервер вообще не будет никого авторизовать):

#./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 tun       # 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"

Про дополнительную авторизацию.

В прилагаемых примерах предлагается использовать 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


Назад в оглавление



[Home] [TTL] [Unix] [Sdictionary] [ROW Programmer] [Symbian] [Misc] [News] [Search] [Contacts] [Guestbook]


Copyright (c) 1999-2017 Alexey Semenoff