Установка OpenVPN на Ubuntu 18.04 LTS. Часть 6 из 12

23.07.2020

Теги: LinuxSSLUbuntuVPNКлиентКлючКонфигурацияЛокальнаяСетьМаршрутизацияНастройкаСерверУстановка

Если требуется обеспечить связь между локальными сетями, но оба маршрутизатора имеют серые ip-адреса — потребуется промежуточный сервер, у которого есть белый ip-адрес. Итак, у нас по-прежнему есть локальная сеть компании и локальная сеть филиала. Маршрутизатор gateway1 обеспечивает выход в интернет для компьютеров сети 192.168.150.0/24, а маршрутизатор gateway2 — для компьютеров сети 192.168.250.0/24.

Настройка маршрутизатора gateway1

Сначала настраиваем сетевые интерфейсы с помощью Netplan:

$ sudo nano /etc/netplan/01-netcfg.yaml
network:
  version: 2
  renderer: networkd
  ethernets:
    enp0s3:
      dhcp4: no
      addresses: [192.168.100.2/24]
      gateway4: 192.168.100.1
      nameservers:
        addresses: [8.8.8.8, 8.8.4.4]
    enp0s8:
      dhcp4: no
      addresses: [192.168.150.1/24]
      nameservers:
        addresses: [8.8.8.8, 8.8.4.4]

Применяем настройки и смотрим сетевые интерфейсы:

$ sudo netplan apply # применить настройки из YAML-файла к работающей системе
$ sudo netplan generate # сохранить текущие настройки в файл конфигурации networkd

Сервер gateway1 должен обеспечивать выход в интернет для всех компьютеров из локальной сети 192.168.150.0/24.

$ sudo nano /etc/sysctl.conf
# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1

Чтобы внесенные изменения вступили в силу, выполняем команду:

$ sudo sysctl -p
net.ipv4.ip_forward = 1

После этого настраиваем netfilter с помощью утилиты iptables:

$ sudo iptables -P FORWARD DROP
$ sudo iptables -A FORWARD -i enp0s8 -o enp0s3 -s 192.168.150.0/24 ! -d 192.168.250.0/24 -j ACCEPT # enp0s8 -> enp0s3
$ sudo iptables -A FORWARD -i enp0s3 -o enp0s8 -d 192.168.150.0/24 -j ACCEPT # enp0s3 -> enp0s8
$ sudo iptables -A FORWARD -i enp0s8 -o tun0 -s 192.168.150.0/24 -d 192.168.250.0/24 -j ACCEPT # enp0s8 -> tun0
$ sudo iptables -A FORWARD -i tun0 -o enp0s8 -s 192.168.250.0/24 -d 192.168.150.0/24 -j ACCEPT # tun0 -> enp0s8
$ sudo iptables -t nat -A POSTROUTING -o enp0s3 -j MASQUERADE # SNAT для enp0s3

Устанавливаем пакет iptables-persistent, чтобы сохранить добавленные правила:

$ sudo apt install iptables-persistent

Настройка маршрутизатора gateway2

Сначала настраиваем сетевые интерфейсы с помощью Netplan:

$ sudo nano /etc/netplan/01-netcfg.yaml
network:
  version: 2
  renderer: networkd
  ethernets:
    enp0s3:
      dhcp4: no
      addresses: [192.168.200.2/24]
      gateway4: 192.168.200.1
      nameservers:
        addresses: [8.8.8.8, 8.8.4.4]
    enp0s8:
      dhcp4: no
      addresses: [192.168.250.1/24]
      nameservers:
        addresses: [8.8.8.8, 8.8.4.4]

Применяем настройки и смотрим сетевые интерфейсы:

$ sudo netplan apply # применить настройки из YAML-файла к работающей системе
$ sudo netplan generate # сохранить текущие настройки в файл конфигурации networkd

Сервер gateway2 должен обеспечивать выход в интернет для всех компьютеров из локальной сети 192.168.250.0/24.

$ sudo nano /etc/sysctl.conf
# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1

Чтобы внесенные изменения вступили в силу, выполняем команду:

$ sudo sysctl -p
net.ipv4.ip_forward = 1

После этого настраиваем netfilter с помощью утилиты iptables:

$ sudo iptables -P FORWARD DROP
$ sudo iptables -A FORWARD -i enp0s8 -o enp0s3 -s 192.168.250.0/24 ! -d 192.168.150.0/24 -j ACCEPT # enp0s8 -> enp0s3
$ sudo iptables -A FORWARD -i enp0s3 -o enp0s8 -d 192.168.250.0/24 -j ACCEPT # enp0s3 -> enp0s8
$ sudo iptables -A FORWARD -i enp0s8 -o tun0 -s 192.168.250.0/24 -d 192.168.150.0/24 -j ACCEPT # enp0s8 -> tun0
$ sudo iptables -A FORWARD -i tun0 -o enp0s8 -s 192.168.150.0/24 -d 192.168.250.0/24 -j ACCEPT # tun0 -> enp0s8
$ sudo iptables -t nat -A POSTROUTING -o enp0s3 -j MASQUERADE # SNAT для enp0s3

Устанавливаем пакет iptables-persistent, чтобы сохранить добавленные правила:

$ sudo apt install iptables-persistent

Создание центра сертификации

Центр сертификации будет на сервере 123.123.123.123, хотя это и неправильно (ЦС должен быть на отдельном сервере):

$ cd ~
$ mkdir easy-rsa
$ wget https://github.com/OpenVPN/easy-rsa/releases/download/v3.0.7/EasyRSA-3.0.7.tgz
$ tar xvf EasyRSA-3.0.7.tgz
$ cp -r EasyRSA-3.0.7/* easy-rsa/

Создаем копию файла vars.example — это пример конфигурации. Ничего в нем изменять не будем, в этом случае EASYRSA_DN имеет значение по умолчанию cn_only (Common Name Only), требующий ввода только универсального имени (подробности здесь).

$ cd ~/easy-rsa/
$ cp vars.example vars

Запускаем скрипт easyrsa с опцией init-pki для инициализации инфраструктуры:

$ ./easyrsa init-pki
init-pki complete; you may now create a CA or requests.
Your newly created PKI dir is: /home/evgeniy/easy-rsa/pki

Создаем корневой сертификат удостоверяющего центра:

$ ./easyrsa build-ca nopass
..........
Common Name (eg: your user, host, or server name) [Easy-RSA CA]: Some Company Auth Center
..........
Your new CA certificate file for publishing is at:
/home/evgeniy/easy-rsa/pki/ca.crt

Корневой сертификат — это файл pki/ca.crt, а приватный ключ — это файл pki/private/ca.key.

Ключи для сервера и клиентов

1. Создание ключей для сервера

Создаем закрытый ключ и запрос на подпись сертификата для VPN-сервера:

$ ./easyrsa gen-req vpn-server-some-company nopass
..........
Common Name (eg: your user, host, or server name) [vpn-server-some-company]: Enter

Keypair and certificate request completed. Your files are:
req: /home/evgeniy/easy-rsa/pki/reqs/vpn-server-some-company.req
key: /home/evgeniy/easy-rsa/pki/private/vpn-server-some-company.key

Подписываем сертификат VPN-сервера:

$ ./easyrsa sign-req server vpn-server-some-company
..........
Type the word 'yes' to continue, or any other input to abort.
  Confirm request details: yes
..........
Certificate created at: /home/evgeniy/easy-rsa/pki/issued/vpn-server-some-company.crt

Теперь создаем ключ Диффи-Хеллмана:

$ ./easyrsa gen-dh
..........
DH parameters of size 2048 created at /home/evgeniy/easy-rsa/pki/dh.pem

Это может занять несколько минут. Наконец, создаем ключ TLS:

$ openvpn --genkey --secret ta.key

2. Создание ключей для клиента gateway1

Создаем закрытый ключ и запрос на подпись сертификата для VPN-клиента gateway1:

$ ./easyrsa gen-req vpn-client-center-office nopass
..........
Common Name (eg: your user, host, or server name) [vpn-client-center-office]: Enter

Keypair and certificate request completed. Your files are:
req: /home/evgeniy/easy-rsa/pki/reqs/vpn-client-center-office.req
key: /home/evgeniy/easy-rsa/pki/private/vpn-client-center-office.key

Подписываем сертификат VPN-клиента:

$ ./easyrsa sign-req client vpn-client-center-office
..........
Type the word 'yes' to continue, or any other input to abort.
  Confirm request details: yes
..........
Certificate created at: /home/evgeniy/easy-rsa/pki/issued/vpn-client-center-office.crt

3. Создание ключей для клиента gateway2

Создаем закрытый ключ и запрос на подпись сертификата для VPN-клиента gateway2:

$ ./easyrsa gen-req vpn-client-branch-office nopass
..........
Common Name (eg: your user, host, or server name) [vpn-client-branch-office]: Enter

Keypair and certificate request completed. Your files are:
req: /home/evgeniy/easy-rsa/pki/reqs/vpn-client-branch-office.req
key: /home/evgeniy/easy-rsa/pki/private/vpn-client-branch-office.key

Подписываем сертификат VPN-клиента:

$ ./easyrsa sign-req client vpn-client-branch-office
..........
Type the word 'yes' to continue, or any other input to abort.
  Confirm request details: yes
..........
Certificate created at: /home/evgeniy/easy-rsa/pki/issued/vpn-client-branch-office.crt

Настройка VPN-сервера

После установки пакета openvpn копируем ключи сервера:

$ sudo mkdir /etc/openvpn/keys/ # создаем директорию для ключей и сертификатов
$ sudo cp /home/evgeniy/easy-rsa/pki/ca.crt /etc/openvpn/keys/ # корневой сертификат
$ sudo cp /home/evgeniy/easy-rsa/pki/private/vpn-server-some-company.key /etc/openvpn/keys/ # закрытый ключ сервера
$ sudo cp /home/evgeniy/easy-rsa/pki/issued/vpn-server-some-company.crt /etc/openvpn/keys/ # открытый ключ сервера
$ sudo cp /home/evgeniy/easy-rsa/pki/dh.pem /etc/openvpn/keys/ # ключ Диффи-Хеллмана
$ sudo cp /home/evgeniy/easy-rsa/ta.key /etc/openvpn/keys/ # ключ Transport Layer Security

Теперь создаем файл конфигурации VPN-сервера (это предварительный вариант, мы его еще дополним чуть позже):

# ip-адрес, на котором нужно принимать соединения от клиентов, если у сервера
# несколько сетевых интерфесов; иначе сервер будет слушать все интерфейсы
local 123.123.123.123
# порт, на котором работает сервер
port 1194
# работа по протоколу UDP (или TCP)
proto udp4
# сетевой интерфейс TUN (или TAP)
dev tun

# локальная сеть — сервер и клиенты
server 10.8.0.0 255.255.255.0

# эта директива используется совместно с директивой route и задает шлюз
# по умолчанию для VPN-сети (которым должен быть VPN-сервер); директива
# route имеет вид: «route network/ip-addr [netmask] [gateway] [metric]»
# и может получать значение gateway из директивы route-gateway
route-gateway 10.8.0.1

# одновременно может быть подключено 100 клиентов
max-clients 100

# три варианта: net30, p2p, subnet
topology subnet

# корневой сертификат
ca /etc/openvpn/keys/ca.crt
# сертификат сервера
cert /etc/openvpn/keys/vpn-server-some-company.crt
# приватный ключ сервера
key /etc/openvpn/keys/vpn-server-some-company.key

# добавляет дополнительную подпись HMAC ко всем пакетам handshake для
# проверки целостности; любой пакет, не имеющий правильной HMAC-подписи,
# будет отброшен без дальнейшей обработки; это для доп.безопасности
tls-auth /etc/openvpn/keys/ta.key
# направление ключа: для сервера — 0, для клиента — 1
key-direction 0

# ключ Диффи-Хеллмана
dh /etc/openvpn/keys/dh.pem

# использовать алгоритм AES-256-GCM шифрования пакетов канала данных;
# на данный момент это самый безопасный и быстрый алгоритм шифрования
cipher AES-256-GCM
# алгоритм хеширования — для проверки целостности передаваемых пакетов
# канала данных и (если включено tls-auth) пакетов канала управления
auth SHA256

# файл для хранения ip-адресов клиентов
ifconfig-pool-persist /var/log/openvpn/ipp.txt

# читать файлы конфигураций клиентов в этой директории
client-config-dir /etc/openvpn/ccd

# клиент может подключиться, если существует файл конфигурации для него
# в директории client-config-dir, пусть даже этот файл будет пустым
ccd-exclusive

# новый механизм компрессии; директива будет автоматически отправлена на клиент
compress lz4-v2
push "compress lz4-v2"
# явно запрещаем использование старого механизма сжатия на сервере и на клиентах
comp-lzo no
push "comp-lzo no"

# пользователь и группа с минимальными правами — для большей безопасности
user nobody
group nogroup

# не перечитывать файлы ключей при восстановлении после разрыва соединения
persist-key
# оставлять без изменения устройства tun или tap при перезапуске службы
persist-tun

# каждые 10 секунд отправлять ping-запрос на удаленный узел;
# если нет ответа 120 секунд — перезапускать туннель
keepalive 10 120

# файл статуса, содержит текущие соединения; перезаписывается каждую минуту
status /var/log/openvpn/openvpn-status.log

# по умолчанию логи идут в syslog; использование одной из директив ниже
# предписывает вести отдельный лог; первая — перезаписывать файл лога,
# вторая — дополнять файл лога; можно использовать только одну директиву
#log         /var/log/openvpn/openvpn.log
#log-append  /var/log/openvpn/openvpn.log

# уровень детализации лога от 0 до 11; если 0 — тогда только фатальные ошибки;
# при настройке установить значение 4-11, при эксплуатации — 0 или 1
verb 3

# предупреждать клиентов, что сервер перезапускается, чтобы клиенты могли
# автоматически переподключиться (только при работе по протоколу UDP)
explicit-exit-notify 1

Директива server является макрокомандой и имеет синтаксис:

server network netmask ['nopool']

Она будет преобразована по следующему алгортиму:

mode server
tls-server
push "topology [topology]"

if dev tun AND (topology == net30 OR topology == p2p):
  ifconfig 10.8.0.1 10.8.0.2
  if !nopool:
    ifconfig-pool 10.8.0.4 10.8.0.251
  route 10.8.0.0 255.255.255.0
  if client-to-client:
    push "route 10.8.0.0 255.255.255.0"
  else if topology == net30:
    push "route 10.8.0.1"

if dev tap OR (dev tun AND topology == subnet):
  ifconfig 10.8.0.1 255.255.255.0
  if !nopool:
    ifconfig-pool 10.8.0.2 10.8.0.253 255.255.255.0
  push "route-gateway 10.8.0.1"
  if route-gateway unset:
    route-gateway 10.8.0.2

В нашем случае это означает следующее:

# по умолчанию используется p2p-режим; эта директива
# включает режим сервера с многими клиентами
mode server
# включить TLS и при handshake представляться как сервер
tls-server
# сообщить клиентам, что используется топология subnet
push "topology subnet"
# назначить серверу первый адрес виртуальной сети
ifconfig 10.8.0.1 255.255.255.0
# остальной блок адресов сети выделить клиентам
ifconfig-pool 10.8.0.2 10.8.0.253 255.255.255.0
# для клиентов шлюзом по умолчанию будет сервер
push "route-gateway 10.8.0.1"

Директива server с параметром nopool задает VPN-сеть без определения для нее пула ip-адресов. Затем с помощью директивы ifconfig-pool нужно самостоятельно задать пул ip-адресов для клиентов.

server 10.8.0.0 255.255.255.0 'nopool'
ifconfig-pool 10.8.0.10 10.8.0.100 255.255.255.0

Чтобы VPN-клиенты видели друг друга, добавим директиву:

# по умолчанию клиенты могут общаться только с сервером, эта директива
# изменяет это и разрешает клиентам общаться между собой
client-to-client

Теперь добавим маршруты в файл конфигурации сервера:

# сообщить серверу, что сеть 192.168.150.0/24 доступна через хост 10.8.0.2
route 192.168.150.0 255.255.255.0 10.8.0.2
# сообщить серверу, что сеть 192.168.250.0/24 доступна через хост 10.8.0.3
route 192.168.250.0 255.255.255.0 10.8.0.3

Директивы, которые будут выполнены при подключении клиента gateway1:

$ sudo nano /etc/openvpn/ccd/vpn-client-center-office
# назначить клиенту gateway1 второй ip-адрес виртуальной VPN-сети
ifconfig-push 10.8.0.2 255.255.255.0
# сообщить этому клиенту маршрут до сети за клиентом gateway2
# (здесь 10.8.0.1 можно не указывать, мы уже отправили клиенту
# push "route-gateway 10.8.0.1" с помощью макрокоманды server)
push "route 192.168.250.0 255.255.255.0 10.8.0.1"
# сообщить серверу, что за этим клиентом есть сеть 192.168.150.0/24
iroute 192.168.150.0 255.255.255.0

Директивы, которые будут выполнены при подключении клиента gateway2:

$ sudo nano /etc/openvpn/ccd/vpn-client-branch-office
# назначить клиенту gateway2 третий ip-адрес виртуальной VPN-сети
ifconfig-push 10.8.0.3 255.255.255.0
# сообщить этому клиенту маршрут до сети за клиентом gateway1
# (здесь 10.8.0.1 можно не указывать, мы уже отправили клиенту
# push "route-gateway 10.8.0.1" с помощью макрокоманды server)
push "route 192.168.150.0 255.255.255.0 10.8.0.1"
# сообщить серверу, что за этим клиентом есть сеть 192.168.250.0/24
iroute 192.168.250.0 255.255.255.0

Обратите внимание, что только клиент gateway1 будет знать маршрут до сети 192.168.250.0/24. И только клиент gateway2 будет знать маршрут до сети 192.168.150.0/24. Если нужно, чтобы и другие клиенты знали о существовании этих сетей, нужно вынести директивы push "route …" в общий файл конфигурации сервера.

# сообщить клиентам, что сеть 192.168.150.0/24 доступна через хост 10.8.0.1
push "route 192.168.150.0 255.255.255.0 10.8.0.1"
# сообщить клиентам, что сеть 192.168.250.0/24 доступна через хост 10.8.0.1
push "route 192.168.250.0 255.255.255.0 10.8.0.1"

Все готово, можно запускать VPN-сервер:

$ sudo systemctl start openvpn-server@config.service

Добавим запуск сервера в автозагрузку:

$ sudo systemctl enable openvpn-server@config.service

Настройка VPN-клиентов

1. Настройка клиента gateway1

Переходим к gateway1 и после установки пакета openvpn копируем ключи с сервера 123.123.123.123:

$ sudo mkdir /etc/openvpn/keys/ # создаем директорию для ключей и сертификатов
$ sudo scp evgeniy@123.123.123.123:/home/evgeniy/easy-rsa/pki/ca.crt /etc/openvpn/keys/
$ sudo scp evgeniy@123.123.123.123:/home/evgeniy/easy-rsa/pki/private/vpn-client-center-office.key /etc/openvpn/keys/
$ sudo scp evgeniy@123.123.123.123:/home/evgeniy/easy-rsa/pki/issued/vpn-client-center-office.crt /etc/openvpn/keys/
$ sudo scp evgeniy@123.123.123.123:/home/evgeniy/easy-rsa/ta.key /etc/openvpn/keys/

Теперь создаем файл конфигурации VPN-клиента:

$ sudo nano /etc/openvpn/client/config.conf
# это макрокоманда, преобразуется в директивы pull и tls-client
client
# работа по протоколу UDP (или TCP)
proto udp
# сетевой интерфейс TUN (или TAP)
dev tun

# ip-адрес и порт сервера
remote 123.123.123.123 1194

# если не удалось получить ip-адрес сервера от DNS, то через указанное
# количество секунд попытаться снова; infinite — повторять бесконечно
resolv-retry infinite

# использовать динамический порт для подключения к серверу (клиенту не
# требуется привязка к определенному порту); актуально только для UDP
nobind

# корневой сертификат
ca /etc/openvpn/keys/ca.crt
# сертификат клиента
cert /etc/openvpn/keys/vpn-client-center-office.crt
# приватный ключ клиента
key /etc/openvpn/keys/vpn-client-center-office.key

# для защиты от атаки «человек посередине», когда авторизованный клиент
# пытается подключиться к другому клиенту, выдавая себя за сервер; при
# указании этой директивы проверяется, что сертификат именно серверный
remote-cert-tls server

# добавляет дополнительную подпись HMAC ко всем пакетам handshake для
# проверки целостности; любой пакет, не имеющий правильной HMAC-подписи,
# будет отброшен без дальнейшей обработки; это для доп.безопасности
tls-auth /etc/openvpn/keys/ta.key
# сервер — 0, клиент — 1 (для TLS)
# направление ключа: для клиента — 1, для сервера — 0
key-direction 1

# использовать алгоритм AES-256-GCM шифрования пакетов канала данных;
# на данный момент это самый безопасный и быстрый алгоритм шифрования
cipher AES-256-GCM
# алгоритм хеширования — для проверки целостности передаваемых пакетов
# канала данных и (если включено tls-auth) пакетов канала управления
auth SHA256

# пользователь и группа с минимальными правами — для большей безопасности
user nobody
group nogroup

# не перечитывать файлы ключей при восстановлении после разрыва соединения
persist-key
# оставлять без изменения устройства tun или tap при перезапуске службы
persist-tun

# по умолчанию логи идут в syslog; использование одной из директив ниже
# предписывает вести отдельный лог; первая — перезаписывать файл лога,
# вторая — дополнять файл лога; можно использовать только одну директиву
#log         /var/log/openvpn/openvpn.log
#log-append  /var/log/openvpn/openvpn.log

# уровень детализации лога от 0 до 11; если 0 — тогда только фатальные ошибки;
# при настройке установить значение 4-11, при эксплуатации — 0 или 1
verb 3

Директива client является макрокомандой и преобразуется в директивы:

# принимать от сервера команды push, например маршруты
pull
# использовать TLS и при handshake представляться как клиент
tls-client

Директива pull-filter позволяет отклонить директивы, отправленные сервером с помощью push:

pull-filter accept|ignore text

Игнорировать изменение шлюза:

pull-filter ignore redirect-gateway

Если в шаблоне text есть пробел:

pull-filter ignore "dhcp-option DNS"

Все готово, можно запускать VPN-клиент:

$ sudo systemctl start openvpn-client@config.service

Добавим запуск клиента в автозагрузку:

$ sudo systemctl enable openvpn-client@config.service

2. Настройка клиента gateway2

Переходим к gateway2 и после установки пакета openvpn копируем ключи с сервера 123.123.123.123:

$ sudo mkdir /etc/openvpn/keys/ # создаем директорию для ключей и сертификатов
$ sudo scp evgeniy@123.123.123.123:/home/evgeniy/easy-rsa/pki/ca.crt /etc/openvpn/keys/
$ sudo scp evgeniy@123.123.123.123:/home/evgeniy/easy-rsa/pki/private/vpn-client-branch-office.key /etc/openvpn/keys/
$ sudo scp evgeniy@123.123.123.123:/home/evgeniy/easy-rsa/pki/issued/vpn-client-branch-office.crt /etc/openvpn/keys/
$ sudo scp evgeniy@123.123.123.123:/home/evgeniy/easy-rsa/ta.key /etc/openvpn/keys/

Теперь создаем файл конфигурации VPN-клиента:

$ sudo nano /etc/openvpn/client/config.conf
# это макрокоманда, преобразуется в директивы pull и tls-client
client
# работа по протоколу UDP (или TCP)
proto udp
# сетевой интерфейс TUN (или TAP)
dev tun

# ip-адрес и порт сервера
remote 123.123.123.123 1194

# если не удалось получить ip-адрес сервера от DNS, то через указанное
# количество секунд попытаться снова; infinite — повторять бесконечно
resolv-retry infinite

# использовать динамический порт для подключения к серверу (клиенту не
# требуется привязка к определенному порту); актуально только для UDP
nobind

# корневой сертификат
ca /etc/openvpn/keys/ca.crt
# сертификат клиента
cert /etc/openvpn/keys/vpn-client-branch-office.crt
# приватный ключ клиента
key /etc/openvpn/keys/vpn-client-branch-office.key

# для защиты от атаки «человек посередине», когда авторизованный клиент
# пытается подключиться к другому клиенту, выдавая себя за сервер; при
# указании этой директивы проверяется, что сертификат именно серверный
remote-cert-tls server

# добавляет дополнительную подпись HMAC ко всем пакетам handshake для
# проверки целостности; любой пакет, не имеющий правильной HMAC-подписи,
# будет отброшен без дальнейшей обработки; это для доп.безопасности
tls-auth /etc/openvpn/keys/ta.key
# направление ключа: для клиента — 1, для сервера — 0
key-direction 1

# использовать алгоритм AES-256-GCM шифрования пакетов канала данных;
# на данный момент это самый безопасный и быстрый алгоритм шифрования
cipher AES-256-GCM
# алгоритм хеширования — для проверки целостности передаваемых пакетов
# канала данных и (если включено tls-auth) пакетов канала управления
auth SHA256

# пользователь и группа с минимальными правами — для большей безопасности
user nobody
group nogroup

# не перечитывать файлы ключей при восстановлении после разрыва соединения
persist-key
# оставлять без изменения устройства tun или tap при перезапуске службы
persist-tun

# по умолчанию логи идут в syslog; использование одной из директив ниже
# предписывает вести отдельный лог; первая — перезаписывать файл лога,
# вторая — дополнять файл лога; можно использовать только одну директиву
#log         /var/log/openvpn/openvpn.log
#log-append  /var/log/openvpn/openvpn.log

# уровень детализации лога от 0 до 11; если 0 — тогда только фатальные ошибки;
# при настройке установить значение 4-11, при эксплуатации — 0 или 1
verb 3

Все готово, можно запускать VPN-клиент:

$ sudo systemctl start openvpn-client@config.service

Добавим запуск клиента в автозагрузку:

$ sudo systemctl enable openvpn-client@config.service

Фильтрация пакетов между сетями

Чтобы пакеты могли ходить между подсетями, мы добавили в файл конфигурации сервера директиву client-to-client. Давайте закомментируем эту директиву и вместо этого разрешим пересылку пакетов между интерфейсами на сервере 123.123.123.123.

$ sudo nano /etc/openvpn/server.conf
# по умолчанию клиенты могут общаться только с сервером, эта директива
# изменяет это и разрешает клиентам общаться между собой
#client-to-client

Разрешаем пересылку пакетов между интерфейсами:

$ sudo nano /etc/sysctl.conf
# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1

Чтобы внесенные изменения вступили в силу:

$ sudo sysctl -p
net.ipv4.ip_forward = 1

Разрешаем пакеты между двумя подсетями:

$ sudo iptables -P FORWARD DROP
$ sudo iptables -A FORWARD -i tun0 -o tun0 -j ACCEPT
$ iptables-save > /etc/iptables/rules.v4
При использовании директивы client-to-client работать будет быстрее, потому что OpenVPN передает пакеты клиент-клиент внутри себя, не используя сетевой стек операционной системы. Но пересылка пакетов между интерфейсами позволяет задействовать всю мощь netfilter для фильтрации пакетов. Здесь важно то, что пакеты проходят через netfilter и мы можем управлять этим с помощью утилиты iptables.

С помощью команды ping и tcpdump проверим, что есть связь между gateway1 и gateway2. На сервере 123.123.123.123 выполним команду tcpdump:

$ sudo tcpdump -i tun0 icmp # выполняем на сервере

А на маршрутизаторе gateway1 — команду ping:

$ ping -c3 10.8.0.3 # выполняем на gateway1
PING 10.8.0.3 (10.8.0.3) 56(84) bytes of data.
From 10.8.0.1: icmp_seq=1 Redirect Host(New nexthop: 10.8.0.3)
64 bytes from 10.8.0.3: icmp_seq=1 ttl=63 time=42.7 ms
From 10.8.0.1: icmp_seq=2 Redirect Host(New nexthop: 10.8.0.3)
64 bytes from 10.8.0.3: icmp_seq=2 ttl=63 time=34.0 ms
From 10.8.0.1: icmp_seq=3 Redirect Host(New nexthop: 10.8.0.3)
64 bytes from 10.8.0.3: icmp_seq=3 ttl=63 time=33.1 ms

--- 10.8.0.3 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 33.197/36.671/42.729/4.301 ms

И на сервере 123.123.123.123 мы видим прохождение пакетов:

$ sudo tcpdump -i tun0 icmp # смотрим на сервере
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on tun0, link-type RAW (Raw IP), capture size 262144 bytes
16:01:10.359941 IP 10.8.0.2 > 10.8.0.3: ICMP echo request, id 21126, seq 1, length 64 # входящий пакет
16:01:10.359971 IP 123.123.123.123 > 10.8.0.2: ICMP redirect 10.8.0.3 to host 10.8.0.3, length 92
16:01:10.359973 IP 10.8.0.2 > 10.8.0.3: ICMP echo request, id 21126, seq 1, length 64 # исходящий пакет
16:01:10.376842 IP 10.8.0.3 > 10.8.0.2: ICMP echo reply, id 21126, seq 1, length 64 # входящий пакет
16:01:10.376858 IP 123.123.123.123 > 10.8.0.3: ICMP redirect 10.8.0.2 to host 10.8.0.2, length 92
16:01:10.376860 IP 10.8.0.3 > 10.8.0.2: ICMP echo reply, id 21126, seq 1, length 64 # исходящий пакет

16:01:11.361381 IP 10.8.0.2 > 10.8.0.3: ICMP echo request, id 21126, seq 2, length 64 # входящий пакет
16:01:11.361405 IP 123.123.123.123 > 10.8.0.2: ICMP redirect 10.8.0.3 to host 10.8.0.3, length 92
16:01:11.361408 IP 10.8.0.2 > 10.8.0.3: ICMP echo request, id 21126, seq 2, length 64 # исходящий пакет
16:01:11.371103 IP 10.8.0.3 > 10.8.0.2: ICMP echo reply, id 21126, seq 2, length 64 # входящий пакет
16:01:11.371121 IP 123.123.123.123 > 10.8.0.3: ICMP redirect 10.8.0.2 to host 10.8.0.2, length 92
16:01:11.371122 IP 10.8.0.3 > 10.8.0.2: ICMP echo reply, id 21126, seq 2, length 64 # исходящий пакет

16:01:12.362456 IP 10.8.0.2 > 10.8.0.3: ICMP echo request, id 21126, seq 3, length 64 # входящий пакет
16:01:12.362475 IP 123.123.123.123 > 10.8.0.2: ICMP redirect 10.8.0.3 to host 10.8.0.3, length 92
16:01:12.362477 IP 10.8.0.2 > 10.8.0.3: ICMP echo request, id 21126, seq 3, length 64 # исходящий пакет
16:01:12.372914 IP 10.8.0.3 > 10.8.0.2: ICMP echo reply, id 21126, seq 3, length 64 # входящий пакет
16:01:12.372936 IP 123.123.123.123 > 10.8.0.3: ICMP redirect 10.8.0.2 to host 10.8.0.2, length 92
16:01:12.372939 IP 10.8.0.3 > 10.8.0.2: ICMP echo reply, id 21126, seq 3, length 64 # исходящий пакет

От хоста 10.8.0.2 идет request на хост 10.8.0.3, но через 10.8.0.1 (у клиентов связь только с сервером). Сервер видит, что 10.8.0.2 отправляет пакеты для 10.8.0.3 не напрямую, а через него (хотя они в одной подсети). Он отправляет полученный request на хост 10.8.0.3, но дополнительно отправляет хосту 10.8.0.2 сообщение переадресации redirect, что есть более удобный маршрут. Хост 10.8.0.3 получает request от 10.8.0.2 и отправляет reply — тоже не напрямую, а через 10.8.0.1. Сервер отправляет request на хост 10.8.0.2, но дополнительно отправляет сообщение redirect хосту 10.8.0.3.

Редиректы используются маршрутизаторами, чтобы известить хост о наличии более удобного маршрута, ведущего к определенному пункту назначения. Но в нашем случае редиректы только мешают, так что давайте их запретим для интерфейса tun0:

$ sudo nano /etc/sysctl.conf
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.tun0.send_redirects = 0
net.ipv4.conf.ens3.send_redirects = 1
$ sudo sysctl -p
net.ipv4.ip_forward = 1
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.tun0.send_redirects = 0
net.ipv4.conf.ens3.send_redirects = 1

Опять выполним команду tcpdump на сервере, а с gateway1 будем пинговать gateway2:

$ sudo tcpdump -i tun0 icmp # выполняем на сервере
$ ping -c3 10.8.0.3 # выполняем на gateway1
PING 10.8.0.3 (10.8.0.3) 56(84) bytes of data.
64 bytes from 10.8.0.3: icmp_seq=1 ttl=63 time=25.8 ms
64 bytes from 10.8.0.3: icmp_seq=2 ttl=63 time=24.8 ms
64 bytes from 10.8.0.3: icmp_seq=3 ttl=63 time=34.5 ms

--- 10.8.0.3 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2004ms
rtt min/avg/max/mdev = 24.844/28.411/34.566/4.372 ms
$ sudo tcpdump -i tun0 icmp # смотрим на сервере
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on tun0, link-type RAW (Raw IP), capture size 262144 bytes
13:04:39.992716 IP 10.8.0.2 > 10.8.0.3: ICMP echo request, id 13751, seq 1, length 64 # входящий пакет
13:04:39.992735 IP 10.8.0.2 > 10.8.0.3: ICMP echo request, id 13751, seq 1, length 64 # исходящий пакет
13:04:40.002855 IP 10.8.0.3 > 10.8.0.2: ICMP echo reply, id 13751, seq 1, length 64 # входящий пакет
13:04:40.002863 IP 10.8.0.3 > 10.8.0.2: ICMP echo reply, id 13751, seq 1, length 64 # исходящий пакет

13:04:40.995066 IP 10.8.0.2 > 10.8.0.3: ICMP echo request, id 13751, seq 2, length 64 # входящий пакет
13:04:40.995078 IP 10.8.0.2 > 10.8.0.3: ICMP echo request, id 13751, seq 2, length 64 # исходящий пакет
13:04:41.005410 IP 10.8.0.3 > 10.8.0.2: ICMP echo reply, id 13751, seq 2, length 64 # входящий пакет
13:04:41.005420 IP 10.8.0.3 > 10.8.0.2: ICMP echo reply, id 13751, seq 2, length 64 # исходящий пакет

13:04:41.997281 IP 10.8.0.2 > 10.8.0.3: ICMP echo request, id 13751, seq 3, length 64 # входящий пакет
13:04:41.997292 IP 10.8.0.2 > 10.8.0.3: ICMP echo request, id 13751, seq 3, length 64 # исходящий пакет
13:04:42.018631 IP 10.8.0.3 > 10.8.0.2: ICMP echo reply, id 13751, seq 3, length 64 # входящий пакет
13:04:42.018642 IP 10.8.0.3 > 10.8.0.2: ICMP echo reply, id 13751, seq 3, length 64 # исходящий пакет

Здесь видно, что пакеты приходят на интерфейс tun0 сервера, проходят через netfilter (где мы их можем обработать), а потом покидают сервер все с того же интерфейса tun0.

Давайте для примера запретим компьютеру pc3 доступ к серверу 192.168.150.254:

$ sudo iptables -I FORWARD 1 -i tun0 -o tun0 -s 192.168.250.2 -d 192.168.150.254 -j DROP
$ sudo iptables-save > /etc/iptables/rules.v4
$ sudo iptables -L -v --line-numbers
Chain INPUT (policy ACCEPT 1589 packets, 136K bytes)
num   pkts   bytes   target   prot   opt   in     out    source          destination

Chain FORWARD (policy DROP 0 packets, 0 bytes)
num   pkts   bytes   target   prot   opt   in     out    source          destination
1        0     0     DROP     all    --    tun0   tun0   192.168.250.2   192.168.150.254
2        0     0     ACCEPT   all    --    tun0   tun0   anywhere        anywhere

Chain OUTPUT (policy ACCEPT 1586 packets, 206K bytes)
num   pkts   bytes   target   prot   opt   in     out    source          destination

Поиск: Linux • SSL • Ubuntu • VPN • Клиент • Ключ • Конфигурация • Локальная сеть • Маршрутизация • Настройка • Сервер • Установка • Сертификат

Каталог оборудования
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Производители
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Функциональные группы
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.