Двойной OpenVPN. Установка и настройка
Суть этой технологии в том, что интернет‑трафик проходит через два VPN-сервера вместо одного. Сначала трафик приходит на первый VPN-сервер, и оттуда направляется на второй VPN-сервер. Для примера, компьютер в домашней сети соединяется с VPN-сервером в России, а этот сервер соединяется c VPN-сервером за рубежом. При этом сервер в России будет одновременно — VPN-сервером для домашнего компа и VPN-клиентом для сервера за рубежом.
OpenVPN поддерживает два варианта установления соединения
- PSK (PreSharedKey или static key mode) — с симметричным ключом, который генерируется и записывается на все машины в процессе настройки VPN. Сгенерированный файл ключа содержит две пары 512 битных случайных ключей (в каждой паре ключ для шифрования и ключ для HMAC), записанные один за другим и закодированные в HEX. Если для директивы
secret
не задать параметрdirection
, то будет использоваться только первая пара, т.е. в обе стороны трафик будет шифроваться и подписываться одинаковыми ключами. - TLS (Transport Layer Security) — основан на инфраструктуре открытых ключей (PKI). Вначале устанавливается TLS соединение с аутентификацией обеих сторон по сертификатам, через которое производится обмен ключевым материалом. Из этого ключевого материала генерируются симметричные ключи и трафик внутри VPN шифруется уже этими ключами так же как в режиме PSK. Внутри TLS канала пользовательского трафика нет — исключительно служебная информация самого OpenVPN.
Рассмотрим пять варианта настройки двойного OpenVPN
- OpenVPN, точка-точка, PSK (static key), протокол UDP, порт 1194
- OpenVPN, точка-точка, PSK (static key), протокол TCP, порт 1234
- OpenVPN, точка-точка, TLS (finger print), протокол UDP, порт 1194
- OpenVPN, точка-точка, TLS (finger print), протокол TCP, порт 1234
- OpenVPN, сервер-клиенты, TLS (finger print), протокол TCP, порт 443
secret
была объявлена deprecated
в OpenVPN 2.6 и будет удалена в OpenVPN 2.7 — так что лучше использовать TLS вместе с finger print
.
Все серверы и компьютеры будут под управлением операционной системы Ubuntu Server. Роль VPN-клиента в домашней сети будет играть виртуальная машина. Роль VPN-клиентов ivanov
и petrov
в пятом варианте — облачные серверы разных провайдеров.
Установка пакета OpenVPN
В самом простом случае можно установить OpenVPN из репозитория Ubuntu
# apt install openvpn
Чтобы установить самую последнюю версию OpenVPN или наоборот, какую-то старую версию — нужно добавить репозиторий. Пакеты в репозитории подписаны закрытым OpenPGP ключом репозитория, а чтобы проверить их подлинность, потребуется открытый OpenPGP ключ. Каждый репозиторий доверяет только собственному ключу, а сами ключи помещаются в специальное хранилище /usr/share/keyrings
, к которому имеет доступ только суперпользователь.
Ключ может быть в двух форматах — текстовом (расширение файла .asc
) и бинарном (расширение файла .gpg
). Текстовые ключи наиболее распространены, так как этот формат более удобен при передаче. Но ключ в хранилище должны быть в бинарном формате, то есть, потребуется преобразование.
Скачать ключ, преобразовать в бинарный формат и записать в хранилище
# curl -fsSL https://swupdate.openvpn.net/repos/repo-public.gpg | gpg --dearmor > /usr/share/keyrings/openvpn.gpg
Теперь нужно создать файл .list
в директории /etc/apt/sources.list.d
# echo "deb [arch=amd64 signed-by=/usr/share/keyrings/openvpn.gpg] \ > https://build.openvpn.net/debian/openvpn/stable $(lsb_release -cs) main" > \ > /etc/apt/sources.list.d/openvpn.list
Теперь получим данные о новых, доступных к установке, пакетах
$ sudo apt update
Посмотрим, какая последняя версия доступна для установки
# apt-cache policy openvpn openvpn: Установлен: (отсутствует) Кандидат: 2.6.12-jammy0 Таблица версий: 2.6.12-jammy0 500 500 https://build.openvpn.net/debian/openvpn/stable jammy/main amd64 Packages 2.6.11-jammy0 500 500 https://build.openvpn.net/debian/openvpn/stable jammy/main amd64 Packages 2.6.10-jammy0 500 500 https://build.openvpn.net/debian/openvpn/stable jammy/main amd64 Packages 2.6.9-jammy0 500 500 https://build.openvpn.net/debian/openvpn/stable jammy/main amd64 Packages 2.6.8-jammy0 500 500 https://build.openvpn.net/debian/openvpn/stable jammy/main amd64 Packages ..........
Установим последнюю доступную версию OpenVPN — это 2.6.12
# apt install openvpn
Директивы конфигурации OpenVPN
Чтобы не запутаться в директивах конфигурации — следует помнить о всех вариантах настройки
- OpenVPN может работать в режиме «точка-точка» (
mode p2p
) или в режиме «сервер-клиенты» (mode server
) - OpenVPN может использовать PSK (общий ключ шифрования известен каждой стороне заранее) или TLS (общий ключ шифрования создается каждой стороной в процессе обмена — с использованием алгоритма Diffie-Hellman)
- OpenVPN может работать по протоколу UDP или по протоколу TCP, хотя предпочтительный вариант — UDP
Директивы mode и topology
Директива mode p2p|server
задает основной режим работы OpenVPN. По умолчанию OpenVPN работает в режиме p2p
, то есть «точка-точка». Относительно новый режим server
реализует возможность сервера с множеством клиентов.
Директива topology p2p|net30|subnet
задает топологию виртуальной адресации при использовании dev tun
. Эта директива не имеет значения при использовании dev tap
, который всегда использует топологию subnet
. В режиме «точка-точка» (mode p2p
) — используется топология p2p
, в режиме «сервер-клиенты» (mode server
) — используется топология net30
или subnet
.
Универсальным решением для режима «сервер-клиенты» является net30
— это значение по умолчанию. Сервер будет работать со всеми версиями Windows, Linux, Mikrotik. Каждый клиент работает в маленькой сети на четыре ip-адреса, внутри этой сети используется режим точка-точка, два ip-адреса внутри этой сети не используются (адрес сети и широковещательный). Топология net30
фактически устарела и сохраняется исключительно для поддержки старых Windows клиентов.
Значение subnet
рекомендуется для режима «сервер-клиенты», когда клиентами являются Linux и Windows 8.2 и выше. Устройство tun
будет настроено на использование ip-адреса и маски сети как «традиционная» широковещательная сеть. Сетевой и широковещательный ip-адреса не должны использоваться — хотя tun
не имеет понятия о широковещании, клиенты Windows не смогут правильно использовать эти адреса. Все остальные ip-адреса в сети доступны для использования.
Значение p2p
не может использоваться в системах Windows и не подходит, если сервер или любой клиент может быть Windows. В этой топологии все узлы настроены как настоящие двухточечные ссылки — каждый ip-адрес может использоваться, включая первый и последний. Другими словами, в сети 10.8.0.0/24
в топологии p2p
можно использовать все 256 ip-адресов. Но Windows считает первый и последний ip-адреса сетевым и широковещательным адресами.
Директивы ifconfig и route
Директива ifconfig local remote
в режиме p2p
задает два серых ip-адреса локальной и удаленной конечных точек VPN-туннеля. Эти ip-адреса будет привязаны к tun-интерфейсам, которые создаются на этапе запуска службы OpenVPN.
Директива ifconfig ip-addr netmask
в режиме server
задает ip-адрес и маску подсети tun-интерфейса. Директива ifconfig-push
позволяет назначить статический ip-адрес клиенту, используется вместе с директивой client-config-dir
.
Директива route
позволяет добавить маршрут в таблицу маршрутизации после установки соединения. Можно указать несколько маршрутов. Маршруты будут автоматически удалены в обратном порядке перед закрытием устройства netmask
не задано — используется значение по умолчанию 255.255.255.255
. Если значение gateway
не задано — используется значение route-gateway
или второго аргумента ifconfig
.
route network/ip-addr route network/ip-addr netmask route network/ip-addr netmask gateway route network/ip-addr netmask gateway metric
Директива route-gateway
задает значение gateway
для директивы route
. Директива route-metric
задает значение metric
для директивы route
.
Директива client-to-client
Директива client-to-client
позволяет каждому клиенту «видеть» других клиентов, которые в данный момент подключены. В противном случае каждый клиент будет видеть только сервер. При этом пакеты от клиентов не попадают в сетевой стек сервера, где установлен OpenVPN сервер — речь идет о внутренней маршрутизации OpenVPN. Кроме использования директивы client-to-client
можно разрешить пересылку пакетов между сетевыми интерфейсами. Это будет работать медленнее, но позволит задействовать всю мощь netfilter
для фильтрации пакетов.
# sysctl -w -q net.ipv4.ip_forward=1 # iptables -P FORWARD DROP # iptables -A FORWARD -i tun0 -o tun0 -j ACCEPT
Директива dh (Diffie-Hellman)
Директива dh file|none
задет файл, который содержит параметры Diffie-Hellman в формате .pem
. Директива используется только в файле конфигурации сервера, в режиме tls-server
. Значение none
предписывает не использовать файл Diffie-Hellman, а использовать протокол на элиптических кривых ECDH (Elliptic curve Diffie-Hellman) для получения общего ключа, которым будут шифроваться данные. Но для этого требуется, чтобы одноранговые узлы использовали библиотеку SSL, которая поддерживает наборы шифров ECDH TLS (например, OpenSSL 1.0.1+ или mbed TLS 2.0+).
Директивы iroute и client-config-dir
В большинстве случаев директива iroute
не нужна, потребность в ней возникает, когда сетям за узлами VPN нужно обмениваться данными.
Предположим, что нужно установить связь между сетями 192.168.1.0/24
и 192.168.2.0/24
, а также между 192.168.1.0/24
и 192.168.3.0/24
— тогда файлы конфигурации vpn_server
будут выглядеть примерно так.
# cat /etc/openvpn/server/config.conf
dev tun
proto udp
port 1194
local 123.123.123.123
mode server
topology subnet
tls-server
ifconfig 10.8.0.1 255.255.255.0
# сообщить клиентам, что сеть 192.168.1.0/24 доступна через хост 10.8.0.1
push "route 192.168.1.0 255.255.255.0 10.8.0.1"
client-config-dir /etc/openvpn/ccd
# cat /etc/openvpn/ccd/client_one
# назначить клиенту client_one второй ip-адрес виртуальной VPN-сети ifconfig-push 10.8.0.2 255.255.255.0 # сообщить серверу, что сеть 192.168.2.0/24 доступна через хост 10.8.0.2 route 192.168.2.0 255.255.255.0 10.8.0.2 # сообщить серверу, что за этим клиентом есть сеть 192.168.2.0/24 iroute 192.168.2.0 255.255.255.0
# cat /etc/openvpn/ccd/client_two
# назначить клиенту client_two третий ip-адрес виртуальной VPN-сети ifconfig-push 10.8.0.3 255.255.255.0 # сообщить серверу, что сеть 192.168.3.0/24 доступна через хост 10.8.0.3 route 192.168.3.0 255.255.255.0 10.8.0.3 # сообщить серверу, что за этим клиентом есть сеть 192.168.3.0/24 iroute 192.168.3.0 255.255.255.0
Файл конфигурации client_one
# cat /etc/openvpn/client/config.conf
dev tun proto udp pull tls-client topology subnet remote 123.123.123.123 1194
Файл конфигурации client_two
# cat /etc/openvpn/client/config.conf
dev tun proto udp pull tls-client topology subnet remote 123.123.123.123 1194
Директива iroute
сообщает OpenVPN о необходимости создания «внутреннего» маршрута OpenVPN к указанной сети через определенный узел.
Причина, по которой необходимы два маршрута, заключается в том, что директива route
направляет пакет из ядра в OpenVPN. После попадания в OpenVPN — директива iroute
направляет пакет к определенному клиенту. Этот фрагмент конфигурации спецефичен для каждого клиента (потому что за каждым клиентом могут быть разные сети), поэтому правильное место для добавления этой информации — каталог файлов конфигурации клиентов client-config-dir
.
iroute
можно использовать SNAT на клиентах — но это потребует определенных накладных расходов на маскарадинг.
# iptables -t nat -A POSTROUTING -s 192.168.2.0/24 -o tun0 -j MASQUERADE # на vpn-клиенте client_one
# iptables -t nat -A POSTROUTING -s 192.168.3.0/24 -o tun0 -j MASQUERADE # на vpn-клиенте client_two
Директива client-config-dir
задает каталог для файлов конфигурации клиентов. После аутентификации подключающегося клиента OpenVPN будет искать в этом каталоге файл с тем же именем, что и CommonName X509 клиента. Если соответствующий файл существует, он будет открыт и проанализирован на предмет параметров конфигурации, специфичных для клиента. Если соответствующий файл не найден, OpenVPN попытается открыть и проанализировать файл по умолчанию с именем DEFAULT
, который может быть предоставлен, но не является обязательным. При этом файлы конфигурации должны быть доступны OpenVPN для чтения после сброса привилегий root
.
Директивы remote и local
Директива remote
задает хост, протокол, порт сервера, к которому клиент должен подключиться. При использовании протокола TCP директива работает как фильтр, отклоняя соединения с любого хоста, который не соответствует host
. При использовании протокола UDP — OpenVPN будет принимать пакеты с любых адресов, но не будет их использовать, пока пакеты не пройдут аутентификацию (очень лекко подделать ip-адрес источника в UDP пакете).
remote host remote host port remote host port proto
Директива local
задает ip-адрес сетевого интерфейса, который нужно простушивать. Если директива не задана — будут прослушиваться все сетевые интерфейсы.
Директивы proto и port
Директива proto
задает протокол и может принимать значения udp
, tcp-client
, tcp-server
. Для работы по UDP необходимо указать proto udp
на сервере и на клиенте (это значение по умолчанию). Для работы по TCP один узел должен использовать значение tcp-server
, а все прочие — значение tcp-client
. Узел tcp-server
будет бесконечно ожидать входящего соединения. Узел tcp-client
будет пытаться подключиться с заданным интервалом между попытками (директива connect-retry
). И будет делать это бесконечно или заданное кол-во раз (директива connect-retry-max
).
Директива port
задает номер порта TCP/UDP как для локального, так и для удаленного хоста, по умолчанию 1194. Другими словами, устанавливает значения директив lport
и rport
.
В файле конфигурации сервера директива lport
устанавливает значение, на котором сервер будет принимать пакеты от клиента. В файле конфигурации клиента директива lport
устанавливает значение, с которого клиент будет отправлять сообщения серверу. Директива lport
на клиенте несовместима с директивой nobind
.
Директива rport
задает значение port
для директивы remote
.
Директива nobind
предписывает не использовать фиксированный номер порта. Операционная ситема выделит динамический порт для приема пакетов, которые приходят с сервера. Поскольку значение динамического порта не может быть известно заранее, директива может быть использована только на клиенте. Директива nobind
несовместима с директивой lport
.
Директивы data-ciphers и auth
Директива data-ciphers
задает набор алгоритмов шифрования для канала передачи данных. Если директива не задана, то для OpenVPN 2.5 и выше — значение по умолчанию будет AES-256-GCM:AES-128-GCM
. Сервер выбирает первый шифр в этом списке, который также есть на стороне клиента. Если общий шифр не найден, клиент отклоняется с сообщением AUTH_FAILED
. Для OpenVPN 2.5 можно дополнить этот список с помощью директивы cipher
. Для OpenVPN 2.6 этот список можно дополнить, если указана директива compat-mode
.
Директива auth alg|none
позволяет добавлять подпись HMAC для всех пакетов канала передачи данных с использованием алгоритма alg
(по умолчанию SHA1). В режиме шифрования со статическим ключом ключ HMAC включается в файл ключа. В режиме TLS ключ HMAC динамически генерируется и передается между узлами через канал управления TLS. Если OpenVPN получает пакет с плохим HMAC — этот пакет сразу отбрасывается. Обычно HMAC добавляет 16 или 20 байт на пакет. Чтобы отключить HMAC — нужно установить значение none
.
Директива tls-auth
позволяет добавлять подпись HMAC для всех пакетов канала управления TLS для смягчения DoS-атак и атак на стек TLS. Директива включает своего рода «брандмауэр HMAC» на порту TCP/UDP OpenVPN, где пакеты канала управления TLS, содержащие неверную подпись HMAC, могут быть немедленно отброшены без ответа. Рекомендуется использовать при запуске OpenVPN в режиме, в котором он прослушивает пакеты с любого ip-адреса — например, когда директива remote
не указана.
Директивы user и group
Директивы user
и group
позволяют понизить права службы сервера и клиента — это нужно для повышения безопасности. Директивы persist-tun
и persist-key
обеспечивают правильную работу после понижения прав.
Директива keepalive
Директива keepalive
является макрокомандой и будет преобразована в директивы ping
и ping-restart
. В режиме p2p
директиву нужно использовать как на сервере, так и на клиенте. В режиме server
директиву нужно указывать только на сервере — сервер сам отправит клиенту ping
и ping-restart
. При этом значения с сервера переопределят локальные значения клиента, если они были установлены.
keepalive interval timeout
Например, директива keepalive 10 60
будет преобразована по следующему алгоритму
if mode server: ping 10 # Argument: interval ping-restart 120 # Argument: timeout*2 push "ping 10" # Argument: interval push "ping-restart 60" # Argument: timeout else ping 10 # Argument: interval ping-restart 60 # Argument: timeout
Директива ping n
предписывает пинговать удаленный узел по каналу управления, если пакеты не отправлялись как минимум последние n
секунд. Директиву нужно задавать как на одном, так и на другом конце VPN-туннеля — поскольку ping OpenVPN не отражается эхом.
Директива ping-restart n
в файле конфигурации клиента предписывает подключиться к серверу снова, если прошло n
секунд без получения ping или пакета данных. Для клиента значение по умолчанию равно 120 секунд (если не было получено другое значение с сервера). Директива ping-restart n
в файле конфигурации сервера предписывает отключить этого клиента, если прошло n
секунд без получения ping или пакета данных.
Директива explicit-exit-notify
Директива explicit-exit-notify
предписывает серверу и клиенту уведомлять друг друга о завершеннии работы службы OpenVPN. Клиент, при получении такого сообщения — попытается подключиться снова. Сервер, при получении такого сообщения — закроет соединение с этим клиентом. Значение по умолчнию — единица (то есть, уведомления разрешены).
Примеры конфигурации
Пример файла конфигурации сервера в режиме server
с множеством клиентов, TLS (Transport Layer Security), протокол UDP
dev tun proto udp lport 1194 # сертификат Центра Сертификации ca /etc/openvpn/keys/ca.crt # приватный ключ сервера key /etc/openvpn/keys/server.key # сертификат сервера cert /etc/openvpn/keys/server.crt # режим сервер + много клиентов mode server # это сервер при TLS handshake tls-server # топология виртуальной сети topology subnet # ip-адрес и маска сервера ifconfig 10.8.0.1 255.255.255.0 # диапазон адресов для клиентов ifconfig-pool 10.8.0.2 10.8.0.100 # шлюз по умолчанию для сети route-gateway 10.8.0.1 # клиенты видят друг друга client-to-client # сообщить клиентам топологию push "topology subnet" # сообщить клиентам шлюз сети push "route-gateway 10.8.0.1" keepalive 10 60 user nobody group nogroup persist-key persist-tun
Пример файла конфигурации клиента, когда для сервера установлен режим server
, TLS (Transport Layer Security), протокол UDP
dev tun proto udp # сертификат Центра Сертификации ca /etc/openvpn/keys/ca.crt # приватный ключ клиента key /etc/openvpn/keys/client.key # сертификат клиента cert /etc/openvpn/keys/client.crt # принимать от сервера директивы pull # это клиент при TLS handshake tls-client # ip-адрес и порт сервера remote 123.123.123.123 1194 # динамический номер порта nobind user nobody group nogroup persist-key persist-tun
1. OpenVPN, точка-точка, PSK (static key), протокол UDP, порт 1194
Это вариант настройки OpenVPN с использованием static key. Мы даже не будем создавать два файла ключей static.key
, а ограничимся одним. То есть, трафик между клиентом и первым VPN-сервером и трафик между первым VPN-сервером и вторым VPN-сервером будут шифроваться с использованием одного файла static.key
.
Создать ключ можно с помощью команды
# openvpn --genkey secret /etc/openvpn/keys/static.key
# cat /etc/openvpn/keys/static.key
# # 2048 bit OpenVPN static key # -----BEGIN OpenVPN Static key V1----- ae6d0316156ef7ee7afe15448dd95a59 de286c12d4c18fbab8ae3b22f5f8e7c9 27794d3b2a116a35c7eab0716e3c9f03 bf7dd359ccf26983465687ec13c7d05c 86e2318b53e7e7d5c71491b338db0237 e4944e8fbbed421b8b6cabc8318f298c f06f6de53024057792a797e33bb73c57 934dd97ac1f2e8d78ccb84e3749dc3d5 301afa1c4640cf2126b775e4d2af91b2 27267603e59bc8d42ffb65b1c9b83041 f0151531148e65100d48e378c9aa7031 e4993fe2e897c8db3054ae7f29140f17 c98e353cffbd14b6641f4b3af0841707 49088cda08d0c507c99f557c7a611fed 000eaaea8fb32eb25fae7cfd8920a383 cf377b7dce4c0b03c90dac80f6288ba5 -----END OpenVPN Static key V1-----
В файлах конфигурации можно указывать путь к этому файлу или разместить ключ прямо внутри конфигурации
secret /etc/openvpn/keys/static.key 0
<secret> # # 2048 bit OpenVPN static key # -----BEGIN OpenVPN Static key V1----- ae6d0316156ef7ee7afe15448dd95a59 de286c12d4c18fbab8ae3b22f5f8e7c9 27794d3b2a116a35c7eab0716e3c9f03 bf7dd359ccf26983465687ec13c7d05c 86e2318b53e7e7d5c71491b338db0237 e4944e8fbbed421b8b6cabc8318f298c f06f6de53024057792a797e33bb73c57 934dd97ac1f2e8d78ccb84e3749dc3d5 301afa1c4640cf2126b775e4d2af91b2 27267603e59bc8d42ffb65b1c9b83041 f0151531148e65100d48e378c9aa7031 e4993fe2e897c8db3054ae7f29140f17 c98e353cffbd14b6641f4b3af0841707 49088cda08d0c507c99f557c7a611fed 000eaaea8fb32eb25fae7cfd8920a383 cf377b7dce4c0b03c90dac80f6288ba5 -----END OpenVPN Static key V1----- </secret> key-direction 0
Этот ключ нужно скопировать на компьютер VPN-клиента в домашней сети и на два VPN-сервера по пути /etc/openvpn/keys/static.key
.
Сервер за рубежом
Файл конфигурации службы VPN-сервера
# nano /etc/openvpn/server/p2p_psk_udp_1194.conf
dev tun # для протокола UDP опция должна быть на клиенте и на сервере proto udp4 # на каком сетевом интерфейсе принимать соединение от клиента local 222.222.222.222 # номер порта, на котором нужно принимать соединение от клиента lport 1194 # секретный ключ и направление (0 — для сервера, 1 — для клиента) secret /etc/openvpn/keys/static.key 0 # включить поддержку устаревших алгоритмов шифрования данных providers legacy default # режим point-to-point, этот режим используется по умолчанию mode p2p # ip-адрес сервера и клиента в виртуальной приватной сети (VPN) ifconfig 10.201.201.1 10.201.201.2 script-security 2 # выполнить команду или скрипт при запуске устройства tun/tap up /etc/openvpn/server-up.sh # выполнить команду или скрипт при остановке устройства tun/tap down /etc/openvpn/server-dn.sh # выполнить команду из down перед, а не после остановки tun/tap down-pre keepalive 10 60 user nobody group nogroup persist-tun persist-key # логирование нужно только на этапе отладки, потом можно отключить log /var/log/openvpn/openvpn.log verb 3
Скрипты при запуске/остановке службы
# nano /etc/openvpn/server-up.sh
#!/bin/bash
# Разрешаем пакеты между интерфейсами, если это запрещено. При этом
# запоминаем значение, чтобы при остановке службы вернуть как было.
forward=$(cat /proc/sys/net/ipv4/ip_forward)
if [[ $forward == '0' ]]; then
echo '0' > /etc/openvpn/forward.txt
sysctl -w -q net.ipv4.ip_forward=1
else
echo '1' > /etc/openvpn/forward.txt
fi
# Изменяем на DROP политику по умолчанию для цепочки FORWARD. При этом
# запоминаем значение, чтобы при остановке службы вернуть как было.
iptables -L | grep 'Chain FORWARD (policy ACCEPT)'
if [[ $? == 0 ]]; then
echo 'ACCEPT' > /etc/openvpn/policy.txt
iptables -P FORWARD DROP
else
echo 'DROP' > /etc/openvpn/policy.txt
fi
# Разрешаем пакеты между интерфейсами tun0 и eth0 в двух направлениях
iptables -A FORWARD -i tun0 -o eth0 -s 10.201.201.2 -j ACCEPT
iptables -A FORWARD -i eth0 -o tun0 -d 10.201.201.2 -j ACCEPT
# SNAT, чтобы клиент использовал ip-адрес сервера для выхода в интернет
iptables -t nat -A POSTROUTING -o eth0 -s 10.201.201.2 -j MASQUERADE
# chmod +x /etc/openvpn/server-up.sh
# nano /etc/openvpn/server-dn.sh
#!/bin/bash
# Восстанавливаем значение, которое было до момента запуска службы
if [[ -f /etc/openvpn/forward.txt ]]; then
forward=$(cat /etc/openvpn/forward.txt)
if [[ $forward == '0' ]]; then
sysctl -w -q net.ipv4.ip_forward=0
fi
rm /etc/openvpn/forward.txt
else
sysctl -w -q net.ipv4.ip_forward=0
fi
# Восстанавливаем политику, которая была до момента запуска службы
if [[ -f /etc/openvpn/policy.txt ]]; then
policy=$(cat /etc/openvpn/policy.txt)
if [[ $policy == 'ACCEPT' ]]; then
iptables -P FORWARD ACCEPT
fi
rm /etc/openvpn/policy.txt
else
iptables -P FORWARD ACCEPT
fi
# Удаляем правила маршрутизации пакетов, добавленные при запуске службы
iptables -D FORWARD -i tun0 -o eth0 -s 10.201.201.2 -j ACCEPT
iptables -D FORWARD -i eth0 -o tun0 -d 10.201.201.2 -j ACCEPT
iptables -t nat -D POSTROUTING -o eth0 -s 10.201.201.2 -j MASQUERADE
# chmod +x /etc/openvpn/server-dn.sh
Запускаем службу и добавляем в автозагрузку
# systemctl start openvpn-server@p2p_psk_udp_1194.service # systemctl enable openvpn-server@p2p_psk_udp_1194.service
Тут меня поджидала неприятность — скрипт server-dn.sh
почему-то не выполнялся. Оказалось, что проблема — в понижении прав с использованием директив user
и group
. По этой причине команды sysctl
и iptables
не могут быть выполнены. Так что нужно внести изменения в файл конфигурации, чтобы использовать плагин для запуска скрипта server-dn.sh
с правами root
.
script-security 2 # выполнить команду или скрипт при запуске устройства tun/tap up /etc/openvpn/server-up.sh # выполнить команду или скрипт при остановке устройства tun/tap plugin /usr/lib/openvpn/openvpn-plugin-down-root.so /etc/openvpn/server-dn.sh # выполнить команду из down перед, а не после остановки tun/tap down-pre
Сервер в России
1. VPN-сервер (служба)
Файл конфигурации службы VPN-сервера
# nano /etc/openvpn/server/p2p_psk_udp_1194.conf
dev ovpn-server dev-type tun # для протокола UDP опция должна быть на клиенте и на сервере proto udp4 # на каком сетевом интерфейсе принимать соединение от клиента local 111.111.111.111 # номер порта, на котором нужно принимать соединение от клиента lport 1194 # секретный ключ и направление (0 — для сервера, 1 — для клиента) secret /etc/openvpn/keys/static.key 0 # включить поддержку устаревших алгоритмов шифрования данных providers legacy default # режим point-to-point, этот режим используется по умолчанию mode p2p # ip-адрес сервера и клиента в виртуальной приватной сети (VPN) ifconfig 10.101.101.1 10.101.101.2 keepalive 10 60 user nobody group nogroup persist-tun persist-key # логирование нужно только на этапе отладки, потом можно отключить log /var/log/openvpn/server.log verb 3
Запускаем службу и добавляем в автозагрузку
# systemctl start openvpn-server@p2p_psk_udp_1194.service # systemctl enable openvpn-server@p2p_psk_udp_1194.service
2. VPN-клиент (служба)
Файл конфигурации службы VPN-клиента
# nano /etc/openvpn/client/p2p_psk_udp_1194.conf
dev ovpn-client dev-type tun # для протокола UDP опция должна быть на клиенте и на сервере proto udp4 # ip-адрес, порт и протокол сервера для установления соединения remote 222.222.222.222 1194 udp4 # использовать динамический порт для возвращающихся пакетов nobind # секретный ключ и направление (0 — для сервера, 1 — для клиента) secret /etc/openvpn/keys/static.key 1 # включить поддержку устаревших алгоритмов шифрования данных providers legacy default # режим point-to-point, этот режим используется по умолчанию mode p2p # ip-адрес клиента и сервера в виртуальной приватной сети (VPN) ifconfig 10.201.201.2 10.201.201.1 script-security 2 # выполнить эту команду или скрипт при запуске устройства tun/tap up /etc/openvpn/client-up.sh # выполнить команду или скрипт при остановке устройства tun/tap plugin /usr/lib/openvpn/openvpn-plugin-down-root.so /etc/openvpn/client-dn.sh # выполнить команду из down перед, а не после остановки tun/tap down-pre keepalive 10 60 user nobody group nogroup persist-tun persist-key # логирование нужно только на этапе отладки, потом можно отключить log /var/log/openvpn/client.log verb 3
Скрипты при запуске/остановке службы
# nano /etc/openvpn/client-up.sh
#!/bin/bash
# Разрешаем пакеты между интерфейсами, если это запрещено. При этом
# запоминаем значение, чтобы при остановке службы вернуть как было.
forward=$(cat /proc/sys/net/ipv4/ip_forward)
if [[ $forward == '0' ]]; then
echo '0' > /etc/openvpn/forward.txt
sysctl -w -q net.ipv4.ip_forward=1
else
echo '1' > /etc/openvpn/forward.txt
fi
# Изменяем на DROP политику по умолчанию для цепочки FORWARD. При этом
# запоминаем значение, чтобы при остановке службы вернуть как было.
iptables -L | grep 'Chain FORWARD (policy ACCEPT)'
if [[ $? == 0 ]]; then
echo 'ACCEPT' > /etc/openvpn/policy.txt
iptables -P FORWARD DROP
else
echo 'DROP' > /etc/openvpn/policy.txt
fi
# Разрешаем пакеты между интерфейсами ovpn-client и ovpn-server туда-обратно
iptables -A FORWARD -i ovpn-server -o ovpn-client -s 10.101.101.2 -j ACCEPT
iptables -A FORWARD -i ovpn-client -o ovpn-server -d 10.101.101.2 -j ACCEPT
# SNAT, чтобы все пакеты, которые уходят с интерфейса ovpn-client в туннель в
# направлении сервера за рубежом, имели ip-адрес источника, как у ovpn-client
iptables -t nat -A POSTROUTING -s 10.101.101.2 -o ovpn-client -j MASQUERADE
# Для пакетов с адреса 10.101.101.2 — создаем отдельную таблицу маршрутизации
ip rule add from 10.101.101.2 table 151
# Чтобы работал ping от клиента в домашней сети, нужно чтобы ответы уходили
# через сетевой интерфейс ovpn-server, иначе они будут уходить по дефолтному
# маршруту, то есть через интерфейс ovpn-client (см.ниже)
ip route add 10.101.101.2 dev ovpn-server table 151
# Пакеты с адреса 10.101.101.2 — будут уходить через интерфейс ovpn-client
ip route add default dev ovpn-client table 151
# chmod +x /etc/openvpn/client-up.sh
FORWARD
была ACCEPT
, то она изменяется на DROP
. Но в общем случае, политику ACCEPT
использовать нежелательно, более правильно использовать политику DROP
. Проходят только те пакеты, для которых нашлось правило -j ACCEPT
, остальные пакеты отбрасываются. Политика по умолчанию ACCEPT
подразумевает, что лишние пакеты нужно отбрасывать с помощью правил -j DROP
— а это значительно труднее.
# nano /etc/openvpn/client-dn.sh
#!/bin/bash
# Восстанавливаем значение, которое было до момента запуска службы
if [[ -f /etc/openvpn/forward.txt ]]; then
forward=$(cat /etc/openvpn/forward.txt)
if [[ $forward == '0' ]]; then
sysctl -w -q net.ipv4.ip_forward=0
fi
rm /etc/openvpn/forward.txt
else
sysctl -w -q net.ipv4.ip_forward=0
fi
# Восстанавливаем политику, которая была до момента запуска службы
if [[ -f /etc/openvpn/policy.txt ]]; then
policy=$(cat /etc/openvpn/policy.txt)
if [[ $policy == 'ACCEPT' ]]; then
iptables -P FORWARD ACCEPT
fi
rm /etc/openvpn/policy.txt
else
iptables -P FORWARD ACCEPT
fi
# Удаляем правила маршрутизации пакетов, добавленные при запуске службы
iptables -D FORWARD -i ovpn-server -o ovpn-client -s 10.101.101.2 -j ACCEPT
iptables -D FORWARD -i ovpn-client -o ovpn-server -d 10.101.101.2 -j ACCEPT
iptables -t nat -D POSTROUTING -s 10.101.101.2 -o ovpn-client -j MASQUERADE
ip rule del from 10.101.101.2 table 151
ip route del 10.101.101.2 dev ovpn-server table 151
ip route del default dev ovpn-client table 151
# chmod +x /etc/openvpn/client-dn.sh
Служба VPN-клиента зависит от службы VPN-сервера — скрипт client-up.sh
ожидает, что сетевой интерфейс ovpn-server
будет существовать и может быть использован в команде iptables
. Это значит, что мы должны обеспечить правильный порядок запуска двух служб — сначала VPN-сервер, потом VPN-клиент.
# cp /usr/lib/systemd/system/openvpn-client@.service /etc/systemd/system # nano /etc/systemd/system/openvpn-client@.service
[Unit] Description=OpenVPN tunnel for %I After=network-online.target Wants=network-online.target # служба VPN-клиента будет запущена после службы VPN-сервера Requires=openvpn-server@p2p_psk_udp_1194.service After=openvpn-server@p2p_psk_udp_1194.service
# systemctl daemon-reload
Запускаем службу и добавляем в автозагрузку
# systemctl start openvpn-client@p2p_psk_udp_1194.service # systemctl enable openvpn-client@p2p_psk_udp_1194.service
Смотрим сетевые интерфейсы и ip-адреса
# ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 9a:90:05:dd:ca:f0 brd ff:ff:ff:ff:ff:ff inet 111.111.111.111/24 metric 100 brd 111.111.111.255 scope global dynamic eth0 valid_lft 85840sec preferred_lft 85840sec .......... 3: ovpn-server: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 500 link/none inet 10.101.101.1 peer 10.101.101.2/32 scope global ovpn-server valid_lft forever preferred_lft forever .......... 4: ovpn-client: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 500 link/none inet 10.201.201.2 peer 10.201.201.1/32 scope global ovpn-client valid_lft forever preferred_lft forever ..........
Клиент в домашней сети
Файл конфигурации службы VPN-клиента
# nano /etc/openvpn/client/p2p_psk_udp_1194.conf
dev tun # для протокола UDP опция должна быть на клиенте и на сервере proto udp4 # ip-адрес, порт и протокол сервера для установления соединения remote 111.111.111.111 1194 udp4 # использовать динамический порт для возвращающихся пакетов nobind # секретный ключ и направление (0 — для сервера, 1 — для клиента) secret /etc/openvpn/keys/static.key 1 # включить поддержку устаревших алгоритмов шифрования данных providers legacy default # режим point-to-point, этот режим используется по умолчанию mode p2p # ip-адрес клиента и сервера в виртуальной приватной сети (VPN) ifconfig 10.101.101.2 10.101.101.1 # использовать VPN-туннель для маршрутизации всего трафика redirect-gateway def1 bypass-dhcp # использовать DNS-сервера 208.67.220.220 и 208.67.222.222 dhcp-option DNS 208.67.220.220 dhcp-option DNS 208.67.222.222 # все DNS-запросы отправлять в туннель для избежания утечки dhcp-option DOMAIN-ROUTE . # следующие четыре директивы нужны для изменения используемых # DNS-серверов на клиенте при запуске/остановке службы script-security 2 # выполнить команду или скрипт при запуске устройства tun/tap up /etc/openvpn/update-systemd-resolved # выполнить команду или скрипт при остановке устройства tun/tap down /etc/openvpn/update-systemd-resolved # выполнить команду из down перед, а не после остановки tun/tap down-pre keepalive 10 60 user nobody group nogroup persist-tun persist-key # логирование нужно только на этапе отладки, потом можно отключить log /var/log/openvpn/openvpn.log verb 3
Чтобы получить скрипт /etc/openvpn/update-systemd-resolved
— нужно установить пакет openvpn-systemd-resolved
# apt install openvpn-systemd-resolved
Запускаем службу и добавляем в автозагрузку
# systemctl start openvpn-client@p2p_psk_udp_1194.service # systemctl enable openvpn-client@p2p_psk_udp_1194.service
2. OpenVPN, точка-точка, PSK (static key), протокол TCP, порт 1234
Здесь есть только два отличия от первого варианта настройки двойного VPN — протокол TCP вместо UDP + порт 1234 вместо 1194. Трафик между клиентом и первым VPN-сервером и трафик между первым VPN-сервером и вторым VPN-сервером будут шифроваться с использованием одного файла static.key
.
Сервер за рубежом
Файл конфигурации службы VPN-сервера
# nano /etc/openvpn/server/p2p_psk_tcp_1234.conf
dev tun # для протокола TCP для сервера опция имеет значение tcp-server proto tcp4-server # секретный ключ и направление (0 — для сервера, 1 — для клиента) secret /etc/openvpn/keys/static.key 0 # включить поддержку устаревших алгоритмов шифрования данных providers legacy default # на каком сетевом интерфейсе принимать соединение от клиента local 222.222.222.222 # номер порта, на котором нужно принимать соединение от клиента lport 1234 # режим point-to-point, этот режим используется по умолчанию mode p2p # ip-адрес сервера и клиента в виртуальной приватной сети (VPN) ifconfig 10.202.202.1 10.202.202.2 script-security 2 # выполнить команду или скрипт при запуске устройства tun/tap up /etc/openvpn/server-up.sh # выполнить команду или скрипт при остановке устройства tun/tap plugin /usr/lib/openvpn/openvpn-plugin-down-root.so /etc/openvpn/server-dn.sh # выполнить команду из down перед, а не после остановки tun/tap down-pre keepalive 10 60 user nobody group nogroup persist-tun persist-key # логирование нужно только на этапе отладки, потом можно отключить log /var/log/openvpn/openvpn.log verb 3
Скрипты при запуске/остановке службы
# nano /etc/openvpn/server-up.sh
#!/bin/bash
# Разрешаем пакеты между интерфейсами, если это запрещено. При этом
# запоминаем значение, чтобы при остановке службы вернуть как было.
forward=$(cat /proc/sys/net/ipv4/ip_forward)
if [[ $forward == '0' ]]; then
echo '0' > /etc/openvpn/forward.txt
sysctl -w -q net.ipv4.ip_forward=1
else
echo '1' > /etc/openvpn/forward.txt
fi
# Изменяем на DROP политику по умолчанию для цепочки FORWARD. При этом
# запоминаем значение, чтобы при остановке службы вернуть как было.
iptables -L | grep 'Chain FORWARD (policy ACCEPT)'
if [[ $? == 0 ]]; then
echo 'ACCEPT' > /etc/openvpn/policy.txt
iptables -P FORWARD DROP
else
echo 'DROP' > /etc/openvpn/policy.txt
fi
# Разрешаем пакеты между интерфейсами tun0 и eth0 в двух направлениях
iptables -A FORWARD -i tun0 -o eth0 -s 10.202.202.2 -j ACCEPT
iptables -A FORWARD -i eth0 -o tun0 -d 10.202.202.2 -j ACCEPT
# SNAT, чтобы клиент использовал ip-адрес сервера для выхода в интернет
iptables -t nat -A POSTROUTING -o eth0 -s 10.202.202.2 -j MASQUERADE
# chmod +x /etc/openvpn/server-up.sh
# nano /etc/openvpn/server-dn.sh
#!/bin/bash
# Восстанавливаем значение, которое было до момента запуска службы
if [[ -f /etc/openvpn/forward.txt ]]; then
forward=$(cat /etc/openvpn/forward.txt)
if [[ $forward == '0' ]]; then
sysctl -w -q net.ipv4.ip_forward=0
fi
rm /etc/openvpn/forward.txt
else
sysctl -w -q net.ipv4.ip_forward=0
fi
# Восстанавливаем политику, которая была до момента запуска службы
if [[ -f /etc/openvpn/policy.txt ]]; then
policy=$(cat /etc/openvpn/policy.txt)
if [[ $policy == 'ACCEPT' ]]; then
iptables -P FORWARD ACCEPT
fi
rm /etc/openvpn/policy.txt
else
iptables -P FORWARD ACCEPT
fi
# Удаляем правила маршрутизации пакетов, добавленные при запуске службы
iptables -D FORWARD -i tun0 -o eth0 -s 10.202.202.2 -j ACCEPT
iptables -D FORWARD -i eth0 -o tun0 -d 10.202.202.2 -j ACCEPT
iptables -t nat -D POSTROUTING -o eth0 -s 10.202.202.2 -j MASQUERADE
# chmod +x /etc/openvpn/server-dn.sh
Запускаем две службы и добавляем в автозагрузку
# systemctl start openvpn-server@p2p_psk_tcp_1234.service # systemctl enable openvpn-server@p2p_psk_tcp_1234.service
Сервер в России
На сервере будут работать две службы — VPN-сервера и VPN-клиента.
1. VPN-сервер (служба)
Файл конфигурации службы VPN-сервера
# nano /etc/openvpn/server/p2p_psk_tcp_1234.conf
dev ovpn-server dev-type tun # для протокола TCP для сервера опция имеет значение tcp-server proto tcp4-server # на каком сетевом интерфейсе принимать соединение от клиента local 111.111.111.111 # номер порта, на котором нужно принимать соединение от клиента lport 1234 # секретный ключ и направление (0 — для сервера, 1 — для клиента) secret /etc/openvpn/keys/static.key 0 # включить поддержку устаревших алгоритмов шифрования данных providers legacy default # режим point-to-point, этот режим используется по умолчанию mode p2p # ip-адрес сервера и клиента в виртуальной приватной сети (VPN) ifconfig 10.102.102.1 10.102.102.2 keepalive 10 60 user nobody group nogroup persist-tun persist-key # логирование нужно только на этапе отладки, потом можно отключить log /var/log/openvpn/server.log verb 3
Запускаем службу и добавляем в автозагрузку
# systemctl start openvpn-server@p2p_psk_tcp_1234.service # systemctl enable openvpn-server@p2p_psk_tcp_1234.service
2. VPN-клиент (служба)
Файл конфигурации службы VPN-клиента
# nano /etc/openvpn/client/p2p_psk_tcp_1234.conf
dev ovpn-client dev-type tun # для протокола TCP для клиента опция имеет значение tcp-client proto tcp4-client # ip-адрес, порт и протокол сервера для установления соединения remote 222.222.222.222 1234 tcp4-client # использовать динамический порт для возвращающихся пакетов nobind # секретный ключ и направление (0 — для сервера, 1 — для клиента) secret /etc/openvpn/keys/static.key 1 # включить поддержку устаревших алгоритмов шифрования данных providers legacy default # режим point-to-point, этот режим используется по умолчанию mode p2p # ip-адрес клиента и сервера в виртуальной приватной сети (VPN) ifconfig 10.202.202.2 10.202.202.1 script-security 2 # выполнить эту команду или скрипт при запуске устройства tun/tap up /etc/openvpn/client-up.sh # выполнить команду или скрипт при остановке устройства tun/tap plugin /usr/lib/openvpn/openvpn-plugin-down-root.so /etc/openvpn/client-dn.sh # выполнить команду из down перед, а не после остановки tun/tap down-pre keepalive 10 60 user nobody group nogroup persist-tun persist-key # логирование нужно только на этапе отладки, потом можно отключить log /var/log/openvpn/client.log verb 3
Скрипты при запуске/остановке службы
# nano /etc/openvpn/client-up.sh
#!/bin/bash
# Разрешаем пакеты между интерфейсами, если это запрещено. При этом
# запоминаем значение, чтобы при остановке службы вернуть как было.
forward=$(cat /proc/sys/net/ipv4/ip_forward)
if [[ $forward == '0' ]]; then
echo '0' > /etc/openvpn/forward.txt
sysctl -w -q net.ipv4.ip_forward=1
else
echo '1' > /etc/openvpn/forward.txt
fi
# Изменяем на DROP политику по умолчанию для цепочки FORWARD. При этом
# запоминаем значение, чтобы при остановке службы вернуть как было.
iptables -L | grep 'Chain FORWARD (policy ACCEPT)'
if [[ $? == 0 ]]; then
echo 'ACCEPT' > /etc/openvpn/policy.txt
iptables -P FORWARD DROP
else
echo 'DROP' > /etc/openvpn/policy.txt
fi
# Разрешаем пакеты между интерфейсами ovpn-client и ovpn-server туда-обратно
iptables -A FORWARD -i ovpn-server -o ovpn-client -s 10.102.102.2 -j ACCEPT
iptables -A FORWARD -i ovpn-client -o ovpn-server -d 10.102.102.2 -j ACCEPT
# SNAT, чтобы все пакеты, которые уходят с интерфейса ovpn-client в туннель в
# направлении сервера за рубежом, имели ip-адрес источника, как у ovpn-client
iptables -t nat -A POSTROUTING -s 10.102.102.2 -o ovpn-client -j MASQUERADE
# Для пакетов с адреса 10.102.102.2 — создаем отдельную таблицу маршрутизации
ip rule add from 10.102.102.2 table 152
# Чтобы работал ping от клиента в домашней сети, нужно чтобы ответы уходили
# через сетевой интерфейс ovpn-server, иначе они будут уходить по дефолтному
# маршруту, то есть через интерфейс ovpn-client (см.ниже)
ip route add 10.102.102.2 dev ovpn-server table 152
# Пакеты с адреса 10.102.102.2 — будут уходить через интерфейс ovpn-client
ip route add default dev ovpn-client table 152
# chmod +x /etc/openvpn/client-up.sh
# nano /etc/openvpn/client-dn.sh
#!/bin/bash
# Восстанавливаем значение, которое было до момента запуска службы
if [[ -f /etc/openvpn/forward.txt ]]; then
forward=$(cat /etc/openvpn/forward.txt)
if [[ $forward == '0' ]]; then
sysctl -w -q net.ipv4.ip_forward=0
fi
rm /etc/openvpn/forward.txt
else
sysctl -w -q net.ipv4.ip_forward=0
fi
# Восстанавливаем политику, которая была до момента запуска службы
if [[ -f /etc/openvpn/policy.txt ]]; then
policy=$(cat /etc/openvpn/policy.txt)
if [[ $policy == 'ACCEPT' ]]; then
iptables -P FORWARD ACCEPT
fi
rm /etc/openvpn/policy.txt
else
iptables -P FORWARD ACCEPT
fi
# Удаляем правила маршрутизации пакетов, добавленные при запуске службы
iptables -D FORWARD -i ovpn-server -o ovpn-client -s 10.102.102.2 -j ACCEPT
iptables -D FORWARD -i ovpn-client -o ovpn-server -d 10.102.102.2 -j ACCEPT
iptables -t nat -D POSTROUTING -s 10.102.102.2 -o ovpn-client -j MASQUERADE
ip rule del from 10.102.102.2 table 152
ip route del 10.102.102.2 dev ovpn-server table 152
ip route del default dev ovpn-client table 152
# chmod +x /etc/openvpn/client-dn.sh
Служба VPN-клиента зависит от службы VPN-сервера — скрипт client-up.sh
ожидает, что сетевой интерфейс ovpn-server
будет существовать и может быть использован в команде iptables
. Это значит, что мы должны обеспечить правильный порядок запуска двух служб — сначала VPN-сервер, потом VPN-клиент.
# cp /usr/lib/systemd/system/openvpn-client@.service /etc/systemd/system # nano /etc/systemd/system/openvpn-client@.service
[Unit] Description=OpenVPN tunnel for %I After=network-online.target Wants=network-online.target # служба VPN-клиента будет запущена после службы VPN-сервера Requires=openvpn-server@p2p_psk_tcp_1234.service After=openvpn-server@p2p_psk_tcp_1234.service
# systemctl daemon-reload
Запускаем службу и добавляем в автозагрузку
# systemctl start openvpn-client@p2p_psk_tcp_1234.service # systemctl enable openvpn-client@p2p_psk_tcp_1234.service
Клиент в домашней сети
Файл конфигурации службы VPN-клиента
# nano /etc/openvpn/client/p2p_psk_tcp_1234.conf
dev tun # для протокола TCP для клиента опция имеет значение tcp-client proto tcp4-client # ip-адрес, порт и протокол сервера для установления соединения remote 111.111.111.111 1234 tcp4-client # использовать динамический порт для возвращающихся пакетов nobind # секретный ключ и направление (0 — для сервера, 1 — для клиента) secret /etc/openvpn/keys/static.key 1 # включить поддержку устаревших алгоритмов шифрования данных providers legacy default # режим point-to-point, этот режим используется по умолчанию mode p2p # ip-адрес клиента и сервера в виртуальной приватной сети (VPN) ifconfig 10.102.102.2 10.102.102.1 # использовать VPN-туннель для маршрутизации всего трафика redirect-gateway def1 bypass-dhcp # использовать DNS-сервера 208.67.220.220 и 208.67.222.222 dhcp-option DNS 208.67.220.220 dhcp-option DNS 208.67.222.222 # все DNS-запросы отправлять в туннель для избежания утечки dhcp-option DOMAIN-ROUTE . # следующие четыре директивы нужны для изменения используемых # DNS-серверов на клиенте при запуске/остановки службы script-security 2 # выполнить команду или скрипт при запуске устройства tun/tap up /etc/openvpn/update-systemd-resolved # выполнить команду или скрипт при остановке устройства tun/tap down /etc/openvpn/update-systemd-resolved # выполнить команду из down перед, а не после остановки tun/tap down-pre keepalive 10 60 user nobody group nogroup persist-tun persist-key # логирование нужно только на этапе отладки, потом можно отключить log /var/log/openvpn/openvpn.log verb 3
Чтобы получить скрипт /etc/openvpn/update-systemd-resolved
— нужно установить пакет openvpn-systemd-resolved
# apt install openvpn-systemd-resolved
Запускаем службу и добавляем в автозагрузку
# systemctl start openvpn-client@p2p_psk_tcp_1234.service # systemctl enable openvpn-client@p2p_psk_tcp_1234.service
3. OpenVPN, точка-точка, TLS (finger print), протокол UDP, порт 1194
Традиционная настройка OpenVPN с использованием TLS (Transport Layer Security) подразумевает использование Центра Сертификации (CA). Вначале устанавливается TLS соединение с аутентификацией обеих сторон по сертификатам, через которое производится обмен открытыми ключами. Каждая сторона генерирует общие симметричные ключи и трафик внутри VPN шифруется уже этими ключами так же, как в режиме PSK. Сертификат сервера и сертификат клиента подписаны Центром Сертификации, которому доверяют обе стороны.
TLS также допускают более простой режим, в котором вместо проверки сертификатов с использованием Центра сертификации (CA), сам сертификат хэшируется и сравнивается с заранее известным набором приемлемых хэшей. Это обычно называется проверкой отпечатков пальцев (finger print). В этом случае не требуется подписывать сертификаты сервера и клиента в Центре Сертификации. Потому как в файле конфигурации сервера и клиентов есть отпечатки сертфикатов, которым можно доверять.
Директива secret
была объявлена deprecated
в OpenVPN 2.6 и будет удалена в OpenVPN 2.7. Использование static key больше не является достаточно безопасным для современных условий. Вместо static key рекомендуется использовать режим TLS. Директива peer-fingerprint
делает настройку режима TLS такой же простой, как и при использовании директивы secret
.
У нас два VPN-туннеля — между сервером за рубежом и сервером в России + между сервером в России и клиентом в домашней сети. Другими словами — два VPN-сервера и два VPN-клиента. Соответственно, нам нужны — ключ и сертификат сервера для 222.222.222.222
, ключ и сертификат клиента для 111.111.111.111
, ключ и сертификат сервера для 111.111.111.111
, ключ и сертификат клиента в домашней сети.
Но мы можем немного облегчить себе жизнь, если будем использовать одну пару ключ-сертификат сервера + одну пару ключ-сертификат клиента — как уже использовали один файл static.key
.
Создаем ключ и сертификат для сервера — файлы server.key
и server.crt
. Эти ключ и сертификат копируем на сервер 222.222.222.222
и на сервер 111.111.111.111
— в директорию /etc/openvpn/keys
.
# openssl req -x509 \ > -newkey ec:<(openssl ecparam -name secp384r1) \ > -keyout server.key \ > -out server.crt \ > -nodes \ > -sha256 \ > -days 3650 \ > -subj '/CN=server'
Создаем SHA256 отпечаток файла сертификата сервера
# openssl x509 -fingerprint -sha256 -in server.crt -noout sha256 Fingerprint=D4:0A:C6:1C:70:7C:83:71:59:48:C4:DC:AB:F3:CE:28:9F:36:56:99:01:94:AD:67:A3:2A:F9:E5:3A:1F:CB:6A
Создаем ключ и сертификат для клиента — файлы client.key
и client.crt
. Эти ключ и сертификат копируем на сервер 111.111.111.111
и на машину клиента в домашней сети — в директорию /etc/openvpn/keys
.
# openssl req -x509 \ > -newkey ec:<(openssl ecparam -name secp384r1) \ > -keyout client.key \ > -out client.crt \ > -nodes \ > -sha256 \ > -days 3650 \ > -subj '/CN=client'
Создаем SHA256 отпечаток файла сертификата клиента
# openssl x509 -fingerprint -sha256 -in client.crt -noout sha256 Fingerprint=68:AA:B5:98:F2:DB:5F:E7:48:07:DB:E7:EF:99:9A:F2:0D:D9:6B:B4:0D:39:36:C2:A2:3C:5D:DA:07:39:00:61
Сервер за рубежом
Файл конфигурации службы VPN-сервера
# nano /etc/openvpn/server/p2p_tls_udp_1194.conf
dev tun # для протокола UDP опция должна быть на клиенте и на сервере proto udp4 # на каком сетевом интерфейсе принимать соединение от клиента local 222.222.222.222 # номер порта, на котором нужно принимать соединение от клиента lport 1194 # эта конечная точка будет представляться сервером при handshake tls-server # файлы ключа и сертификата сервера server.key и server.crt key /etc/openvpn/keys/server.key cert /etc/openvpn/keys/server.crt # отпечатки пальцев клиентов, у нас сейчас только один клиент <peer-fingerprint> 68:AA:B5:98:F2:DB:5F:E7:48:07:DB:E7:EF:99:9A:F2:0D:D9:6B:B4:0D:39:36:C2:A2:3C:5D:DA:07:39:00:61 </peer-fingerprint> # не использовать файл Diffie-Hellman, а использовать протокол # на элиптических кривых ECDH (Elliptic curve Diffie-Hellman) dh none # режим point-to-point (p2p), этот режим используется по умолчанию mode p2p # ip-адрес сервера и клиента в виртуальной приватной сети (VPN) ifconfig 10.203.203.1 10.203.203.2 script-security 2 # выполнить команду или скрипт при запуске устройства tun/tap up /etc/openvpn/server-up.sh # выполнить команду или скрипт при остановке устройства tun/tap plugin /usr/lib/openvpn/openvpn-plugin-down-root.so /etc/openvpn/server-dn.sh # выполнить команду из down перед, а не после остановки tun/tap down-pre keepalive 10 60 user nobody group nogroup persist-tun persist-key # логирование нужно только на этапе отладки, потом можно отключить log /var/log/openvpn/openvpn.log verb 3
Скрипты при запуске/остановке службы
# nano /etc/openvpn/server-up.sh
#!/bin/bash
# Разрешаем пакеты между интерфейсами, если это запрещено. При этом
# запоминаем значение, чтобы при остановке службы вернуть как было.
forward=$(cat /proc/sys/net/ipv4/ip_forward)
if [[ $forward == '0' ]]; then
echo '0' > /etc/openvpn/forward.txt
sysctl -w -q net.ipv4.ip_forward=1
else
echo '1' > /etc/openvpn/forward.txt
fi
# Изменяем на DROP политику по умолчанию для цепочки FORWARD. При этом
# запоминаем значение, чтобы при остановке службы вернуть как было.
iptables -L | grep 'Chain FORWARD (policy ACCEPT)'
if [[ $? == 0 ]]; then
echo 'ACCEPT' > /etc/openvpn/policy.txt
iptables -P FORWARD DROP
else
echo 'DROP' > /etc/openvpn/policy.txt
fi
# Разрешаем пакеты между интерфейсами tun0 и eth0 в двух направлениях
iptables -A FORWARD -i tun0 -o eth0 -s 10.203.203.2 -j ACCEPT
iptables -A FORWARD -i eth0 -o tun0 -d 10.203.203.2 -j ACCEPT
# SNAT, чтобы клиент использовал ip-адрес сервера для выхода в интернет
iptables -t nat -A POSTROUTING -o eth0 -s 10.203.203.2 -j MASQUERADE
# chmod +x /etc/openvpn/server-up.sh
# nano /etc/openvpn/server-dn.sh
#!/bin/bash
# Восстанавливаем значение, которое было до момента запуска службы
if [[ -f /etc/openvpn/forward.txt ]]; then
forward=$(cat /etc/openvpn/forward.txt)
if [[ $forward == '0' ]]; then
sysctl -w -q net.ipv4.ip_forward=0
fi
rm /etc/openvpn/forward.txt
else
sysctl -w -q net.ipv4.ip_forward=0
fi
# Восстанавливаем политику, которая была до момента запуска службы
if [[ -f /etc/openvpn/policy.txt ]]; then
policy=$(cat /etc/openvpn/policy.txt)
if [[ $policy == 'ACCEPT' ]]; then
iptables -P FORWARD ACCEPT
fi
rm /etc/openvpn/policy.txt
else
iptables -P FORWARD ACCEPT
fi
# Удаляем правила маршрутизации пакетов, добавленные при запуске службы
iptables -D FORWARD -i tun0 -o eth0 -s 10.203.203.2 -j ACCEPT
iptables -D FORWARD -i eth0 -o tun0 -d 10.203.203.2 -j ACCEPT
iptables -t nat -D POSTROUTING -o eth0 -s 10.203.203.2 -j MASQUERADE
# chmod +x /etc/openvpn/server-dn.sh
Запускаем службу и добавляем в автозагрузку
# systemctl start openvpn-server@p2p_tls_udp_1194.service # systemctl enable openvpn-server@p2p_tls_udp_1194.service
Сервер в России
На сервере будут работать две службы — VPN-сервера и VPN-клиента.
1. VPN-сервер (служба)
Файл конфигурации службы VPN-сервера
# nano /etc/openvpn/server/p2p_tls_udp_1194.conf
dev ovpn-server dev-type tun # для протокола UDP опция должна быть на клиенте и на сервере proto udp4 # на каком сетевом интерфейсе принимать соединение от клиента local 111.111.111.111 # номер порта, на котором нужно принимать соединение от клиента lport 1194 # эта конечная точка будет представляться сервером при handshake tls-server # файлы ключа и сертификата сервера server.key и server.crt key /etc/openvpn/keys/server.key cert /etc/openvpn/keys/server.crt # отпечатки пальцев клиентов, у нас сейчас только один клиент <peer-fingerprint> 68:AA:B5:98:F2:DB:5F:E7:48:07:DB:E7:EF:99:9A:F2:0D:D9:6B:B4:0D:39:36:C2:A2:3C:5D:DA:07:39:00:61 </peer-fingerprint> # не использовать файл Diffie-Hellman, а использовать протокол # на элиптических кривых ECDH (Elliptic curve Diffie-Hellman) dh none # режим point-to-point (p2p), этот режим используется по умолчанию mode p2p # ip-адрес сервера и клиента в виртуальной приватной сети (VPN) ifconfig 10.103.103.1 10.103.103.2 keepalive 10 60 user nobody group nogroup persist-tun persist-key # логирование нужно только на этапе отладки, потом можно отключить log /var/log/openvpn/server.log verb 3
Запускаем службу и добавляем в автозагрузку
# systemctl start openvpn-server@p2p_tls_udp_1194.service # systemctl enable openvpn-server@p2p_tls_udp_1194.service
2. VPN-клиент (служба)
Файл конфигурации службы VPN-клиента
# nano /etc/openvpn/client/p2p_tls_udp_1194.conf
dev ovpn-client dev-type tun # для протокола UDP опция должна быть на клиенте и на сервере proto udp4 # ip-адрес, порт и протокол сервера для установления соединения remote 222.222.222.222 1194 udp4 # использовать динамический порт для возвращающихся пакетов nobind # эта конечная точка будет представляться клиентом при handshake tls-client # файлы ключа и сертификата клиента client.key и client.crt key /etc/openvpn/keys/client.key cert /etc/openvpn/keys/client.crt # здесь отпечаток сертификата сервера за рубежом 222.222.222.222 peer-fingerprint D4:0A:C6:1C:70:7C:83:71:59:48:C4:DC:AB:F3:CE:28:9F:36:56:99:01:94:AD:67:A3:2A:F9:E5:3A:1F:CB:6A # режим point-to-point, этот режим используется по умолчанию mode p2p # ip-адрес клиента и сервера в виртуальной приватной сети (VPN) ifconfig 10.203.203.2 10.203.203.1 script-security 2 # выполнить эту команду или скрипт при запуске устройства tun/tap up /etc/openvpn/client-up.sh # выполнить команду или скрипт при остановке устройства tun/tap plugin /usr/lib/openvpn/openvpn-plugin-down-root.so /etc/openvpn/client-dn.sh # выполнить команду из down перед, а не после остановки tun/tap down-pre keepalive 10 60 user nobody group nogroup persist-tun persist-key # логирование нужно только на этапе отладки, потом можно отключить log /var/log/openvpn/client.log verb 3
Скрипты при запуске/остановке службы
# nano /etc/openvpn/client-up.sh
#!/bin/bash
# Разрешаем пакеты между интерфейсами, если это запрещено. При этом
# запоминаем значение, чтобы при остановке службы вернуть как было.
forward=$(cat /proc/sys/net/ipv4/ip_forward)
if [[ $forward == '0' ]]; then
echo '0' > /etc/openvpn/forward.txt
sysctl -w -q net.ipv4.ip_forward=1
else
echo '1' > /etc/openvpn/forward.txt
fi
# Изменяем на DROP политику по умолчанию для цепочки FORWARD. При этом
# запоминаем значение, чтобы при остановке службы вернуть как было.
iptables -L | grep 'Chain FORWARD (policy ACCEPT)'
if [[ $? == 0 ]]; then
echo 'ACCEPT' > /etc/openvpn/policy.txt
iptables -P FORWARD DROP
else
echo 'DROP' > /etc/openvpn/policy.txt
fi
# Разрешаем пакеты между интерфейсами ovpn-client и ovpn-server туда-обратно
iptables -A FORWARD -i ovpn-server -o ovpn-client -s 10.103.103.2 -j ACCEPT
iptables -A FORWARD -i ovpn-client -o ovpn-server -d 10.103.103.2 -j ACCEPT
# SNAT, чтобы все пакеты, которые уходят с интерфейса ovpn-client в туннель в
# направлении сервера за рубежом, имели ip-адрес источника, как у ovpn-client
iptables -t nat -A POSTROUTING -s 10.103.103.2 -o ovpn-client -j MASQUERADE
# Для пакетов с адреса 10.103.103.2 — создаем отдельную таблицу маршрутизации
ip rule add from 10.103.103.2 table 153
# Чтобы работал ping от клиента в домашней сети, нужно чтобы ответы уходили
# через сетевой интерфейс ovpn-server, иначе они будут уходить по дефолтному
# маршруту, то есть через интерфейс ovpn-client (см.ниже)
ip route add 10.103.103.2 dev ovpn-server table 153
# Пакеты с адреса 10.103.103.2 — будут уходить через интерфейс ovpn-client
ip route add default dev ovpn-client table 153
# chmod +x /etc/openvpn/client-up.sh
# nano /etc/openvpn/client-dn.sh
#!/bin/bash
# Восстанавливаем значение, которое было до момента запуска службы
if [[ -f /etc/openvpn/forward.txt ]]; then
forward=$(cat /etc/openvpn/forward.txt)
if [[ $forward == '0' ]]; then
sysctl -w -q net.ipv4.ip_forward=0
fi
rm /etc/openvpn/forward.txt
else
sysctl -w -q net.ipv4.ip_forward=0
fi
# Восстанавливаем политику, которая была до момента запуска службы
if [[ -f /etc/openvpn/policy.txt ]]; then
policy=$(cat /etc/openvpn/policy.txt)
if [[ $policy == 'ACCEPT' ]]; then
iptables -P FORWARD ACCEPT
fi
rm /etc/openvpn/policy.txt
else
iptables -P FORWARD ACCEPT
fi
# Удаляем правила маршрутизации пакетов, добавленные при запуске службы
iptables -D FORWARD -i ovpn-server -o ovpn-client -s 10.103.103.2 -j ACCEPT
iptables -D FORWARD -i ovpn-client -o ovpn-server -d 10.103.103.2 -j ACCEPT
iptables -t nat -D POSTROUTING -s 10.103.103.2 -o ovpn-client -j MASQUERADE
ip rule del from 10.103.103.2 table 153
ip route del 10.103.103.2 dev ovpn-server table 153
ip route del default dev ovpn-client table 153
# chmod +x /etc/openvpn/client-dn.sh
Служба VPN-клиента зависит от службы VPN-сервера — скрипт client-up.sh
ожидает, что сетевой интерфейс ovpn-server
будет существовать и может быть использован в команде iptables
. Это значит, что мы должны обеспечить правильный порядок запуска двух служб — сначала VPN-сервер, потом VPN-клиент.
# cp /usr/lib/systemd/system/openvpn-client@.service /etc/systemd/system # nano /etc/systemd/system/openvpn-client@.service
[Unit] Description=OpenVPN tunnel for %I After=network-online.target Wants=network-online.target # служба VPN-клиента будет запущена после службы VPN-сервера Requires=openvpn-server@p2p_tls_udp_1194.service After=openvpn-server@p2p_tls_udp_1194.service
# systemctl daemon-reload
Запускаем службу и добавляем в автозагрузку
# systemctl start openvpn-client@p2p_tls_udp_1194.service # systemctl enable openvpn-client@p2p_tls_udp_1194.service
Клиент в домашней сети
Файл конфигурации службы VPN-клиента
# nano /etc/openvpn/client/p2p_tls_udp_1194.conf
dev tun # для протокола UDP опция должна быть на клиенте и на сервере proto udp4 # ip-адрес, порт и протокол сервера для установления соединения remote 111.111.111.111 1194 udp4 # использовать динамический порт для возвращающихся пакетов nobind # эта конечная точка будет представляться клиентом при handshake tls-client # файлы ключа и сертификата клиента client.key и client.crt key /etc/openvpn/keys/client.key cert /etc/openvpn/keys/client.crt # здесь отпечаток сертификата сервера в России 111.111.111.111 peer-fingerprint D4:0A:C6:1C:70:7C:83:71:59:48:C4:DC:AB:F3:CE:28:9F:36:56:99:01:94:AD:67:A3:2A:F9:E5:3A:1F:CB:6A # режим point-to-point, этот режим используется по умолчанию mode p2p # ip-адрес клиента и сервера в виртуальной приватной сети (VPN) ifconfig 10.103.103.2 10.103.103.1 # использовать VPN-туннель для маршрутизации всего трафика redirect-gateway def1 bypass-dhcp # использовать DNS-сервера 208.67.220.220 и 208.67.222.222 dhcp-option DNS 208.67.220.220 dhcp-option DNS 208.67.222.222 # все DNS-запросы отправлять в туннель для избежания утечки dhcp-option DOMAIN-ROUTE . # следующие четыре директивы нужны для изменения используемых # DNS-серверов на клиенте при запуске/остановки службы script-security 2 # выполнить команду или скрипт при запуске устройства tun/tap up /etc/openvpn/update-systemd-resolved # выполнить команду или скрипт при остановке устройства tun/tap down /etc/openvpn/update-systemd-resolved # выполнить команду из down перед, а не после остановки tun/tap down-pre keepalive 10 60 user nobody group nogroup persist-tun persist-key # логирование нужно только на этапе отладки, потом можно отключить log /var/log/openvpn/openvpn.log verb 3
Чтобы получить скрипт /etc/openvpn/update-systemd-resolved
— нужно установить пакет openvpn-systemd-resolved
# apt install openvpn-systemd-resolved
Запускаем службу и добавляем в автозагрузку
# systemctl start openvpn-client@p2p_tls_udp_1194.service # systemctl enable openvpn-client@p2p_tls_udp_1194.service
4. OpenVPN, точка-точка, TLS (finger print), протокол TCP, порт 1234
Здесь есть только два отличия от предыдущего варианта настройки двойного VPN — использование протокола TCP вместо UDP + порт 1234 вместо 1194.
Сервер за рубежом
Файл конфигурации службы VPN-сервера
# nano /etc/openvpn/server/p2p_tls_tcp_1234.conf
dev tun # для протокола TCP для сервера опция имеет значение tcp-server proto tcp4-server # на каком сетевом интерфейсе принимать соединение от клиента local 222.222.222.222 # номер порта, на котором нужно принимать соединение от клиента lport 1234 # эта конечная точка будет представляться сервером при handshake tls-server # файлы ключа и сертификата сервера server.key и server.crt key /etc/openvpn/keys/server.key cert /etc/openvpn/keys/server.crt # отпечатки пальцев клиентов, у нас сейчас только один клиент <peer-fingerprint> 68:AA:B5:98:F2:DB:5F:E7:48:07:DB:E7:EF:99:9A:F2:0D:D9:6B:B4:0D:39:36:C2:A2:3C:5D:DA:07:39:00:61 </peer-fingerprint> # не использовать файл Diffie-Hellman, а использовать протокол # на элиптических кривых ECDH (Elliptic curve Diffie-Hellman) dh none # режим point-to-point (p2p), этот режим используется по умолчанию mode p2p # ip-адрес сервера и клиента в виртуальной приватной сети (VPN) ifconfig 10.204.204.1 10.204.204.2 script-security 2 # выполнить команду или скрипт при запуске устройства tun/tap up /etc/openvpn/server-up.sh # выполнить команду или скрипт при остановке устройства tun/tap plugin /usr/lib/openvpn/openvpn-plugin-down-root.so /etc/openvpn/server-dn.sh # выполнить команду из down перед, а не после остановки tun/tap down-pre keepalive 10 60 user nobody group nogroup persist-tun persist-key # логирование нужно только на этапе отладки, потом можно отключить log /var/log/openvpn/openvpn.log verb 3
Скрипты при запуске/остановке службы
# nano /etc/openvpn/server-up.sh
#!/bin/bash
# Разрешаем пакеты между интерфейсами, если это запрещено. При этом
# запоминаем значение, чтобы при остановке службы вернуть как было.
forward=$(cat /proc/sys/net/ipv4/ip_forward)
if [[ $forward == '0' ]]; then
echo '0' > /etc/openvpn/forward.txt
sysctl -w -q net.ipv4.ip_forward=1
else
echo '1' > /etc/openvpn/forward.txt
fi
# Изменяем на DROP политику по умолчанию для цепочки FORWARD. При этом
# запоминаем значение, чтобы при остановке службы вернуть как было.
iptables -L | grep 'Chain FORWARD (policy ACCEPT)'
if [[ $? == 0 ]]; then
echo 'ACCEPT' > /etc/openvpn/policy.txt
iptables -P FORWARD DROP
else
echo 'DROP' > /etc/openvpn/policy.txt
fi
# Разрешаем пакеты между интерфейсами tun0 и eth0 в двух направлениях
iptables -A FORWARD -i tun0 -o eth0 -s 10.204.204.2 -j ACCEPT
iptables -A FORWARD -i eth0 -o tun0 -d 10.204.204.2 -j ACCEPT
# SNAT, чтобы клиент использовал ip-адрес сервера для выхода в интернет
iptables -t nat -A POSTROUTING -o eth0 -s 10.204.204.2 -j MASQUERADE
# chmod +x /etc/openvpn/server-up.sh
# nano /etc/openvpn/server-dn.sh
#!/bin/bash
# Восстанавливаем значение, которое было до момента запуска службы
if [[ -f /etc/openvpn/forward.txt ]]; then
forward=$(cat /etc/openvpn/forward.txt)
if [[ $forward == '0' ]]; then
sysctl -w -q net.ipv4.ip_forward=0
fi
rm /etc/openvpn/forward.txt
else
sysctl -w -q net.ipv4.ip_forward=0
fi
# Восстанавливаем политику, которая была до момента запуска службы
if [[ -f /etc/openvpn/policy.txt ]]; then
policy=$(cat /etc/openvpn/policy.txt)
if [[ $policy == 'ACCEPT' ]]; then
iptables -P FORWARD ACCEPT
fi
rm /etc/openvpn/policy.txt
else
iptables -P FORWARD ACCEPT
fi
# Удаляем правила маршрутизации пакетов, добавленные при запуске службы
iptables -D FORWARD -i tun0 -o eth0 -s 10.204.204.2 -j ACCEPT
iptables -D FORWARD -i eth0 -o tun0 -d 10.204.204.2 -j ACCEPT
iptables -t nat -D POSTROUTING -o eth0 -s 10.204.204.2 -j MASQUERADE
# chmod +x /etc/openvpn/server-dn.sh
Запускаем службу и добавляем в автозагрузку
# systemctl start openvpn-server@p2p_tls_tcp_1234.service # systemctl enable openvpn-server@p2p_tls_tcp_1234.service
Сервер в России
На сервере будут работать две службы — VPN-сервера и VPN-клиента.
1. VPN-сервер (служба)
Файл конфигурации службы VPN-сервера
# nano /etc/openvpn/server/p2p_tls_tcp_1234.conf
dev ovpn-server dev-type tun # для протокола TCP для сервера опция имеет значение tcp-server proto tcp4-server # на каком сетевом интерфейсе принимать соединение от клиента local 111.111.111.111 # номер порта, на котором нужно принимать соединение от клиента lport 1234 # эта конечная точка будет представляться сервером при handshake tls-server # файлы ключа и сертификата сервера server.key и server.crt key /etc/openvpn/keys/server.key cert /etc/openvpn/keys/server.crt # отпечатки пальцев клиентов, у нас сейчас только один клиент <peer-fingerprint> 68:AA:B5:98:F2:DB:5F:E7:48:07:DB:E7:EF:99:9A:F2:0D:D9:6B:B4:0D:39:36:C2:A2:3C:5D:DA:07:39:00:61 </peer-fingerprint> # не использовать файл Diffie-Hellman, а использовать протокол # на элиптических кривых ECDH (Elliptic curve Diffie-Hellman) dh none # режим point-to-point (p2p), этот режим используется по умолчанию mode p2p # ip-адрес сервера и клиента в виртуальной приватной сети (VPN) ifconfig 10.104.104.1 10.104.104.2 keepalive 10 60 user nobody group nogroup persist-tun persist-key # логирование нужно только на этапе отладки, потом можно отключить log /var/log/openvpn/server.log verb 3
Запускаем службу и добавляем в автозагрузку
# systemctl start openvpn-server@p2p_tls_tcp_1234.service # systemctl enable openvpn-server@p2p_tls_tcp_1234.service
2. VPN-клиент (служба)
Файл конфигурации службы VPN-клиента
# nano /etc/openvpn/client/p2p_tls_tcp_1234.conf
dev ovpn-client dev-type tun # для протокола TCP для клиента опция имеет значение tcp-client proto tcp4-client # ip-адрес, порт и протокол сервера для установления соединения remote 222.222.222.222 1234 tcp4-client # использовать динамический порт для возвращающихся пакетов nobind # эта конечная точка будет представляться клиентом при handshake tls-client # файлы ключа и сертификата клиента client.key и client.crt key /etc/openvpn/keys/client.key cert /etc/openvpn/keys/client.crt # здесь отпечаток сертификата сервера за рубежом 222.222.222.222 peer-fingerprint D4:0A:C6:1C:70:7C:83:71:59:48:C4:DC:AB:F3:CE:28:9F:36:56:99:01:94:AD:67:A3:2A:F9:E5:3A:1F:CB:6A # режим point-to-point, этот режим используется по умолчанию mode p2p # ip-адрес клиента и сервера в виртуальной приватной сети (VPN) ifconfig 10.204.204.2 10.204.204.1 script-security 2 # выполнить эту команду или скрипт при запуске устройства tun/tap up /etc/openvpn/client-up.sh # выполнить команду или скрипт при остановке устройства tun/tap plugin /usr/lib/openvpn/openvpn-plugin-down-root.so /etc/openvpn/client-dn.sh # выполнить команду из down перед, а не после остановки tun/tap down-pre keepalive 10 60 user nobody group nogroup persist-tun persist-key # логирование нужно только на этапе отладки, потом можно отключить log /var/log/openvpn/client.log verb 3
Скрипты при запуске/остановке службы
# nano /etc/openvpn/client-up.sh
#!/bin/bash
# Разрешаем пакеты между интерфейсами, если это запрещено. При этом
# запоминаем значение, чтобы при остановке службы вернуть как было.
forward=$(cat /proc/sys/net/ipv4/ip_forward)
if [[ $forward == '0' ]]; then
echo '0' > /etc/openvpn/forward.txt
sysctl -w -q net.ipv4.ip_forward=1
else
echo '1' > /etc/openvpn/forward.txt
fi
# Изменяем на DROP политику по умолчанию для цепочки FORWARD. При этом
# запоминаем значение, чтобы при остановке службы вернуть как было.
iptables -L | grep 'Chain FORWARD (policy ACCEPT)'
if [[ $? == 0 ]]; then
echo 'ACCEPT' > /etc/openvpn/policy.txt
iptables -P FORWARD DROP
else
echo 'DROP' > /etc/openvpn/policy.txt
fi
# Разрешаем пакеты между интерфейсами ovpn-client и ovpn-server туда-обратно
iptables -A FORWARD -i ovpn-server -o ovpn-client -s 10.104.104.2 -j ACCEPT
iptables -A FORWARD -i ovpn-client -o ovpn-server -d 10.104.104.2 -j ACCEPT
# SNAT, чтобы все пакеты, которые уходят с интерфейса ovpn-client в туннель в
# направлении сервера за рубежом, имели ip-адрес источника, как у ovpn-client
iptables -t nat -A POSTROUTING -s 10.104.104.2 -o ovpn-client -j MASQUERADE
# Для пакетов с адреса 10.104.104.2 — создаем отдельную таблицу маршрутизации
ip rule add from 10.104.104.2 table 154
# Чтобы работал ping от клиента в домашней сети, нужно чтобы ответы уходили
# через сетевой интерфейс ovpn-server, иначе они будут уходить по дефолтному
# маршруту, то есть через интерфейс ovpn-client (см.ниже)
ip route add 10.104.104.2 dev ovpn-server table 154
# Пакеты с адреса 10.104.104.2 — будут уходить через интерфейс ovpn-client
ip route add default dev ovpn-client table 154
# chmod +x /etc/openvpn/client-up.sh
# nano /etc/openvpn/client-dn.sh
#!/bin/bash
# Восстанавливаем значение, которое было до момента запуска службы
if [[ -f /etc/openvpn/forward.txt ]]; then
forward=$(cat /etc/openvpn/forward.txt)
if [[ $forward == '0' ]]; then
sysctl -w -q net.ipv4.ip_forward=0
fi
rm /etc/openvpn/forward.txt
else
sysctl -w -q net.ipv4.ip_forward=0
fi
# Восстанавливаем политику, которая была до момента запуска службы
if [[ -f /etc/openvpn/policy.txt ]]; then
policy=$(cat /etc/openvpn/policy.txt)
if [[ $policy == 'ACCEPT' ]]; then
iptables -P FORWARD ACCEPT
fi
rm /etc/openvpn/policy.txt
else
iptables -P FORWARD ACCEPT
fi
# Удаляем правила маршрутизации пакетов, добавленные при запуске службы
iptables -D FORWARD -i ovpn-server -o ovpn-client -s 10.104.104.2 -j ACCEPT
iptables -D FORWARD -i ovpn-client -o ovpn-server -d 10.104.104.2 -j ACCEPT
iptables -t nat -D POSTROUTING -s 10.104.104.2 -o ovpn-client -j MASQUERADE
ip rule del from 10.104.104.2 table 154
ip route del 10.104.104.2 dev ovpn-server table 154
ip route del default dev ovpn-client table 154
# chmod +x /etc/openvpn/client-dn.sh
Служба VPN-клиента зависит от службы VPN-сервера — скрипт client-up.sh
ожидает, что сетевой интерфейс ovpn-server
будет существовать и может быть использован в команде iptables
. Это значит, что мы должны обеспечить правильный порядок запуска двух служб — сначала VPN-сервер, потом VPN-клиент.
# cp /usr/lib/systemd/system/openvpn-client@.service /etc/systemd/system # nano /etc/systemd/system/openvpn-client@.service
[Unit] Description=OpenVPN tunnel for %I After=network-online.target Wants=network-online.target # служба VPN-клиента будет запущена после службы VPN-сервера Requires=openvpn-server@p2p_psk_tcp_1234.service After=openvpn-server@p2p_psk_tcp_1234.service
# systemctl daemon-reload
Запускаем службу и добавляем в автозагрузку
# systemctl start openvpn-client@p2p_psk_tcp_1234.service # systemctl enable openvpn-client@p2p_psk_tcp_1234.service
Клиент в домашней сети
Файл конфигурации службы VPN-клиента
# nano /etc/openvpn/client/p2p_tls_tcp_1234.conf
dev tun # для протокола TCP для клиента опция имеет значение tcp-client proto tcp4-client # ip-адрес, порт и протокол сервера для установления соединения remote 111.111.111.111 1234 tcp4-client # использовать динамический порт для возвращающихся пакетов nobind # эта конечная точка будет представляться клиентом при handshake tls-client # файлы ключа и сертификата клиента client.key и client.crt key /etc/openvpn/keys/client.key cert /etc/openvpn/keys/client.crt # здесь отпечаток сертификата сервера в России 111.111.111.111 peer-fingerprint D4:0A:C6:1C:70:7C:83:71:59:48:C4:DC:AB:F3:CE:28:9F:36:56:99:01:94:AD:67:A3:2A:F9:E5:3A:1F:CB:6A # режим point-to-point, этот режим используется по умолчанию mode p2p # ip-адрес клиента и сервера в виртуальной приватной сети (VPN) ifconfig 10.104.104.2 10.104.104.1 # использовать VPN-туннель для маршрутизации всего трафика redirect-gateway def1 bypass-dhcp # использовать DNS-сервера 208.67.220.220 и 208.67.222.222 dhcp-option DNS 208.67.220.220 dhcp-option DNS 208.67.222.222 # все DNS-запросы отправлять в туннель для избежания утечки dhcp-option DOMAIN-ROUTE . # следующие четыре директивы нужны для изменения используемых # DNS-серверов на клиенте при запуске/остановки службы script-security 2 # выполнить команду или скрипт при запуске устройства tun/tap up /etc/openvpn/update-systemd-resolved # выполнить команду или скрипт при остановке устройства tun/tap down /etc/openvpn/update-systemd-resolved # выполнить команду из down перед, а не после остановки tun/tap down-pre keepalive 10 60 user nobody group nogroup persist-tun persist-key # логирование нужно только на этапе отладки, потом можно отключить log /var/log/openvpn/openvpn.log verb 3
Чтобы получить скрипт /etc/openvpn/update-systemd-resolved
— нужно установить пакет openvpn-systemd-resolved
# apt install openvpn-systemd-resolved
Запускаем службу и добавляем в автозагрузку
# systemctl start openvpn-client@p2p_tls_tcp_1234.service # systemctl enable openvpn-client@p2p_tls_tcp_1234.service
5. OpenVPN, сервер-клиенты, TLS (finger print), протокол TCP, порт 443
Вместо режима «точка-точка» (mode p2p
) будем использовать режим «сервер-клиенты» (mode server
) — потому что у сервера за рубежом и у сервера в России — теперь по два клиента. Эти два новых клиента будут отправлять весь трафик в VPN-туннель — то есть, выходить в интернет через VPN-сервер за рубежом.
Компьютер ivanov
Создаем ключ и сертификат для клиента — файлы ivanov.key
и ivanov.crt
. Эти ключ и сертификат копируем на компьютер ivanov
— в директорию /etc/openvpn/keys
.
# openssl req -x509 \ > -newkey ec:<(openssl ecparam -name secp384r1) \ > -keyout ivanov.key \ > -out ivanov.crt \ > -nodes \ > -sha256 \ > -days 3650 \ > -subj '/CN=ivanov'
Создаем SHA256 отпечаток файла сертификата клиента ivanov
# openssl x509 -fingerprint -sha256 -in ivanov.crt -noout sha256 Fingerprint=82:68:0F:99:F6:DD:E3:C0:42:60:D1:2C:B9:3B:73:6E:27:B4:D0:3C:B0:D7:F5:34:B2:AB:16:C2:28:59:79:25
Файл конфигурации службы VPN-клиента
# nano /etc/openvpn/client/srv_tls_tcp_443.conf
dev tun # для протокола TCP для клиента опция имеет значение tcp-client proto tcp4-client # ip-адрес, порт и протокол сервера для установления соединения remote 222.222.222.222 443 tcp4-client # использовать динамический порт для возвращающихся пакетов nobind # эта конечная точка будет представляться клиентом при handshake tls-client # файлы ключа и сертификата клиента ivanov.key и ivanov.crt key /etc/openvpn/keys/ivanov.key cert /etc/openvpn/keys/ivanov.crt # здесь отпечаток сертификата сервера за рубежом 222.222.222.222 peer-fingerprint D4:0A:C6:1C:70:7C:83:71:59:48:C4:DC:AB:F3:CE:28:9F:36:56:99:01:94:AD:67:A3:2A:F9:E5:3A:1F:CB:6A # директиву можно использовать только в режиме «сервер-клиенты» в # файле конфигурации клиента; она разрешает принимать от сервера # директивы конфигурации, которые тот отправляет с помощью push pull # этот маршрут нужен, чтобы иметь доступ к этому серверу по ssh route 123.123.123.123 255.255.255.255 net_gateway # следующие четыре директивы нужны для изменения используемых # DNS-серверов на клиенте при запуске/остановки службы script-security 2 # выполнить команду или скрипт при запуске устройства tun/tap up /etc/openvpn/update-systemd-resolved # выполнить команду или скрипт при остановке устройства tun/tap down /etc/openvpn/update-systemd-resolved # выполнить команду из down перед, а не после остановки tun/tap down-pre user nobody group nogroup persist-tun persist-key # логирование нужно только на этапе отладки, потом можно отключить log /var/log/openvpn/openvpn.log verb 3
В файле конфигурации есть директива route
, которая добавляет маршрут до 123.123.123.123
через физический сетевой интерфейс. У меня роль компьютера ivanov
играет облачный сервер, к которому есть доступ по ssh с ip-адреса 123.123.123.123
. Эта директива нужна, чтобы не потерять ssh-доступ к серверу — ответы должны уходить через физический сетевой интерфейс. Для обычного VPN-клиента ivanov
, который просто выходит в интернет через сервер за рубежом — эта директива не нужна.
Было бы правильно настроить Policy-based Routing (PBR) — чтобы на входящее ssh-соединение, которое пришло на физический сетевой интерфейс, ответ уходил через тот же физический интерефейс, вместо маршрута по умолчанию. Но в данном случае подразумевается, что ivanov
— обычный пользователь, компьютер которого не имеет белого ip-адреса, так что и подключиться к его компу невозможно. И лучше для такого пользователя создать ovpn файл конфигурации, в который включить содержимое ivanov.key
и ivanov.crt
.
Чтобы получить скрипт /etc/openvpn/update-systemd-resolved
— нужно установить пакет openvpn-systemd-resolved
# apt install openvpn-systemd-resolved
Запускаем службу и добавляем в автозагрузку
# systemctl start openvpn-client@srv_tls_tcp_443.service # systemctl enable openvpn-client@srv_tls_tcp_443.service
Компьютер petrov
Создаем ключ и сертификат для клиента — файлы petrov.key
и petrov.crt
. Эти ключ и сертификат копируем на компьютер petrov
— в директорию /etc/openvpn/keys
.
# openssl req -x509 \ > -newkey ec:<(openssl ecparam -name secp384r1) \ > -keyout petrov.key \ > -out petrov.crt \ > -nodes \ > -sha256 \ > -days 3650 \ > -subj '/CN=petrov'
Создаем SHA256 отпечаток файла сертификата клиента petrov
# openssl x509 -fingerprint -sha256 -in petrov.crt -noout
Файл конфигурации службы VPN-клиента
# nano /etc/openvpn/client/srv_tls_tcp_443.conf
dev tun # для протокола TCP для клиента опция имеет значение tcp-client proto tcp4-client # ip-адрес, порт и протокол сервера для установления соединения remote 111.111.111.111 443 tcp4-client # использовать динамический порт для возвращающихся пакетов nobind # эта конечная точка будет представляться клиентом при handshake tls-client # файлы ключа и сертификата клиента petrov.key и petrov.crt key /etc/openvpn/keys/petrov.key cert /etc/openvpn/keys/petrov.crt # здесь отпечаток сертификата сервера в России 111.111.111.111 peer-fingerprint D4:0A:C6:1C:70:7C:83:71:59:48:C4:DC:AB:F3:CE:28:9F:36:56:99:01:94:AD:67:A3:2A:F9:E5:3A:1F:CB:6A # директиву можно использовать только в режиме «сервер-клиенты» в # файле конфигурации клиента; она разрешает принимать от сервера # директивы конфигурации, которые тот отправляет с помощью push pull # следующие четыре директивы нужны для изменения используемых # DNS-серверов на клиенте при запуске/остановки службы script-security 2 # выполнить команду или скрипт при запуске устройства tun/tap up /etc/openvpn/update-systemd-resolved # выполнить команду или скрипт при остановке устройства tun/tap down /etc/openvpn/update-systemd-resolved # выполнить команду из down перед, а не после остановки tun/tap down-pre user nobody group nogroup persist-tun persist-key # логирование нужно только на этапе отладки, потом можно отключить log /var/log/openvpn/openvpn.log verb 3
Чтобы получить скрипт /etc/openvpn/update-systemd-resolved
— нужно установить пакет openvpn-systemd-resolved
# apt install openvpn-systemd-resolved
Запускаем службу и добавляем в автозагрузку
# systemctl start openvpn-client@srv_tls_tcp_443.service # systemctl enable openvpn-client@srv_tls_tcp_443.service
Сервер за рубежом
Файл конфигурации службы VPN-сервера
# nano /etc/openvpn/server/srv_tls_tcp_443.conf
dev tun # для протокола TCP для сервера опция имеет значение tcp-server proto tcp4-server # на каком сетевом интерфейсе принимать соединения от клиентов local 222.222.222.222 # номер порта, на котором нужно принимать соединения от клиентов lport 443 # эта конечная точка будет представляться сервером при handshake tls-server # файлы ключа и сертификата сервера server.key и server.crt key /etc/openvpn/keys/server.key cert /etc/openvpn/keys/server.crt # отпечатки пальцев клиентов, теперь два клиента вместо одного <peer-fingerprint> # первый клиент, сервер в России 68:AA:B5:98:F2:DB:5F:E7:48:07:DB:E7:EF:99:9A:F2:0D:D9:6B:B4:0D:39:36:C2:A2:3C:5D:DA:07:39:00:61 # второй клиент, компьютер ivanov 82:68:0F:99:F6:DD:E3:C0:42:60:D1:2C:B9:3B:73:6E:27:B4:D0:3C:B0:D7:F5:34:B2:AB:16:C2:28:59:79:25 </peer-fingerprint> # не использовать файл Diffie-Hellman, а использовать протокол # на элиптических кривых ECDH (Elliptic curve Diffie-Hellman) dh none # режим «сервер-клиенты» вместо режима по умолчанию «точка-точка» mode server # топология «subnet» для режима «сервер-клиенты» вместо топологии # «p2p», которая используется в режиме по умолчанию «точка-точка» topology subnet # ip-адрес и маска сервера в виртуальной сети «сервер-клиенты» ifconfig 10.205.205.1 255.255.255.0 # шлюз по умолчанию для этой виртуальной сети (это VPN-сервер) route-gateway 10.205.205.1 # серверу в России назначим статический ip-адрес 10.205.205.2 client-config-dir /etc/openvpn/ccd # остальным клиентам будем назначать адреса из этого диапазона ifconfig-pool 10.205.205.3 10.205.205.254 255.255.255.0 # сохранять за клиентамм постоянные адреса, хранить их в файле ifconfig-pool-persist /var/log/openvpn/ipp.txt # При подключении клиентов — отправлять им директивы настройки: # использовать топологию «subnet» для этой виртуальной сети push "topology subnet" # шлюз по умолчанию для этой виртуальной сети (это VPN-сервер) push "route-gateway 10.205.205.1" # использовать VPN-туннель для маршрутизации всего трафика push "redirect-gateway def1 bypass-dhcp" # использовать DNS-сервера 208.67.220.220 и 208.67.222.222 push "dhcp-option DNS 208.67.220.220" push "dhcp-option DNS 208.67.222.222" # все DNS-запросы отправлять в туннель для избежания утечки push "dhcp-option DOMAIN-ROUTE ." script-security 2 # выполнить команду или скрипт при запуске устройства tun/tap up /etc/openvpn/server-up.sh # выполнить команду или скрипт при остановке устройства tun/tap plugin /usr/lib/openvpn/openvpn-plugin-down-root.so /etc/openvpn/server-dn.sh # выполнить команду из down перед, а не после остановки tun/tap down-pre keepalive 10 60 user nobody group nogroup persist-tun persist-key # логирование нужно только на этапе отладки, потом можно отключить log /var/log/openvpn/openvpn.log verb 3
Файл конфигурации клиента в директории client-config-dir
, который будет использован в момент подключения клиента client
. Этот файл должен быть доступен для чтения службе OpenVPN-сервера, когда уже отброшены права root
и служба работает от имени nobody
и nogroup
.
# mkdir /etc/openvpn/ccd # nano /etc/openvpn/ccd/client
# серверу в России назначим статический ip-адрес
ifconfig-push 10.205.205.2 255.255.255.0
Скрипты при запуске/остановке службы
# nano /etc/openvpn/server-up.sh
#!/bin/bash
# Разрешаем пакеты между интерфейсами, если это запрещено. При этом
# запоминаем значение, чтобы при остановке службы вернуть как было.
forward=$(cat /proc/sys/net/ipv4/ip_forward)
if [[ $forward == '0' ]]; then
echo '0' > /etc/openvpn/forward.txt
sysctl -w -q net.ipv4.ip_forward=1
else
echo '1' > /etc/openvpn/forward.txt
fi
# Изменяем на DROP политику по умолчанию для цепочки FORWARD. При этом
# запоминаем значение, чтобы при остановке службы вернуть как было.
iptables -L | grep 'Chain FORWARD (policy ACCEPT)'
if [[ $? == 0 ]]; then
echo 'ACCEPT' > /etc/openvpn/policy.txt
iptables -P FORWARD DROP
else
echo 'DROP' > /etc/openvpn/policy.txt
fi
# Разрешаем пакеты между интерфейсами tun0 и eth0 в двух направлениях
iptables -A FORWARD -i tun0 -o eth0 -s 10.205.205.0/24 -j ACCEPT
iptables -A FORWARD -i eth0 -o tun0 -d 10.205.205.0/24 -j ACCEPT
# SNAT, чтобы клиенты использовали адрес сервера для выхода в интернет
iptables -t nat -A POSTROUTING -o eth0 -s 10.205.205.0/24 -j MASQUERADE
# chmod +x /etc/openvpn/server-up.sh
# nano /etc/openvpn/server-dn.sh
#!/bin/bash
# Восстанавливаем значение, которые было до момента запуска службы
if [[ -f /etc/openvpn/forward.txt ]]; then
forward=$(cat /etc/openvpn/forward.txt)
if [[ $forward == '0' ]]; then
sysctl -w -q net.ipv4.ip_forward=0
fi
rm /etc/openvpn/forward.txt
else
sysctl -w -q net.ipv4.ip_forward=0
fi
# Восстанавливаем политику, которая была до момента запуска службы
if [[ -f /etc/openvpn/policy.txt ]]; then
policy=$(cat /etc/openvpn/policy.txt)
if [[ $policy == 'ACCEPT' ]]; then
iptables -P FORWARD ACCEPT
fi
rm /etc/openvpn/policy.txt
else
iptables -P FORWARD ACCEPT
fi
# Удаляем правила маршрутизации пакетов, добавленные при запуске службы
iptables -D FORWARD -i tun0 -o eth0 -s 10.205.205.0/24 -j ACCEPT
iptables -D FORWARD -i eth0 -o tun0 -d 10.205.205.0/24 -j ACCEPT
iptables -t nat -D POSTROUTING -o eth0 -s 10.205.205.0/24 -j MASQUERADE
# chmod +x /etc/openvpn/server-dn.sh
Запускаем службу и добавляем в автозагрузку
# systemctl start openvpn-client@srv_tls_tcp_443.service # systemctl enable openvpn-client@srv_tls_tcp_443.service
Сервер в России
На сервере будут работать две службы — VPN-сервера и VPN-клиента.
1. VPN-сервер (служба)
Файл конфигурации службы VPN-сервера
# nano /etc/openvpn/server/srv_tls_tcp_443.conf
dev ovpn-server dev-type tun # для протокола TCP для сервера опция имеет значение tcp-server proto tcp4-server # на каком сетевом интерфейсе принимать соединения от клиентов local 111.111.111.111 # номер порта, на котором нужно принимать соединения от клиентов lport 443 # эта конечная точка будет представляться сервером при handshake tls-server # файлы ключа и сертификата сервера server.key и server.crt key /etc/openvpn/keys/server.key cert /etc/openvpn/keys/server.crt # отпечатки пальцев клиентов, теперь два клиента вместо одного <peer-fingerprint> # первый клиент в домашней сети 68:AA:B5:98:F2:DB:5F:E7:48:07:DB:E7:EF:99:9A:F2:0D:D9:6B:B4:0D:39:36:C2:A2:3C:5D:DA:07:39:00:61 # второй клиент, компьютер petrov 72:12:3F:0F:24:4D:97:D6:4E:59:CB:61:65:81:CF:B6:0D:27:AC:7A:F1:47:E5:23:D8:62:B7:81:66:50:4C:BD </peer-fingerprint> # не использовать файл Diffie-Hellman, а использовать протокол # на элиптических кривых ECDH (Elliptic curve Diffie-Hellman) dh none # режим «сервер-клиенты» вместо режима по умолчанию «точка-точка» mode server # топология «subnet» для режима «сервер-клиенты» вместо топологии # «p2p», которая используется в режиме по умолчанию «точка-точка» topology subnet # ip-адрес и маска сервера в виртуальной сети «сервер-клиенты» ifconfig 10.105.105.1 255.255.255.0 # шлюз по умолчанию для этой виртуальной сети (это VPN-сервер) route-gateway 10.105.105.1 # VPN-клиенту в домашней сети назначим статический ip-адрес client-config-dir /etc/openvpn/ccd # остальным клиентам будем назначать адреса из этого диапазона ifconfig-pool 10.105.105.3 10.105.105.254 255.255.255.0 # сохранять за клиентамм постоянные адреса, хранить их в файле ifconfig-pool-persist /var/log/openvpn/ipp.txt # При подключении клиентов — отправлять им директивы настройки: # использовать топологию «subnet» для этой виртуальной сети push "topology subnet" # шлюз по умолчанию для этой виртуальной сети (это VPN-сервер) push "route-gateway 10.105.105.1" # использовать VPN-туннель для маршрутизации всего трафика push "redirect-gateway def1 bypass-dhcp" # использовать DNS-сервера 208.67.220.220 и 208.67.222.222 push "dhcp-option DNS 208.67.220.220" push "dhcp-option DNS 208.67.222.222" # все DNS-запросы отправлять в туннель для избежания утечки push "dhcp-option DOMAIN-ROUTE ." keepalive 10 60 user nobody group nogroup persist-tun persist-key # логирование нужно только на этапе отладки, потом можно отключить log /var/log/openvpn/server.log verb 3
Файл конфигурации клиента в директории client-config-dir
, который будет использован в момент подключения клиента client
. Этот файл должен быть доступен для чтения службе OpenVPN-сервера, когда уже отброшены права root
и служба работает от имени nobody
и nogroup
.
# mkdir /etc/openvpn/ccd # nano /etc/openvpn/ccd/client
# VPN-клиенту в домашней сети назначим статический ip-адрес
ifconfig-push 10.105.105.2 255.255.255.0
Запускаем службу и добавляем в автозагрузку
# systemctl start openvpn-server@srv_tls_tcp_443.service # systemctl enable openvpn-server@srv_tls_tcp_443.service
2. VPN-клиент (служба)
Файл конфигурации службы VPN-клиента
# nano /etc/openvpn/client/srv_tls_tcp_443.conf
dev ovpn-client dev-type tun # для протокола TCP для клиента опция имеет значение tcp-client proto tcp4-client # ip-адрес, порт и протокол сервера для установления соединения remote 222.222.222.222 443 tcp4-client # использовать динамический порт для возвращающихся пакетов nobind # эта конечная точка будет представляться клиентом при handshake tls-client # файлы ключа и сертификата клиента client.key и client.crt key /etc/openvpn/keys/client.key cert /etc/openvpn/keys/client.crt # здесь отпечаток сертификата сервера за рубежом 222.222.222.222 peer-fingerprint D4:0A:C6:1C:70:7C:83:71:59:48:C4:DC:AB:F3:CE:28:9F:36:56:99:01:94:AD:67:A3:2A:F9:E5:3A:1F:CB:6A # директиву можно использовать только в режиме «сервер-клиенты» в # файле конфигурации клиента; она разрешает принимать от сервера # директивы конфигурации, которые тот отправляет с помощью push pull # этот клиент не должен отправлять весь свой трафик в VPN-туннель; # отбрасываем все директивы от сервера, которые это предписывают pull-filter ignore "redirect-gateway def1 bypass-dhcp" pull-filter ignore "dhcp-option DNS 208.67.220.220" pull-filter ignore "dhcp-option DNS 208.67.222.222" pull-filter ignore "dhcp-option DOMAIN-ROUTE ." script-security 2 # выполнить эту команду или скрипт при запуске устройства tun/tap up /etc/openvpn/client-up.sh # выполнить команду или скрипт при остановке устройства tun/tap plugin /usr/lib/openvpn/openvpn-plugin-down-root.so /etc/openvpn/client-dn.sh # выполнить команду из down перед, а не после остановки tun/tap down-pre user nobody group nogroup persist-tun persist-key # логирование нужно только на этапе отладки, потом можно отключить log /var/log/openvpn/client.log verb 3
Скрипты при запуске/остановке службы
# nano /etc/openvpn/client-up.sh
#!/bin/bash
# Разрешаем пакеты между интерфейсами, если это запрещено. При этом
# запоминаем значение, чтобы при остановке службы вернуть как было.
forward=$(cat /proc/sys/net/ipv4/ip_forward)
if [[ $forward == '0' ]]; then
echo '0' > /etc/openvpn/forward.txt
sysctl -w -q net.ipv4.ip_forward=1
else
echo '1' > /etc/openvpn/forward.txt
fi
# Изменяем на DROP политику по умолчанию для цепочки FORWARD. При этом
# запоминаем значение, чтобы при остановке службы вернуть как было.
iptables -L | grep 'Chain FORWARD (policy ACCEPT)'
if [[ $? == 0 ]]; then
echo 'ACCEPT' > /etc/openvpn/policy.txt
iptables -P FORWARD DROP
else
echo 'DROP' > /etc/openvpn/policy.txt
fi
# Разрешаем пакеты между интерфейсами ovpn-client и ovpn-server туда-обратно
iptables -A FORWARD -i ovpn-server -o ovpn-client -s 10.105.105.0/24 -j ACCEPT
iptables -A FORWARD -i ovpn-client -o ovpn-server -d 10.105.105.0/24 -j ACCEPT
# SNAT, чтобы все пакеты, которые уходят с интерфейса ovpn-client в туннель в
# направлении сервера за рубежом, имели ip-адрес источника, как у ovpn-client
iptables -t nat -A POSTROUTING -s 10.105.105.0/24 -o ovpn-client -j MASQUERADE
# Для пакетов из сети 10.105.105.0/24 — создаем отдельную таблицу маршрутизации
ip rule add from 10.105.105.0/24 table 155
# Чтобы работал ping от клиента в домашней сети, нужно чтобы ответы уходили
# через сетевой интерфейс ovpn-server, иначе они будут уходить по дефолтному
# маршруту, то есть через интерфейс ovpn-client (см.ниже)
ip route add 10.105.105.0/24 dev ovpn-server table 155
# Пакеты из сети 10.105.105.0/24 — будут уходить через интерфейс ovpn-client
ip route add default dev ovpn-client table 155
# chmod +x /etc/openvpn/client-up.sh
# nano /etc/openvpn/client-dn.sh
#!/bin/bash
# Восстанавливаем значение, которые было до момента запуска службы
if [[ -f /etc/openvpn/forward.txt ]]; then
forward=$(cat /etc/openvpn/forward.txt)
if [[ $forward == '0' ]]; then
sysctl -w -q net.ipv4.ip_forward=0
fi
rm /etc/openvpn/forward.txt
else
sysctl -w -q net.ipv4.ip_forward=0
fi
# Восстанавливаем политику, которая была до момента запуска службы
if [[ -f /etc/openvpn/policy.txt ]]; then
policy=$(cat /etc/openvpn/policy.txt)
if [[ $policy == 'ACCEPT' ]]; then
iptables -P FORWARD ACCEPT
fi
rm /etc/openvpn/policy.txt
else
iptables -P FORWARD ACCEPT
fi
# Удаляем правила маршрутизации пакетов, добавленные при запуске службы
iptables -D FORWARD -i ovpn-server -o ovpn-client -s 10.105.105.0/24 -j ACCEPT
iptables -D FORWARD -i ovpn-client -o ovpn-server -d 10.105.105.0/24 -j ACCEPT
iptables -t nat -D POSTROUTING -s 10.105.105.0/24 -o ovpn-client -j MASQUERADE
ip rule del from 10.105.105.0/24 table 155
ip route del 10.105.105.0/24 dev ovpn-server table 155
ip route del default dev ovpn-client table 155
# chmod +x /etc/openvpn/client-dn.sh
Служба VPN-клиента зависит от службы VPN-сервера — скрипт client-up.sh
ожидает, что сетевой интерфейс ovpn-server
будет существовать и может быть использован в команде iptables
. Это значит, что мы должны обеспечить правильный порядок запуска двух служб — сначала VPN-сервер, потом VPN-клиент.
# cp /usr/lib/systemd/system/openvpn-client@.service /etc/systemd/system # nano /etc/systemd/system/openvpn-client@.service
[Unit] Description=OpenVPN tunnel for %I After=network-online.target Wants=network-online.target # служба VPN-клиента будет запущена после службы VPN-сервера Requires=openvpn-server@srv_tls_tcp_443.service After=openvpn-server@srv_tls_tcp_443.service
# systemctl daemon-reload
Запускаем службу и добавляем в автозагрузку
# systemctl start openvpn-client@srv_tls_tcp_443.service # systemctl enable openvpn-client@srv_tls_tcp_443.service
Клиент в домашней сети
Файл конфигурации службы VPN-клиента
# nano /etc/openvpn/client/srv_tls_tcp_443.conf
dev tun # для протокола TCP для клиента опция имеет значение tcp-client proto tcp4-client # ip-адрес, порт и протокол сервера для установления соединения remote 111.111.111.111 443 tcp4-client # использовать динамический порт для возвращающихся пакетов nobind # эта конечная точка будет представляться клиентом при handshake tls-client # файлы ключа и сертификата клиента client.key и client.crt key /etc/openvpn/keys/client.key cert /etc/openvpn/keys/client.crt # здесь отпечаток сертификата сервера в России 111.111.111.111 peer-fingerprint D4:0A:C6:1C:70:7C:83:71:59:48:C4:DC:AB:F3:CE:28:9F:36:56:99:01:94:AD:67:A3:2A:F9:E5:3A:1F:CB:6A # директиву можно использовать только в режиме «сервер-клиенты» в # файле конфигурации клиента; она разрешает принимать от сервера # директивы конфигурации, которые тот отправляет с помощью push pull # следующие четыре директивы нужны для изменения используемых # DNS-серверов на клиенте при запуске/остановки службы script-security 2 # выполнить команду или скрипт при запуске устройства tun/tap up /etc/openvpn/update-systemd-resolved # выполнить команду или скрипт при остановке устройства tun/tap down /etc/openvpn/update-systemd-resolved # выполнить команду из down перед, а не после остановки tun/tap down-pre user nobody group nogroup persist-tun persist-key # логирование нужно только на этапе отладки, потом можно отключить log /var/log/openvpn/openvpn.log verb 3
Чтобы получить скрипт /etc/openvpn/update-systemd-resolved
— нужно установить пакет openvpn-systemd-resolved
# apt install openvpn-systemd-resolved
Запускаем службу и добавляем в автозагрузку
# systemctl start openvpn-client@srv_tls_tcp_443.service # systemctl enable openvpn-client@srv_tls_tcp_443.service
Немного пояснений
Сервер в России весь трафик, который приходит на сетевой интерфейс ovpn-server
, перебрасывает на сетевой интерфейс ovpn-client
— откуда он уходит в направлении сервера за рубежом. При этом свой трафик сервер в России отправляет с физического интерфейса eth0
— то есть, выходит в интернет самостоятельно. Два клиента VPN-сервера в России имеют одинаковые настройки — оба отправляют весь свой трафик с сетевого интерфейса tun0
, то есть в VPN-туннель.
Клиент ivanov
весь свой трафик отправляет с интерфейса tun0
, то есть выходит в интернет через сервер за рубежом. Подразумевается, что таких клиентов может быть много, поэтому в файл конфигурации VPN-сервера за рубежом мы добавляем директивы push
, которые предписывают клиентам отправлять весь трафик в VPN-туннель. Но для VPN-клиента, который запущен на сервере в России — эти директивы не нужны. Поэтому в файле конфигурации службы этого VPN-клиента — используем директиву pull-filter
.
Директива client-config-dir
задает директорию для хранения файлов конфигурации клиентов, которые используются VPN-сервером только при подключении конкретного клиента. В этих файлах можно использовать директиву push
— чтобы отправить клиенту индивидуальные настройки. С другой стороны, в файле конфигурации клиента можно использовать директиву pull-filter
— чтобы принять или отбросить директивы, отправленные сервером с помощью push
.
В файлах конфигурации клиентов мы не используем директиву keepalive
, потому что в режиме «сервер-клиенты» — VPN-сервер сам отправит клиентам директивы ping
и ping-restart
с помощью push
. Но в файлах конфигурации клиентов должна быть директива pull
— которая разрешает принимать от сервера директивы конфигурации.
- Установка WireGuard на Ubuntu 20.04 LTS. Часть вторая из двух
- Установка WireGuard на Ubuntu 20.04 LTS. Часть первая из двух
- Установка OpenVPN на Ubuntu 18.04 LTS. Часть 12 из 12
- Установка OpenVPN на Ubuntu 18.04 LTS. Часть 11 из 12
- Установка OpenVPN на Ubuntu 18.04 LTS. Часть 10 из 12
- Установка OpenVPN на Ubuntu 18.04 LTS. Часть 9 из 12
- Установка OpenVPN на Ubuntu 18.04 LTS. Часть 8 из 12
Поиск: Linux • Ubuntu • VPN • Клиент • Ключ • Настройка • Сервер • Установка • OpenVPN