главная - Статьи - Удаленный доступ (VPN)
Установка OpenVPN в CentOS 7 / Debian / Ubuntu etc.
Дата обновления: 02.12.2022На этом сайте уже неоднократно публиковались статьи по настройке OpenVPN, но время летит, инструменты немного изменяются, узнаются новые опции, поэтому решил обновить кладовую пошаговых how-to. Большинство из того, что здесь описано, касается не только CentOS, но и других дистрибутивов Linux, но у меня традиционно все для CentOS. С примерами рабочих конфигов сервера и клиента, разумеется.
Актуальность статьи: 02.12.2022 ПО: CentOS 7 minimal, SELinux включен. Все ПО обновлено с помощью yum update.
offtop, для CentOS 7: сделайте над собой усилие, не отключайте SELinux сразу после установки CentOS! В конце статьи кратко затрагивается и это. Даже встроенный firewall Windows может сослужить хорошую службу, что уж говорить про SELinux.
По сути, что в Debian, что в Ubuntu, что в CentOS и др. разницы в настройке нет. Ну разве что где-то yum install openvpn, а где-то apt install openvpn. Все, все остальные нюансы - это настройка PKI (то есть инфраструктуры ключей, проще говоря - создание списка сертификатов и ключей для сервера и клиентов). Конфиг сервера от дистрибутива Linux не зависит. Могут отличаться команды настройки firewall, но если у вас везде iptables, то и тут разницы не будет.
Оглавление:
Установка
Инфраструктура публичных ключей PKI
Сертификаты сервера OpenVPN
Клиентские ключи
Конфигурационный файл сервера
Конфигурационный файл клиента
Запускаем сервер
Отзыв сертификата
Справка по Easy-RSA
Настройка iptables
Установка
Устанавливаем openvpn:
# yum install epel-release
# yum install openvpn
Вспомогательные утилиты:
# yum install wget
Установка в Debian/Ubuntu:
# apt install openvpn
# yum install wget
Инфраструктура публичных ключей PKI
Директория для ключей:
# mkdir /etc/openvpn/keys
# cd /etc/openvpn/keys
Вообще, все операции с ключами OpenVPN можно совершать с помощью OpenSSL. Но есть утилита Easy-RSA, которая раньше шла в составе с OpenVPN, а теперь это отдельный проект https://github.com/OpenVPN/easy-rsa. Вот эту утилиту мы и скопируем себе на сервер:
# wget https://github.com/OpenVPN/easy-rsa/releases/download/v3.0.8/EasyRSA-3.0.8.tgz
# tar xvf EasyRSA-3.0.8.tgz
# cd /etc/openvpn/keys/EasyRSA-3.0.8
Вообще, есть еще вариант с yum install easy-rsa, но тут есть минус в том, что при дальнейшем обновлении можно получить версию easy-rsa новее, чем ту, с которой вы работаете сейчас, а вы все равно копируете эти скрипты и работаете в дальнейшем с копиями, поэтому - не знаю, можно и yum. А можно и wget. Если через yum, не забудьте скопировать файлы из /usr/share/easy-rsa/3.0.8 (на данный момент).
Создаем файл настроек, с пониманием того, что будет. Например, опция EASYRSA_PKI (по-умолчанию, "$PWD/pki") указывает путь, где будет создана директория для ключей.
Команда "init-pki" выполнит "rm -rf" содержимого директории, будьте внимательны! Вы еще инициализируете инфраструктуру ключей, её еще нет, но если там что-то есть, то это будет стерто. Большинство опций - дефолт, на свой вкус отредактируйте страну, OU, email и т.п. Обратите внимание на сроки (в днях) валидности сертифкатов CA, CRL, CERT.
В файле конфига vars старайтесь указывать или важные для вас опции, или те, которые вы переопределяете, но не стоит весь дефолтный конфиг сюда лить.
# nano vars set_var EASYRSA "/etc/openvpn/keys/EasyRSA-3.0.8" set_var EASYRSA_PKI "$EASYRSA/pki" set_var EASYRSA_REQ_COUNTRY "US" set_var EASYRSA_REQ_PROVINCE "California" set_var EASYRSA_REQ_CITY "San Francisco" set_var EASYRSA_REQ_ORG "Copyleft Certificate Co" set_var EASYRSA_REQ_EMAIL "me@example.net" set_var EASYRSA_REQ_OU "My Organizational Unit" set_var EASYRSA_KEY_SIZE 4096 set_var EASYRSA_ALGO rsa set_var EASYRSA_CA_EXPIRE 3650 set_var EASYRSA_CERT_EXPIRE 3650 set_var EASYRSA_CRL_DAYS 3650 set_var EASYRSA_DIGEST "sha512"
Сложного ничего там нет, посмотрите сами.
Создаем инфраструктуру публичных ключей (PKI, Public Key Infrastructure):
# ./easyrsa init-pki
При этом будет создан каталог /etc/openvpn/keys/EasyRSA-3.0.8/pki/
.
Внимание! После создания инфраструктуры никогда больше не запускайте команду init-pki! Эта команда, в числе прочего, выполнит "rm -rf" содержимого директории, будьте внимательны!
Чтобы при подключении клиентов к серверу OpenVPN можно было бы быть уверенным, что сертификат сервера и клиента - не поддельные, нужен кто-то, кто отвечает за "кристальную чистоту партийных рядов". Этот кто-то - удостоверяющий центр, CA (Certificate Authority). CA бывают свои (чаще самоподписанные) и публичные, типа Thawte, StartSSL и др. В данном примере рассмотрим ситуацию, когда используется свой CA - как минимум, это значительно дешевле. Даже свой CA не обязан быть на том же сервере, где будет запущен сервер OpenVPN, но чаще всего расположение CA для OpenVPN на том же сервере, что и сам OpenVPN.
Создаем свой CA:
# ./easyrsa build-ca
Можно было бы избежать ввода пароля (./easyrsa build-ca nopass), но при этом если кто-то скопирует секретный ключ вашего CA, он сможет подписывать "левые" ключи. Вы должны охранять приватный ключ CA как зеницу ока, ведь все остальное верифицируется именно им. Поэтому пароль должен быть стойким к перебору. В конце концов, вы не каждый день будете им пользоваться.
Итак, у нас появились секретный ключ ca.key и сертификат ca.crt:
/etc/openvpn/keys/EasyRSA-3.0.8/pki/private/ca.key
/etc/openvpn/keys/EasyRSA-3.0.8/pki/ca.crt
Секретный ключ нужно оставить на сервере и никому не отдавать. Каждый раз при выпуске нового сертификата сервера или пользователя нам будет необходим пароль секретного ключа! Он важнее сертификата сервера, пользователя, да всего вообще.
Сертификат CA (ca.crt) — открытый, его мы будем вместе с пользовательскими сертификатами передавать клиентам.
Сертификаты сервера OpenVPN
Создаем запрос сертификата для сервера без пароля с помощью опции nopass, иначе придется вводить пароль с консоли при каждом запуске сервера:
# ./easyrsa gen-req server nopass
Keypair and certificate request completed. Your files are:
req: /etc/openvpn/keys/EasyRSA-3.0.8/pki/reqs/server.req
key: /etc/openvpn/keys/EasyRSA-3.0.8/pki/private/server.key
Подписываем запрос на получение сертификата у нашего CA:
# ./easyrsa sign-req server server
В процессе работы скрипта вводим пароль от CA, который указывали раньше и отвечаем на вопрос yes. Мы получили подписанный нашим удостоверяющим центром сертификат для сервера — /etc/openvpn/keys/easy-rsa-master/easyrsa3/pki/issued/server.crt
Создаем ключ Диффи-Хелмана:
# ./easyrsa gen-dh
В применении к OpenVPN файл Диффи-Хелмана нужен для обеспечения защиты трафика от расшифровки, если ключи были похищены. Имеется в виду тот трафик, который был записан и сохранен еще до похищения ключей [https://habrahabr.ru/post/233971/]. Тема широкая, захламлять статью лирическими отступлениями не решился.
Генерация занимает приличное время (по отношению к другим ключам). В конце концов получаем ключ /etc/openvpn/keys/
EasyRSA-3.0.8/pki/dh.pem
Чтобы можно было отозвать клиентский сертификат (например, при утере мобильного устройства или при увольнении сотрудника), надо создать список отозванных сертификатов CRL:
# ./easyrsa gen-crl
Будет создан файл /etc/openvpn/keys/EasyRSA-3.0.8/pki/crl.pem
, который будет содержать список отозванных сертификатов. Этот файл необходимо скопировать в директорию /etc/openvpn/, указать в конфиге сервера OpenVPN и перезапустить сервер OpenVPN.
Копируем в папку /etc/openvpn все необходимые для работы openvpn сервера ключи (напомню, мы находимся в директории /etc/openvpn/keys/EasyRSA-3.0.8
):
# cp pki/{ca.crt,dh.pem,crl.pem} /etc/openvpn/
# cp pki/issued/server.crt /etc/openvpn/
# cp pki/private/server.key /etc/openvpn/
Создадим файл HMAC, для дополнительной верификации клиента и сервера (для защиты от DDoS, например):
# cd /etc/openvpn
# openvpn --genkey secret ta.key
Файл ta.key должен быть скопирован и передан клиенту.
В нормальной конфигурации сервера после старта (от root) права меняются на непривилегированного пользователя (nobody или созданного специально). Этот пользователь должен иметь права на чтение к сертификатам для аутентификации клиентов:
# chmod 644 /etc/openvpn/ca.crt
# chmod 644 /etc/openvpn/crl.pem
# chmod 644 /etc/openvpn/dh.pem
# chmod 644 /etc/openvpn/server.crt
Ключи server.key, ta.key должны быть доступны только root (chmod 600).
Клиентские ключи
Создадим ключ для клиента openvpn:
# cd /etc/openvpn/keys/EasyRSA-3.0.8
# ./easyrsa gen-req client1 nopass
# ./easyrsa sign-req client client1
Опять можно отметить, что могут быть ситуации, когда лучше ключ клиента защищать паролем, хотя бы несложным. Тогда всякий раз при подключении к VPN необходимо будет ввести пароль. Это может быть удобным, если вы не хотите, например, чтобы ваш ребенок случайно подключился к вашей рабочей сети и натворил делов. Для этого просто не надо указывать "nopass" в конце команды выше.
В итоге мы получим два файла:
Публичный сертификат клиента: /etc/openvpn/keys/EasyRSA-3.0.8/pki/issued/client1.crt
Приватный ключ клиента: /etc/openvpn/keys/EasyRSA-3.0.8/pki/private/client1.key
Клиенту вместе с конфигом (см ниже) нужно будет передать копии следующих файлов:
client1.crt;
client1.key;
ca.crt;
ta.key
которые все используются в клиентском конфиге. Никакие иные файлы, кроме тех, которые указаны в конфиге клиента, передавать клиенту не надо!
Конфигурационный файл сервера
Конфигурационный файл сервера по-умолчанию: /etc/openvpn/server.conf
. Скорее всего, у вас не будет необходимости менять его расположение.
Обратите внимание на общие опции для клиента и сервера. Это тип шифрования, сжатие трафика и др. Некоторые опции зеркальные. Например, на сервере ta.key 0, на клиенте ta.key 1 и др.
Пример 1 (конфиг сервера OpenVPN):
port 3876 proto udp dev tun ca ca.crt cert server.crt key server.key dh dh.pem # Проверка, не отозван ли сертификат клиента crl-verify crl.pem server 10.8.12.0 255.255.255.0 ifconfig-pool-persist ipp.txt # Пусть весь трафик клиента идет через VPN push "redirect-gateway def1" # DNS хостинга сервера (или иные, по вашему усмотрению): push "dhcp-option DNS 8.8.8.8" keepalive 10 120 tls-server tls-auth ta.key 0 tls-timeout 120 auth SHA512 cipher BF-CBC max-clients 10 user nobody group nobody persist-key persist-tun status openvpn-status.log log /var/log/openvpn.log # 0 is silent, except for fatal errors # 4 is reasonable for general usage # 5 and 6 can help to debug connection problems # 9 is extremely verbose verb 0
Пример 2 (конфиг сервера OpenVPN):
port 3725 proto udp dev tun ca ca.crt cert server.crt key server.key dh dh.pem crl-verify crl.pem server 10.8.0.0 255.255.255.0 ifconfig-pool-persist ipp.txt push "redirect-gateway def1" push "dhcp-option DNS 8.8.8.8" remote-cert-eku "TLS Web Client Authentication" keepalive 10 120 tls-server tls-auth ta.key 0 tls-timeout 120 auth SHA512 cipher AES-256-CBC max-clients 10 user nobody group nobody persist-key persist-tun status openvpn-status.log #log-append openvpn.log #log /dev/null #log /var/log/openvpn.log log openvpn.log verb 0
Оба конфига рабочие.
Конфигурационный файл клиента
Некоторые опции должны быть симметричны опциям сервера, в частности тип шифрования (здесь BF-CBC), сжатия трафика и др. Все приведенные ниже конфиги рабочие.
Приведены примеры конфигов клиентов OpenVPN для Windows. Для Linux все то же, только пути до файлов ключей надо указать как в конфиге сервера (см. выше).
Пример 1 (конфиг клиента OpenVPN):
client dev tun proto udp remote 1.2.3.4 3876 resolv-retry infinite nobind persist-key persist-tun mute-replay-warnings ns-cert-type server tls-auth "C:\\Program Files\\OpenVPN\\config\\ta.key" 1 auth SHA512 ca "C:\\Program Files\\OpenVPN\\config\\ca.crt" cert "C:\\Program Files\\OpenVPNconfig\\client1.crt" key "C:\\Program Files\\OpenVPN\\config\\client1.key" cipher BF-CBC verb 0
Пример 2 (соотв. примеру 2-го конфига сервера):
client dev tun proto udp remote 1.2.3.4 3876 resolv-retry infinite nobind block-outside-dns persist-key persist-tun mute-replay-warnings remote-cert-eku "TLS Web Server Authentication" remote-cert-tls server tls-client tls-auth "C:\\Program Files\\OpenVPN\\config\\ta.key" 1 auth SHA512 ca "C:\\Program Files\\OpenVPN\\config\\ca.crt" cert "C:\\Program Files\\OpenVPN\\config\\client1.crt" key "C:\\Program Files\\OpenVPN\\config\\client1.key" cipher AES-256-CBC verb 0
Запускаем сервер
# systemctl start openvpn@server
Проверяем, запустился или нет (считаем, что в конфиге указан порт 3876/udp):
# netstat -tulnp | grep 3876
udp 0 0 0.0.0.0:3876 0.0.0.0:* 10431/openvpn
Отлично, запустился на указанном порту.
Ну, или так проверяем:
# systemctl status -l openvpn@server
Если все ок, разрешаем автозапуск:
# systemctl enable openvpn@server
(для CentOS / SELinux) Если что-то не так, смотрим лог. Возможно, SELinux не разрешает запускать OpenVPN на выбранном вами порте.
# semanage port -a -t openvpn_port_t -p udp 3876
и еще раз пробуем запустить OpenVPN.
В любом случае, файл лога вам в помощь. После отладки лог можно и отключить (log /dev/null). VPN - он такой...
Отзыв сертификата
Для того, чтобы отозвать сертификат client1:
# cd /etc/openvpn/keys/EasyRSA-3.0.8/pki/
# ./vars
# ./easyrsa revoke client1
При этом будет создан новый файл crl.pem, который обязательно надо скопировать в директорию /etc/openvpn, заменив старый и перезапустить сервер OpenVPN.
А в файле index.txt
соответствующий сертификат будет отмечен символом R (рабочие V, а отозванные - R).
Т.к. инфраструктура ключей OpenVPN это по сути обычный CA OpenSSL, то многое из того, что вы знаете про OpenSSL, подойдет и для OpenVPN. Например, список сертификатов с серийными номерами, указанием, отозваны ли они и другой информацией находится в файле index.txt.
При попытке подключиться к серверу с отозванным сертификатом в логе сервера могут быть такие события (уровень детализации verb 4):
TLS: Initial packet from [AF_INET]1.2.3.4:65454, sid=3e2e1135 a0086339 CRL CHECK OK: C=RU, ST=NW, L=City, O=Org, OU=OU, CN=Org CA, name=EasyRSA, emailAddress=admin@localhost.local VERIFY OK: depth=1, C=RU, ST=NW, L=City, O=Org, OU=OU, CN=Org CA, name=EasyRSA, emailAddress=admin@localhost.local CRL CHECK FAILED: C=RU, ST=NW, L=City, O=Org, OU=OU, CN=client1, name=EasyRSA, emailAddress=client1@localhost.local (serial 04) is REVOKED TLS_ERROR: BIO read tls_read_plaintext error: error:140890B2:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:no certificate returned TLS Error: TLS object -> incoming plaintext read error TLS Error: TLS handshake failed
Обратите внимание на строчку "CRL CHECK FAILED" (Ошибка Проверки Списка Отозванных Сертификатов): сертификат с серийным номером 04 отозван (is REVOKED)!
Справка по Easy-RSA
Если вы хотите получить справку по утилите Easy-RSA, выполните команду:
# ./easyrsa
Для получения справки по конкретным командам, например build-ca:
# ./easyrsa help build-ca
Настройка iptables
Немного про настройку iptables. Чуть-чуть. По-умолчанию, таблицы INPUT, FORWARD (а порой и OUTPUT) должны быть в состоянии DROP. Поэтому необходимо разрешить прохождение пакетов из сети OpenVPN в интернет (eth0) и/или в локальную сеть (eth1). Пожалуйста, обратите внимание, это пример того, что вам может быть необходимо сделать. Все нижеприведенные команды уже не пошаговый how-to, как в разделах выше. Вы можете нарушить нормальную работу сети необдуманными действиями!
Разрешить доступ к серверу OpenVPN с внешнего интерфейса:
# iptables -A INPUT -i eth0 -p udp --dport 3876 -j ACCEPT
После этого клиенты OpenVPN смогут подключиться к серверу, но могут не иметь возможности выйти за его пределы, в зависимости от текущих настроек firewall.
Чтобы клиенты могли выходить в интернет или пользоваться ресурсами LAN, для начала на сервере OpenVPN разрешим маршрутизацию (действует до перезагрузки):
# echo 1 > /proc/sys/net/ipv4/ip_forward
или так (сохранится после перезагрузки):
# nano /etc/sysctl.conf
Добавить строку:
net.ipv4.ip_forward = 1
Перезагрузим сервис:
# systemctl restart network.service
Чтобы клиенты OpenVPN могли выходить в интернет от лица сервера (внешний интерфейс eth0):
# iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
Возможно, у вас уже есть правило для NAT, что-то вроде:
# iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
В таком случае нет необходимости в создании отдельного правила для маскарада из сети OpenVPN.
Чтобы клиенты OpenVPN могли работать с локальной сетью (интерфейс LAN eth1):
iptables -A FORWARD -i tun0 -o eth1 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -i eth1 -o tun0 -m state --state ESTABLISHED,RELATED -j ACCEPT
Пример рабочего скрипта для сервера OpenVPN (без подключения к локальной сети):
#!/bin/sh IF_EXT="eth0" IF_OVPN="tun0" OVPN_PORT="3876" IPT="/sbin/iptables" IPT6="/sbin/ip6tables" # flush $IPT --flush $IPT -t nat --flush $IPT -t mangle --flush $IPT -X $IPT6 --flush # 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 $IPT6 -P INPUT DROP $IPT6 -P OUTPUT DROP $IPT6 -P FORWARD DROP # allow forwarding echo 1 > /proc/sys/net/ipv4/ip_forward # NAT # ######################################### # SNAT - local users to out internet $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 # ssh $IPT -A INPUT -i $IF_EXT -p tcp --dport 2685 -j ACCEPT # удобно для тестов связи icmp (vpn) $IPT -A INPUT -i $IF_OVPN -p icmp -s 10.8.0.0/24 -j ACCEPT # если openvpn - еще и dns (vpn) $IPT -A INPUT -i $IF_OVPN -p udp --dport 53 -s 10.8.0.0/24 -j ACCEPT # openvpn $IPT -A INPUT -i $IF_EXT -p udp --dport $OVPN_PORT -j ACCEPT # FORWARD chain # ######################################### $IPT -A FORWARD -i $IF_OVPN -o $IF_EXT -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT $IPT -A FORWARD -i $IF_EXT -o $IF_OVPN -m state --state ESTABLISHED,RELATED -j ACCEPT # OUTPUT chain # ######################################### $IPT -A OUTPUT -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
Дополняйте, улучшайте, делитесь с другими опытом :) Вот, вроде бы и все. Удачи!
Единственно, что не хватает для полноты "справочника", так это настройки firewalld. Для тех, кто не выключал его в установленной CentOS 7/
Огромное спасибо за статью. Но один вопрос - Пример рабочего скрипта для сервера OpenVPN (без подключения к локальной сети) - куда (в какой файл) вставлять данный скрипт?
Спасибо!
# systemctl enable openvpn@server
# openvpn --config /etc/openvpn/server.conf &
netstat -tulnp | grep 3876
где 3876 - порт на котором висит openvpn,
Netstat найдет Pid, скажем, 2026. Грохаете этот процесс по pid:
kill -HUP 2026
Пример рабочего скрипта для сервера OpenVPN (без подключения к локальной сети):
#!/bin/sh
IF_EXT="eth0"
IF_OVPN="tun0"
и далее... я про это.
И ещё расскажите пожалуйста как добавить второго клиента?
Спасибо.
cd /etc/openvpn/keys/easy-rsa-master/easyrsa3
# ./easyrsa gen-req client2 nopass
# ./easyrsa sign-req client client2
Было бы не плохо рассмотрение данного вопроса.
И еще очень не хватает статьи об организации выборочной маршрутизации и о назначении каждому клиенту своих правил (вынесение их в отдельный файл).
На сервере в конфиге прописано:
push "route 192.168.3.0 255.255.255.0"
route 192.168.3.0 255.255.255.0
На клиенте маршрут в интернет через VPN туннель:
0.0.0.0/1 via 10.8.0.21 dev tun0
Нужно, чтобы при падении туннели хосты из подсети 192.168.3.0/24 ходили в интернет через eth0, а при поднятии VPN туннеля ходили в интернет снова через tun0.
Например, такой скрипт может быть:
ping -n 1 10.8.0.21 >nul
IF ERRORLEVEL 1 GOTO alarm
:alarm
start alarm_command.exe
GOTO end
:end
exit
Под alarm_command.exe может быть что угодно, хоть открытие jpg или браузера. Или выполнение перезапуска службы.
Вроде все захостилось и клиент пытается подключиться без ошибок, только состояние остается подключение,нет идей в чем может быть проблема?
Логи на клиенте пустые.
Буду очень благодарен.
Авторизуйтесь для добавления комментариев!
Внимание! В разных руководствах есть разные наборы опций, обдумайте их все. Например, где-то видел: set_var EASYRSA_SSL_CONF "$EASYRSA/openssl-1.0.cnf"
А оно вам точно надо? Вот что в описании написано: if you need to use a specific openssl config file, you can reference it here. Normally this file is auto-detected from a file named openssl-easyrsa.cnf from theEASYRSA_PKI or EASYRSA dir (in that order.) NOTE that this file is Easy-RSA specific and you cannot just use a standard config file, so this is an advanced feature.
ADVANCED, Карл! Если вам нужны какие-то особые опции OpenSSL, указывайте файл конфига, понимая, что он как минимум, у вас есть и понимая, зачем вам это.