Схема следующа. OpenVPN-сервер находится в РФ, к нему подключаютсся клиенты, а также шлюз, через который идёт весь трафик. Обязательно использование режима DCO (Data channel offloading) для OpenVPN-интерфейсов клиента и шлюза, т.к. при включении этого режима производительность увеличивается драматически. Поэтому использование готовых скриптов типа github/angristan нам не подходит, будем поднимать всё ручками. Для начала нам нужно два сервера - в РФ и в забугорище. Оба подготавливаем идентично: ``` apt update && apt dist-upgrade -y ``` Если произошёл апгрейд ядра, нужно обязательно перезагрузиться, т.к. в дальнейшем мы будем устанавливать расширения ядра. ``` reboot ``` Когда перезагрузились, устанавливаем необходимые пакеты: ``` apt install -y openvpn openvpn-dco-dkms easy-rsa ``` Далее включаем модуль openvpn-dco: ``` modprobe ovpn-dco-v2 ``` Проверяем, включилось ли: ``` lsmod | grep ovpn ``` Если вывод пуст, разбираемся. Если вывод что-то типа > ovpn_dco_v2 86016 0 > ip6_udp_tunnel 16384 1 ovpn_dco_v2 > udp_tunnel 32768 1 ovpn_dco_v2 То всё хорошо, можно примменять на постоянку: ``` echo "ovpn-dco-v2" | sudo tee -a /etc/modules ``` ``` update-initramfs -u -k all ``` Можно ещё раз перезагрузиться и проверить наличие dco-модуля после перезагрузки `lsmod | grep ovpn` Теперь приступим к настройке OpenVPN-сервера. Инициализируем инфраструктуру открытых ключей и выпускаем сертификат сервера (без паролей для автозапуска): ``` make-cadir ~/openvpn-ca && cd ~/openvpn-ca ./easyrsa init-pki ./easyrsa build-ca nopass ./easyrsa gen-dh # Генерация и подписание ключей сервера ./easyrsa gen-req server nopass ./easyrsa sign-req server server # Генерация секретного ключа защиты от сканирования (TLS-Crypt) openvpn --genkey secret tls-crypt.key ``` Копируем ключи в рабочую директорию OpenVPN-сервера: ``` cp pki/ca.crt pki/dh.pem pki/issued/server.crt pki/private/server.key tls-crypt.key /etc/openvpn/server/ ``` Создаём конфиг сервера: ``` nano /etc/openvpn/server/server.conf ``` Вставляем следующее содержимое: ``` dev tun proto udp port 1194 server 10.210.0.0 255.255.255.0 topology subnet # Сертификаты и секреты ca /etc/openvpn/server/ca.crt cert /etc/openvpn/server/server.crt key /etc/openvpn/server/server.key dh /etc/openvpn/server/dh.pem tls-crypt /etc/openvpn/server/tls-crypt.key # Максимальная скорость (Только AES-128-GCM, без сжатия) data-ciphers AES-128-GCM data-ciphers-fallback AES-128-GCM # Логирование (минимум операций, разгрузка CPU) verb 1 mute 20 # Тайм-ауты и папка индивидуальных настроек keepalive 10 120 persist-key persist-tun client-config-dir /etc/openvpn/server/ccd # Маршрут по умолчанию для клиентов push "redirect-gateway def1 bypass-dhcp" push "dhcp-option DNS 1.1.1.1" ``` Далее необходимо создать на сервере конфиг, в котором описаны директивы, затрагивающие конкретный клиент. Имя такого файла должно соответствовать сертификату клиента (без расширения) и находиться в client-config-dir (у нас /etc/openvpn/server/ccd). Это аналог Client Specific Overrides в pFsense. В нашем случае таким клиентом будет шлюз в забугорище. Присвоим ему адрес в конце нашего диапазона и обязательно отменим перенаправление трафика в туннелль: ``` sudo mkdir -p /etc/openvpn/server/ccd echo "ifconfig-push 10.210.0.254 255.255.255.0" | sudo tee /etc/openvpn/server/ccd/special-gateway echo 'push-remove "redirect-gateway def1 bypass-dhcp"' | sudo tee -a /etc/openvpn/server/ccd/special-gateway ``` Теперь "финт ушами". Существует опция iroute в client specific override которая позволяет завернуть весь трафик туннеля конкретному клиенту (iroute 0.0.0.0 0.0.0.0). НО!!! Эта опция конфликтует с DCO, который нам нужен для производительности. Поэтому нужно сделать default маршрут от сервера в сторону шлюза. Но только для интерфейса tun0. Остальной трафик должен имет default маршрут в сторону физического интерфейса (в нашем случае ens3). Для этого применим policy-based routing, который будет включаться вместе с сервисом openvpn-server@server.service: ``` nano /etc/systemd/system/vpn-policy-routing.service ``` ``` [Unit] Description=OpenVPN Policy Routing for Clients After=network.target openvpn-server@server.service Requires=openvpn-server@server.service [Service] Type=oneshot RemainAfterExit=yes # Применяем правила: сначала добавляем локальный маршрут подсети в таблицу 100, затем дефолтный на шлюз ExecStart=/sbin/ip rule add from 10.210.0.0/24 table 100 ; /sbin/ip route add 10.210.0.0/24 dev tun0 proto kernel scope link table 100 ; /sbin/ip route add default via 10.210.0.254 dev tun0 table 100 # Корректно удаляем при остановке ExecStop=/sbin/ip rule del from 10.210.0.0/24 table 100 ; /sbin/ip route del default via 10.210.0.254 dev tun0 table 100 ; /sbin/ip route del 10.210.0.0/24 dev tun0 table 100 [Install] WantedBy=multi-user.target ``` ``` systemctl daemon-reload systemctl enable vpn-policy-routing.service ``` Ну а теперь самое время запустить сервер: ``` systemctl start openvpn-server@server.service ``` Проверяем, поднялся ли интерфейс и включился ли dco: ``` ip -details link show dev tun0 | grep dco ``` Вывод должен быть не пустой. Можно создавать клиентов с помощью скрипта: `./gen-client.sh user1 user2 user3 ...`. Теперь займёмся клиентом, который будет выступать в роли шлюза.