В сегодняшней статье речь пойдет о создании собственного VPN сервера на основе OpenVPN - технологии создающей виртуальные частные сети между сервером и его клиентами. OpenVPN является свободным ПО и доступно для всех желающих.
VPN (Virtual Private Network) - Виртуальная частная сеть, технология позволяющая создавать виртуальные сети поверх сети интернет. Поскольку к сети подключаются только доверенные пользователи, такая сеть называется частной.
В наше время VPN активно используется не только для защиты трафика, но и для обхода блокировок и цензуры в сети интернет.
Объединяя клиентов в локальную сеть, VPN-сервер не только связывает пользователей друг с другом, но и играет роль шлюза для выхода во внешнюю сеть. Обращение к сетевым узлам происходит c ip-адреса VPN-сервера. Возвращение ответного трафика происходит в обратном порядке, сначала VPN-сервер, потом конечный клиент.
Установка OpenVPN
Для работы OpenVPN требуется поддержка TUN/TAP. Поэтому для OpenVPN подходят не все типы виртуализации VPS/VDS. Hапример, подходит KVM и не подходит OpenVZ. Хотя в OpenVZ и существует возможность включения TUN/TAP устройств, но не все хостинг-провайдеры ее предоставляют. Это лучше уточнить заранее, перед оформлением услуги.
Поддержку TUN проверяют командой ls -l /dev/net/tun, вывод будет примерно такой.
ls -l /dev/net/tun crw-rw-rw- 1 root root 10, 200 Sep 27 03:31 /dev/net/tun
В Ubuntu
Устанавливаем OpenVPN вместе с центром сертификации easy-rsa.
apt-get install -y openvpn easy-rsa
Копируем каталог easy-rsa в домашний каталог пользователя.
make-cadir ~/openvpn-ca
В CentOS
Для установки OpenVPN нужно добавить EPEL - репозиторий.
yum install -y epel-release
Устанавливаем OpenVPN вместе с центром сертификации easy-rsa.
yum install -y openvpn easy-rsa
Копируем каталог easy-rsa в домашний каталог пользователя.
cp -r /usr/share/easy-rsa/2.0 ~/openvpn-ca
Удостоверяющий центр, сертификаты и ключи
Переходим в каталог openvpn-ca.
cd ~/openvpn-ca
Сначала я редактирую файл vars, подставляя свои переменные. Я делаю это для того, чтобы при создании ключей и сертификатов не заполнять значения вручную.
nano vars
Нужно изменить эти несколько строк.
# These are the default values for fields # which will be placed in the certificate. # Don't leave any of these fields blank. export KEY_COUNTRY="US" export KEY_PROVINCE="CA" export KEY_CITY="SanFrancisco" export KEY_ORG="Fort-Funston" export KEY_EMAIL="me@myhost.mydomain" export KEY_OU="MyOrganizationalUnit" # X509 Subject Field export KEY_NAME="EasyRSA"
Для своего чешского сервера, я заполнил примерно так.
# These are the default values for fields # which will be placed in the certificate. # Don't leave any of these fields blank. export KEY_COUNTRY="CZ" export KEY_PROVINCE="CZ" export KEY_CITY="Ktis" export KEY_ORG="aruba" export KEY_EMAIL="vpn@techlist.top" export KEY_OU="aruba" # X509 Subject Field export KEY_NAME="server_aruba"
Инициализируем переменные.
source ./vars
Во время выполнения будет выдано напоминание, что если следом будет выполнена команда ./clean-all, то каталог keys будет очищен.
NOTE: If you run ./clean-all, I will be doing a rm -rf on /root/openvpn-ca/keys
Команда ./clean-all выполняется для очищения каталога keys от старых сертификатов и ключей, а также создания серийного и индексного файлов для новых.
./clean-all
Центр сертификации CA
Создадим сертификат и ключ центра сертификации CA. Если переменные были заданы заранее, то прописывать значения не нужно, во всех строках просто нажимаем Enter.
./build-ca Generating a 2048 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) [CZ]: State or Province Name (full name) [CZ]: Locality Name (eg, city) [Ktis]: Organization Name (eg, company) [aruba]: Organizational Unit Name (eg, section) [aruba]: Common Name (eg, your name or your server's hostname) [aruba CA]: Name [server_aruba]: Email Address [vpn@techlist.top]:
В каталоге keys появятся файлы ca.crt и ca.key.
- ca.crt - сертификат удостоверяющего центра CA. Должен быть и на сервере, и у клиента.
- ca.key - приватный ключ CA. Должен храниться только на сервере, секретный.
Сертификат и ключ сервера
Создадим сертификат и закрытый ключ сервера.
./build-key-server server
Во время выполнения нужно подписать и заверить сертификат - ввести "y" и нажать Enter. Challenge password задавать не нужно, просто нажимаем Enter.
Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y
В каталоге keys появятся файлы server.crt и server.key.
- server.crt - сертификат сервера, находится на сервере.
- server.key - ключ сервера, находится на сервере, секретный.
Ключ Diffie Hellman
Создадим ключ Diffie Hellman'а.
./build-dh
По завершению генерации ключа в каталоге keys появится файл dh2048.pem. Если в команде не задана длина шифрования, то по умолчанию будет создан 2048-битный файл.
- dh2048.pem - файл параметров Diffie Hellman'а, храниться только на сервере.
Ключ HMAC
Создадим ключ HMAC, для дополнительной TLS-аутентификации и защиты от DoS-атак и флуда.
openvpn --genkey --secret ./keys/ta.key
В каталоге keys появится файл ta.key.
- ta.key - ключ несущий в себе код аутентификации для проверки подлинности сообщений. Должен быть и на сервере и на клиенте. При использовании ключа в конфигурации сервера указывается вместе со значением 0, в клиентской конфигурации указывается со значением 1.
Сертификаты и ключи клиентов
Создадим сертификат и ключ клиента. Каждому клиенту нужно создавать отдельную пару (сертификат + ключ). Вместо username подставить имя пользователя.
./build-key username
Для примера создадим пару (сертификат + ключ) с именем client.
./build-key client
Подписываем и заверяем сертификат - y + Enter. Challenge password не задаем, просто нажимаем Enter.
Certificate is to be certified until Oct 8 14:03:17 2027 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
В каталоге keys появятся файлы client.crt и client.key.
- client.crt - сертификат клиента, находится у клиента.
- client.key - ключ клиента, находится у клиента, секретный.
Если спустя какое-то время нужно будет создать дополнительные клиентские сертификаты, то выполняем без очистки каталога keys.
source ./vars ./build-key username_1 ./build-key username_2 ./build-key username_3 ... и так сколько нужно.
Для конфигураций сервера и клиента нужны следующие файлы:
- server.crt - сертификат сервера, только сервер.
- server.key - ключ сервера, только сервер.
- dh2048.pem - ключ DH, только сервер.
- ca.crt - корневой CA-сертификат, сервер + клиент.
- ta.key - HMAC ключ, сервер + клиент.
- client.crt - сертификат клиента, только клиент.
- client.key - ключ клиента, только клиент.
Пять верхних файлов должны быть на сервере, четыре нижних должны быть переданы клиенту.
Создадим каталог server-keys в /etc/openvpn.
mkdir /etc/openvpn/server-keys
Перейдем в каталог keys и скопируем из него нужные файлы.
cd ~/openvpn-ca/keys cp server.crt server.key dh2048.pem ca.crt ta.key /etc/openvpn/server-keys
Настройка сервера
Теперь необходимо создать конфигурационный файл server.conf. Образец файла можно просмотреть в следующих каталогах:
- /usr/share/doc/openvpn-2.4.3/sample/sample-config-files/server.conf - в CentOS
- /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz - в Ubuntu
nano /etc/openvpn/server.conf
Для примера приведу минимальную конфигурацию OpenVPN сервера, которая может использоваться для повседневной работы в сети.
port 443 proto udp dev tun ca /etc/openvpn/server-keys/ca.crt dh /etc/openvpn/server-keys/dh2048.pem key /etc/openvpn/server-keys/server.key cert /etc/openvpn/server-keys/server.crt tls-auth /etc/openvpn/server-keys/ta.key 0 server 172.16.150.0 255.255.255.0 push "redirect-gateway def1 bypass-dhcp" keepalive 10 120 compress lz4-v2 push "compress lz4-v2" #comp-lzo mssfix 0 persist-key persist-tun log /var/log/openvpn/openvpn.log status /var/log/openvpn/openvpn-status.log verb 3
Некоторые строки закомментированы, поэтому предлагаю сначала разобрать написанное, а не бездумно копировать и удивляться что ничего не работает.
Ключи и сертификаты
Указываем расположение файлов ключей и сертификатов, которые перед этим были скопированы в каталог /etc/openvpn/server-keys.
ca /etc/openvpn/server-keys/ca.crt dh /etc/openvpn/server-keys/dh2048.pem key /etc/openvpn/server-keys/server.key cert /etc/openvpn/server-keys/server.crt tls-auth /etc/openvpn/server-keys/ta.key 0
После ta.key, на сервере добавляем 0, на клиентах добавляем 1.
Порт сервера
Указываем значение порта на котором будет работать сервер. По умолчанию OpenVPN использует 1194 порт, но его можно изменить на любой другой. Я рекомендую использовать 443, хотя бы потому, что его использование не может быть заблокировано.
port 443
Если Openvpn установлен на чистый VPS/VDS, то 443 порт не будет занят. Но при установке на машину уже использующуюся, данный порт может быть занят web-сервером.
Узнать какие порты и какой программой используются на текущий момент, можно с помощью утилиты netstat. Вот так выглядит отчет на чистой системе, кроме ssh ничего нет.
netstat -tunlp Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:23532 0.0.0.0:* LISTEN 1012/sshd tcp6 0 0 :::23532 :::* LISTEN 1012/sshd
Протокол TCP/UDP
Указываем протокол передачи пакетов, по умолчанию udp.
proto udp
Про различия UDP и TCP можно прочитать на Википедии. Здесь будет достаточно сказать что UDP работает быстрее чем TCP, а TCP надежнее чем UDP. Поскольку в VPN-сетях прежде всего важна скорость передачи данных, то выбор UDP в качестве протокола по умолчанию, очевиден.
TUN/TAP интерфейсы
Зададим тип сетевого интерфейса, TUN или TAP, который будет создаваться при запуске openvpn и использоваться для передачи данных. Про отличия TUN/TAP читаем Википедию, а использовать будем TUN, как задано по умолчанию.
dev tun
Рабочая подсеть
Зададим подсеть сервера, диапазон которой будет использоваться для выдачи адресов клиентам. По умолчанию в настройках OpenVPN используется подсеть 10.8.0.0/24, которая может быть изменена на любую из частных подсетей.
- 10.0.0.0
- 172.16.0.0
- 192.168.0.0
Подсети могут использоваться с масками /8, /16, /24 или 255.0.0.0, 255.255.0.0, 255.255.255.0, соответственно. Подробнее про частные подсети можно прочитать тут.
С используемыми подсетями не все просто, иногда появляются конфликты адресов.
Представьте что вы используете подсеть с адресом 192.168.0.0/24, в таком случае ваш шлюз будет иметь адрес 192.168.0.1. А теперь представьте что вы находитесь в каком-нибудь месте с публичным Wi-Fi, и пытаетесь подключиться к своей VPN-сети через него. Если Wi-Fi сеть будет использовать такой же диапазон адресов, что и ваша, то возникнет конфликт в маршрутизации. Ваше устройство просто не будет знать кто есть кто, точнее к кому относится шлюз, к Wi-Fi сети или к вашему VPN-серверу.
Этого можно избежать назначив рабочей подсетью сервера что-нибудь более оригинальное чем распространенное 192.168.0.0/24. Например можно использовать 172.16.150.0/24.
server 172.16.150.0 255.255.255.0
Указываем клиентам что в качестве шлюза по умолчанию нужно использовать шлюз VPN-сервера. Если этого не сделать то весь трафик будет ходить во внешнюю сеть с вашего адреса, даже при активном VPN-соединении.
push "redirect-gateway def1 bypass-dhcp"
Сжатие трафика
Если канал связи не слишком большой, то следует использовать сжатие трафика для экономии полосы пропускания. На толстых каналах трафик можно не сжимать, разницы не видно.
В версии OpenVPN ниже чем 2.4.+ (устанавливается в Ubuntu), следует использовать comp-lzo. Опция должна быть указана и на сервере, и на клиенте.
comp-lzo
При использовании OpenVPN выше чем 2.4.+ (устанавливается в CentOS), в конфигурации на стороне сервера следует использовать:
compress lz4-v2 push "compress lz4-v2"
А на стороне клиента указывают comp-lzo.
comp-lzo
Если сжатие активировано, то следует добавить опцию mssfix, чтобы скрыть VPN fingerprint, но об этом немного позже. Пока просто добавим mssfix и укажем дефолтное значение равное 0.
mssfix 0
Ведение логов
Чтобы вести логи сервера создадим каталог openvpn в /var/log.
mkdir /var/log/openvpn
В конфигурацию сервера добавим следующие строки.
log /var/log/openvpn/openvpn.log status /var/log/openvpn/openvpn-status.log
В первом файле ведется учет клиентских подключений к серверу. Те самые логи "отсутствием" которых заманивают пользователей VPN-сервисы. Что впрочем не мешает им выдавать логи клиентов по первому обращению из соответствующих структур. Во втором файле отмечается статус сервера.
Чтобы регулировать подробность логов добавляют опцию verb, значения могут варьироваться от 0 до 9, чем больше значение, тем подробнее запись. По умолчанию достаточно значения 3.
verb 3
Также можно указать значение mute, которое будет приглушать повтор записи одинаковых сообщений в логи, по умолчанию 20.
mute 20
Остальные настройки
При перезапуске OpenVPN не изменять tun/tap устройства и не перепроверять файлы ключей.
persist-key persist-tun
Опция keepalive отвечает за пинг клиентов и перезапуск туннеля. Например, каждые 10 секунд пинговать клиента, если в течении 120 секунд ответа от клиента не будет, то перезапускать туннель.
keepalive 10 120
На этом минимальную настройку можно считать законченной. Как я уже писал выше подобной конфигурации вполне хватает для безопасной работы в сети.
Запускаем OpenVPN сервер и добавляем его в автозагрузку.
systemctl start openvpn@server systemctl enable openvpn@server
После запуска сервера должен появиться tun интерфейс.
ifconfig tun0 tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 1500 inet 172.16.150.1 netmask 255.255.255.255 destination 172.16.150.2 unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 100 (UNSPEC) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 11 bytes 440 (440.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
Настройка Файрвола
Осталось включить форвардинг пакетов и настроить iptables. Сначала включим пересылку трафика между интерфейсами.
Добавляем строку net.ipv4.ip_forward = 1 в файл sysctl.conf echo net.ipv4.ip_forward = 1 >> /etc/sysctl.conf Применяем изменения sysctl -p
Для OpenVPN нужно настроить фаервол: разрешить входящие подключения к 443 порту, разрешить прохождение транзитных пакетов, настроить преобразование адресов SNAT.
Разрешаем подключения на 443-ем порту.
# eth0 заменить на имя своего основного интерфейса iptables -A INPUT -i eth0 -p udp --dport 443 -j ACCEPT
Разрешаем прохождение транзитных пакетов из подсети OpenVPN.
# Разрешаем транзит трафика из подсети OpenVPN iptables -A FORWARD -s 172.16.150.0/24 -j ACCEPT # Разрешаем установленные соединения для транзита iptables -A FORWARD -p all -m state --state ESTABLISHED,RELATED -j ACCEPT
Настраиваем SNAT. Локальный ip-адрес пакетов выходящих из подсети OpenVPN будет заменен на внешний ip-адрес вашего сервера.
# При необходимости заменить имя интерфейса XX.XX.XX.XX - заменить на свой IP сервера iptables --table nat --append POSTROUTING --out-interface eth0 -j SNAT --to XX.XX.XX.XX
Естественно это не все правила iptables, а только необходимые для работы OpenVPN. Подробнее про настройку netfilter/iptables можно прочитать здесь.
Про настройку клиента под Windows читаем здесь. Настройка клиента для Linux Mint здесь.