Сервер в кармане, или просто о сложном!

главная - Статьи - Удаленный доступ (VPN)

Настройка OpenVPN

Теги: OpenVPN VPN VPN сервер

Нам надо соединить удаленного сотрудника к рабочей сети. Это делается в том числе с помощью VPN, в нашем случае, OpenVPN. Это бесплатный, достаточно надежный и не очень сложный в настройке сервер и клиент VPN.

Структура нашей сети такая:

  • Сеть: 192.168.10.0/24
  • IP-адрес внешнего интерфейса сервера OpenVPN: 444.333.222.111
  • Порт, на котором "висит" OpenVPN: 1194 udp (стандартный для OpenVPN)
  • IP-адрес DNS внутренней сети: 192.168.10.100
  • Сеть VPN: 10.8.0.0/24 (стандартная для OpenVPN)
  • Удаленный сотрудник без определенного адреса

Настройка OpenVPN

Начальная установка простая для любой популярной операционной системы:

  • CentOS: yum install openvpn (правда, это я немного лукавлю насчет просто, читайте ниже)
  • FreeBSD: cd /usr/ports/security/openvpn -> make -> make install
  • Windows: ну тут уж все специалисты!

Пожалуй, не скажу ничего про Mac OS, т.к. не сталкивался лично.

Установка OpenVPN в Linux

Я использую CentOS, поэтому могу описать установку именно для этого Linux.

Как и везде, скачать пакет и установить не есть гуд, т.к. его будет труднее обновлять. А т.к. "yum install openvpn" выдаст фиг, надо нам подключить репозиторий.

Вариант 1 - попробовать поставить репозиторий с самого openvpn.net:

# cd /etc/yum.repos.d
# wget http://repos.openvpn.net/repos/yum/conf/repos.openvpn.net-CentOS6-snapshots.repo
# yum install openvpn

Эти команды см. в файле http://repos.openvpn.net/repos/yum/conf/repos.openvpn.net-CentOS6-snapshots.txt.

Скоре всего, это у вас не прокатит :)

Вариант 2 - репозиторий RPMForge

Для i386:

# rpm  -Uhv http://apt.sw.be/redhat/el5/en/i386/rpmforge/RPMS/rpmforge-release-0.5.1-1.el5.rf.i386.rpm

Для x86_64:

# rpm  -Uhv http://apt.sw.be/redhat/el5/en/x86_64/rpmforge/RPMS/rpmforge-release-0.5.1-1.el5.rf.x86_64.rpm

Установка ключа

# rpm –import http://dag.wieers.com/rpm/packages/RPM-GPG-KEY.dag.txt

Проверим, чего наставили:

# yum repolist

Особо не увлекайтесь всякими репозиториями :) Чем меньше их, тем лучше.

Вариант 3 - сложные случаи - попробуйте посмотреть http://pkgs.org/search/?keyword=openvpn.

Итак, чтобы вы ни делали, вы должны успешно выполнить команду:

# yum install openvpn

Installed:
  openvpn.i386 0:2.3-3

Dependency Installed:
  pkcs11-helper.i686 0:1.08-1.el6.rf

Complete!

Первичная настройка OpenVPN

Независимо от того, на FreeBSD, Linux или Windows, общие шаги по созданию необходимой инфраструктуры для OpenVPN практически одинаковы.

Копируем файл конфигурации:

# cp /usr/share/doc/openvpn-*/sample-config-files/server.conf /etc/openvpn/

Копируем пакет управления RSA ключами из поставки OpenVPN в /etc/openvpn/easy-rsa:

# cp /usr/share/doc/openvpn-*/easy-rsa/2.0/ /etc/openvpn/
# cd /etc/openvpn/easy-rsa
# cp openssl-1.0.0.cnf openssl.cnf
# mkdir keys

Редактируем файл /etc/openvpn/rsa-keys/vars:

export KEY_COUNTRY="RU"
export KEY_PROVINCE="RU"
export KEY_CITY="Moscow"
export KEY_ORG="Company"
export KEY_EMAIL="abuse@company-domain.com"
export KEY_EMAIL=abuse@company-domain.com
export KEY_CN=changeme
export KEY_NAME=changeme
export KEY_OU=Office
export PKCS11_MODULE_PATH=changeme
export PKCS11_PIN=1234

Далее следует экспортировать переменные KEY_*, они необходимы для работы скриптов build-*, генерирующих сертификаты. На этом шаге могу отметить, что у меня не сразу получилось экспортировать переменные из файла /etc/openvpn/easy-rsa/keys, пришлось делать скрипт с экспортом системной переменной $PATH, но, как мне кажется, это чисто у меня такая проблема была (в Windows-версии C:Program FilesOpenVPNeasy-rsavars.bat переменные экспортировались без проблем):

# cd /etc/openvpn/easy-rsa
# ./vars

Дополнение: прочел следующее на http://www.lissyara.su/?id=1549: Внимание! Если у вас по умолчанию не баш, то перед следующими операциями нужно набрать в консоли "sh", советую для "100-%-ного" результата всё же наверняка сделайте это, даже если у вас шелл sh. Загружаем переменные в оболочку (для выхода из режима sh ввести exit):
# cd /etc/openvpn/easy-rsa
# sh
# . ./vars

В Windows откройте командную строку "cmd":

cd "C:Program FilesOpenVPNeasy-rsa
vars.bat

Отмечу на всякий случай, что если вы не можете выполнить какой-либо скрипт, вероятнее всего у него просто нет прав на запуск, например, при запуске ./build-ca я сначала получил такое сообщение:

  Please edit the vars script to reflect your configuration,
  then source it with "source ./vars".
  Next, to start with a fresh PKI configuration and to delete any
  previous certificates and keys, run "./clean-all".
  Finally, you can run this tool (pkitool) to build certificates/keys.

 
О чем это? А просто-напросто переменные из файла vars не экпортировались, т.к. vars не выполнился, т.к. ему нужны права на запуск, т.е. "chmod +x vars". Мне пришлось дать права на запуск нескольким файлам, в том числе:
build-ca, clean-all, pkitool, vars, whichopensslcnf.

Удаляем все предыдущие файлы ключей и сертифкатов из директории /etc/openvpn/easy-rsa/keys (эта директория указана в переменной KEY_DIR файла vars):

# chmod +x clean-all
# ./clean-all

Создаем сертификат подлинности (Certificate Authority) сервера:

# chmod +x build-ca
# chmod +x pkitool
# ./build-ca

.++++++
........................................++++++
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) [RU]:
State or Province Name (full name) [RU]:
Locality Name (eg, city) [Moscow]:
Organization Name (eg, company) [Company]:
Organizational Unit Name (eg, section) [Office]:
Common Name (eg, your name or your server's hostname) [changeme]:VPNServer
Name [changeme]:Name
Email Address [abuse@company-domain.com]:

Ок, мы вроде бы все сделали.

Будьте внимательны при заполнени данных сертификатов, поле Common Name обязательно к заполнению, причем для сервера оно должно быть одно, а для клиента другое. Например в поле Common Name при генерации сертификата X.509 для сервера можно написать "server", а для клиента соотвественно "client".

Создаем сертификат X.509 для сервера.

# chmod +x build-key-server
# ./build-key-server server
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.
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) [RU]:
State or Province Name (full name) [RU]:
Locality Name (eg, city) [Moscow]:
Organization Name (eg, company) [Company]:
Organizational Unit Name (eg, section) [Office]:
Common Name (eg, your name or your server's hostname) [server]:
Name [changeme]:IAmServer
Email Address [abuse@company-domain.com]:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Using configuration from /etc/openvpn/easy-rsa/openssl.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'RU'
stateOrProvinceName   :PRINTABLE:'RU'
localityName          :PRINTABLE:'Moscow'
organizationName      :PRINTABLE:'Company'
organizationalUnitName:PRINTABLE:'Office'
commonName            :PRINTABLE:'server'
name                  :PRINTABLE:'IAmServer'
emailAddress          :IA5STRING:'abuse@company-domain.com'
Certificate is to be certified until Apr  7 12:15:29 2022 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

Для создания файла параметров Диффи-Хелмана, предназначенного для обеспечения более надежной защиты данных при установке соединения клиента с сервером, выполняем:

# chmod +x build-dh
# ./build-dh
Generating DH parameters, 1024 bit long safe prime, generator 2
This is going to take a long time

Создаем сертификаты для удаленного клиента:

# ./build-key-pass Client1
Generating a 1024 bit RSA private key
...................++++++
.......................................................++++++
writing new private key to 'Client1.key'
...

...
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

На последок генерируем общий для клиента и сервера TLS-ключ, служащий дополнительной защитой. TLS предоставляет возможности аутентификации и безопасной передачи данных через Интернет с использованием криптографических средств. Часто происходит лишь аутентификация сервера, в то время как клиент остается неаутентифицированным. Для взаимной аутентификации каждая из сторон должна поддерживать инфраструктуру открытого ключа (PKI), которая позволяет защитить клиент-серверные приложения от перехвата сообщений, редактирования существующих сообщений и создания поддельных (источник: wikipedia).

openvpn --genkey --secret ta.key

В результате в папке /etc/openvpn/easy-rsa/keys мы имеем следующие файлы:

ca.crt - главный сертификат подлинности (Certificate Authority), этот файл нужен и клиенту и серверу
dh1024.pem - ключ Диффи Хельмана, этот файл нужен только серверу
server.crt - сертификат X.509 сервера (стандарт X.509 ITU-T является фундаментальным стандартом, лежащим в основе всех остальных, используемых в Инфраструктуре Открытых Ключей (ИОК). Основное его назначение - определение формата электронного сертификата и списков отозванных сертификатов), нужен только серверу
server.key - ключ сервера, нужен только серверу (СЕКРЕТНЫЙ файл)
client1.crt - сертификат X.509 клиента, нужен только клиенту
client1.key - ключ клиента, нужен только клиенту (СЕКРЕТНЫЙ файл)
ta.key - TLS-ключ, нужен и клиенту и серверу

Серверу - одно, клиенту - другое

Теперь в папку /etc/openvpn/keys на будущем сервере OpenVPN скопируем файлы ca.crt, dh1024.pem, server.crt, server.key и ta.key:

# mkdir /etc/openvpn/keys
# cp /etc/openvpn/easy-rsa/keys/ca.crt dh1024.pem server.crt server.key ta.key /etc/openvpn/keys

В папку будущего клиента /etc/openvpn/client1 скопируем файлы ca.crt, client1.crt, client1.key и ta.key:

# mkdir /etc/openvpn/client1
# cp /etc/openvpn/easy-rsa/keys/ca.crt client1.crt client1.key ta.key /etc/openvpn/client1

Теперь подкаталог "client1" можно скопировать в папку конфигурации будущего удаленного клиента Windows.

В принципе, в папке /etc/openvpn/easy-rsa/keys/ все файлы можно оставить, на всякий случай :) Права на доступ к папке openvpn лучше обновить до правильных:

# chown -R root:wheel /etc/openvpn

Конфиг сервера OpenVPN

Расположение файла конфигурации сервера: "/etc/openvpn/config/server.conf" (для Windows: "C:Program FilesOpenVPNconfigserver.ovpn").

Пример файла конфигурации сервера OpenVPN (подходит для Windows, Linux, FreeBSD с минимальными изменениями):

port 1194

# на сайте разработчиков рекомендуется использовать udp в том числе
# по соображениям безопасности
proto udp

dev tun

ca "/etc/openvpn/keys/ca.crt"
cert "/etc/openvpn/keys/server.crt"
key "/etc/openvpn/keys/server.key" # Этот файл хранить в секрете!

dh "/etc/openvpn/keys/dh1024.pem"

topology subnet

# включаем TLS аутификацию
tls-server
# указываем tls-ключ, и указываем 0 для сервера, а 1 для клиента
tls-auth "/etc/openvpn/keys/ta.key" 0
# таймаут до реконекта
tls-timeout 120
auth MD5

# задаем IP-адрес сервера и маску подсети
server 10.8.0.0 255.255.255.0

# задаем МАРШРУТ который передаём клиенту
# и маску подсети для того чтобы он "видел"
# сеть за OpenVPN сервером (сеть 192.168.10.0/24)
push "route 192.168.10.0 255.255.255.0"

ifconfig-pool-persist "/etc/openvpn/config/ipp.txt"

route 192.168.10.0 255.255.255.0

# If enabled, this directive will configure
# all clients to redirect their default
# network gateway through the VPN, causing
# all IP traffic such as web browsing and
# and DNS lookups to go through the VPN
# (The OpenVPN server machine may need to NAT
# or bridge the TUN/TAP interface to the internet
# in order for this to work properly).
# Фактически означает, что даже в интернет вы будете ходить через
# рабочий интернет-шлюз. Имейте это ввиду!
# После отключения от VPN-соединения вполне возможно вам будет необходимо
# выполнить команду в консоли cmd: ipconfig /renew.
push "redirect-gateway def1 bypass-dhcp"

# Сообщаем удаленному клиенту адрес внутреннего DNS-сервера
# чтобы клиент мог по именам обращаться к компьютерам локальной сети
push "dhcp-option DNS 192.168.10.100"

# удерживать соединение (полезно при работе через nat, proxy и т.п.)
keepalive 10 120

# включаем шифрацию пакетов
cipher BF-CBC

# включить сжатие (если есть проблемы при соединении - выключите эту опцию на клиенте и сервере)
comp-lzo

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

;user nobody
;group nobody

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

# клиенты могут "видеть" друг друга
client-to-client

status "/etc/openvpn/log/openvpn-status.log"

log "/etc/openvpn/log/openvpn.log"
log-append "/etc/openvpn/log/openvpn.log"

# уровень детализации отчетов
verb 3

Примечания к конфигурационному файлу сервера OpenVPN

В данном конфиге будут только два различия в версиях сервера для Unix или для Windows.

1. Пути расположения файлов конфигурации, сертификатов и пр. в конфиге для Windows должны прописываться так:

dh "C:Program FilesOpenvpnconfigdh1024.pem"

а в Linux/FreeBSD так:

dh "/etc/openvpn/config/dh1024.pem"

2. В конфиге для Windows следующие строки должны быть закомментированы:

;user nobody
;group nobody

а в Linux/FreeBSD (по желанию или по соображениям безопасности, но режиме отладки самого сервера OpenVPN можно сначала запускать сервер OpenVPN под админом, чтобы в случае проблем не грешить на права доступа, но потом обязательно сменить запуск на nobody!!!) раскомментированы:

user nobody
group nobody

С конфигом для сервера, в принципе, все. Для начала работы вполне достаточно того конфига, который указан выше.

Автозапуск сервера OpenVPN в Linux/FreeBSD

Для автоматического запуска сервера OpenVPN можно использовать следующий скрипт (# - комментарий), например, start_openvpn.sh (не забудьте сделать его исполняемым "chmod +x start_openvpn.sh"):

#!/bin/sh
dir=/etc/openvpn/config
modprobe tun
echo 1 > /proc/sys/net/ipv4/ip_forward
openvpn --cd $dir --daemon --config /etc/openvpn/config/server.conf
# кстати, здесь можно запускать несколько серверов OpenVPN одновременно:
# openvpn --cd $dir --daemon --config /etc/openvpn/config/server2.conf

либо такой (например, во FreeBSD):

openvpn_enable="YES"
openvpn_if="tun" #
openvpn_configfile="/etc/openvpn/config/server.conf"
openvpn_dir="/etc/openvpn" # --cd directory

Конфиг клиента OpenVPN на Windows XP

Файлы клиента берем из папки /etc/openvpn/client1 на сервере и копируем их в папку "C:Program FilesOpenVPNconfig" на клиенте.

Расположение файла конфигурации клиента: "C:Program FilesOpenVPNconfigclient1.ovpn" (для Linux/FreeBSD расположение, полагаю, где-либо в домашней папке юзера, к примеру, "/home/vpn/client1.ovpn").

Пример файла конфигурации клиента OpenVPN :

client

dev tun

proto udp

# IP-адрес и порт сервера OpenVPN)
remote 444.333.222.111 1194

resolv-retry infinite

nobind

persist-key
persist-tun

ca "C:Program FilesOpenVPNconfigca.crt"
cert "C:Program FilesOpenVPNconfigclient1.crt"
key "C:Program FilesOpenVPNconfigclient1.key"

tls-client
tls-auth "C:Program FilesOpenVPNconfigta.key" 1
auth MD5

#Это еще одна защита, на этот раз от "man in the middle" атаки
ns-cert-type server

comp-lzo

verb 3

Также надо настроить брандмауэр для того, чтобы внешние клиенты OpenVPN могли "видеть" сеть "за NAT". Я приведу часть конфига iptables работающего шлюза CentOS / Squid (внутренняя сеть 192.168.10.0/24):

IF_EXT="eth1"
IF_INT="eth0"
IF_VPN="tun0"

IPT="/sbin/iptables"

VPN_NET="10.8.0.0/24"

IPT="/sbin/iptables"

# flush
$IPT --flush
$IPT -t nat --flush
$IPT -t mangle --flush
$IPT -X

# loopback
$IPT -A INPUT -i lo -j ACCEPT
$IPT -A OUTPUT -o lo -j ACCEPT

# default
$IPT -P INPUT DROP
$IPT -P OUTPUT DROP
$IPT -P FORWARD DROP

# allow forwarding
echo 1 > /proc/sys/net/ipv4/ip_forward
...

...
# FORWARD chain
# #########################################

# Форвардинг пакетов из внутренней сети "наружу"
# К нашему вопросу не относится, для общего понимания привел.
$IPT -A FORWARD -i $IF_INT -o $IF_EXT -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
$IPT -A FORWARD -i $IF_EXT -o $IF_INT -m state --state ESTABLISHED,RELATED -j ACCEPT

# Маршрутизация пакетов VPN-клиентов
$IPT -A FORWARD -i $IF_INT -o $IF_VPN -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
$IPT -A FORWARD -i $IF_VPN -o $IF_INT -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPT -A FORWARD -s $VPN_NET -j ACCEPT
...

...
# NAT
# #########################################

# Веб-трафик клиентов внутренней сети предприятия автоматически "заворачиваем"
# на прокси-сервер Squid в прозрачном режиме. 
$IPT -t nat -A PREROUTING -i $IF_INT -p tcp --dport 80 -j DNAT --to 192.168.10.100:3128

# VPN-clients www via Squid
# Т.к. мы указали клиенту VPN взять маршрут по-умолчанию через сервер OpenVPN,
# то будет весьма неплохо дать ему возможность выходить в интернет без "головной боли",
# прозрачно перекинув его запросы на локальный прокси-сервер Squid в прозрачном режиме.
$IPT -t nat -A PREROUTING -i $IF_VPN -p tcp --dport 80 -j DNAT --to 10.8.0.1:3128

# SNAT - внутреняя сеть (за NAT) должна иметь возможность выхода в интернет
$IPT -t nat -A POSTROUTING -o $IF_EXT -j MASQUERADE
...

...
# INPUT chain
# #########################################
$IPT -A INPUT -p tcp ! --syn -m state --state NEW -j DROP
$IPT -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# Разрешаем внешним клиентам соединяться с нашим сервером OpenVPN
$IPT -A INPUT -i $IF_EXT -p udp --dport 1194 -j ACCEPT

# ssh
$IPT -A INPUT -i $IF_INT -p tcp --dport 22 -j ACCEPT

# Разрешаем входящие соединения по виртуальной сети
$IPT -A INPUT -i $IF_VPN -j ACCEPT
...

...
# OUTPUT chain
# #########################################

# В принципе, нет смысла ставить здесь ограничения.
$IPT -A OUTPUT -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

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

Отзыв клиентского сертификата

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

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

...
error 23 at 0 depth lookup:certificate revoked

После успешного выполнения последней команды (вы должны увидеть последнюю строчку) в директории /etc/openvpn/easy-rsa/2.0/keys будет создан файл файл crl.pem (CRL - certificate revocation list - список отозванных сертификатов). Скопируйте его в директорию, где у вас находятся остальные файлы, имеющие отношение к работающему серверу OpenVPN. По идее, это директория /etc/openvpn. На всякий случай, проверьте существование в этой директории старого файла crl.pem (есть хорошая практика - сначала сделать резервную копию). Учтите, что в команде подразумеваются относительные пути, а не абсолютные:

# cp keys/crl.pem /etc/openvpn/

А теперь укажем нашему серверу проверять список отозванных сертификатов каждый раз при подключении нового клиента. Для этого надо добавить в конфиг сервера (возможно, /etc/openvpn/server.conf) одну строчку:

crl-verify crl.pem

Перезагрузим сервер OpenVPN:

# service openvpn restart

Теперь даже если вы не удалили с сервера ключи пользователя client25, он не сможет подключиться.

Авторизуйтесь для добавления комментариев!


    забыли пароль?    новый пользователь?