VPN_Linux

Настройка VPN в Linux

VPN (Virtual Private Network) создаёт защищённый туннель поверх другой сети. Он применяется для удалённого доступа, объединения площадок и направления трафика через защищённый шлюз.

Основные режимы:

Перед изменением сети удалённого сервера подготовьте резервный доступ через консоль. Имена пакетов, служб и пути могут различаться между дистрибутивами.


Выбор технологии

Технология Особенности Применение
WireGuard Простая конфигурация, высокая производительность, ключи peer-to-peer Новые VPN, remote access, site-to-site
OpenVPN TLS/PKI, UDP или TCP, широкая совместимость Сложные и устаревшие инфраструктуры
IPsec/IKEv2 Стандартный стек, поддержка многими ОС Корпоративный доступ, мобильные клиенты, site-to-site
L2TP/IPsec L2TP внутри IPsec, обычно IKEv1 и общий PSK Совместимость с существующими системами

L2TP без IPsec не обеспечивает надёжной защиты. Для новых установок обычно выбирают WireGuard или IKEv2.


Общая подготовка

Проверка интерфейсов, маршрутов и портов:

ip -brief address
ip route
ip -6 route
ss -lntup
ip route get 1.1.1.1

VPN-подсети не должны пересекаться с сетями клиентов и площадок. Пример:

VPN:             10.20.0.0/24
Офисная сеть:    10.30.0.0/24
Удалённая сеть:  10.40.0.0/24

Включение IPv4 forwarding:

sudo sysctl -w net.ipv4.ip_forward=1

Постоянная настройка /etc/sysctl.d/99-vpn.conf:

net.ipv4.ip_forward = 1

Применение:

sudo sysctl --system

Для маршрутизации IPv6 при необходимости:

net.ipv6.conf.all.forwarding = 1

Если клиенты выходят в интернет через VPN-сервер, обычно нужны forwarding и NAT. Пример для VPN-сети 10.20.0.0/24, интерфейсов wg0 и eth0:

sudo iptables -A FORWARD -i wg0 -o eth0 -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o wg0 \
  -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -t nat -A POSTROUTING \
  -s 10.20.0.0/24 -o eth0 -j MASQUERADE

Не управляйте одними правилами одновременно через iptables, nftables, ufw и firewalld.


WireGuard

WireGuard создаёт виртуальный интерфейс. Узлы идентифицируются открытыми ключами, а AllowedIPs одновременно участвует в маршрутизации и проверке адресов peer.

Установка

# Debian/Ubuntu
sudo apt update && sudo apt install wireguard

# Fedora/RHEL-подобные
sudo dnf install wireguard-tools

# Arch Linux
sudo pacman -S wireguard-tools

Ключи

На сервере:

sudo install -d -m 700 /etc/wireguard
umask 077
wg genkey | sudo tee /etc/wireguard/server.key | \
  wg pubkey | sudo tee /etc/wireguard/server.pub >/dev/null

На клиенте:

umask 077
wg genkey | tee client.key | wg pubkey > client.pub

Закрытые ключи нельзя публиковать и помещать в Git.

Сервер

/etc/wireguard/wg0.conf:

[Interface]
Address = 10.20.0.1/24
ListenPort = 51820
PrivateKey = SERVER_PRIVATE_KEY

[Peer]
# laptop
PublicKey = CLIENT_PUBLIC_KEY
AllowedIPs = 10.20.0.2/32
sudo chmod 600 /etc/wireguard/wg0.conf
sudo systemctl enable --now wg-quick@wg0
sudo wg show

Открытие порта:

sudo iptables -A INPUT -p udp --dport 51820 -j ACCEPT

Клиент

[Interface]
Address = 10.20.0.2/32
PrivateKey = CLIENT_PRIVATE_KEY
DNS = 10.20.0.1

[Peer]
PublicKey = SERVER_PUBLIC_KEY
Endpoint = vpn.example.com:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25

0.0.0.0/0, ::/0 создаёт full tunnel. Для split tunnel:

AllowedIPs = 10.20.0.0/24, 10.30.0.0/24

Управление:

sudo wg-quick up wg0
sudo wg-quick down wg0
sudo systemctl restart wg-quick@wg0

PersistentKeepalive = 25 полезен клиенту за NAT. Каждому клиенту на сервере назначают уникальный /32; пересекающиеся AllowedIPs приводят к неправильному выбору peer.

Site-to-site

На площадке A, где удалённая сеть B — 10.40.0.0/24:

[Peer]
PublicKey = SITE_B_PUBLIC_KEY
Endpoint = site-b.example.com:51820
AllowedIPs = 10.20.0.2/32, 10.40.0.0/24
PersistentKeepalive = 25

На B, где сеть A — 10.30.0.0/24:

[Peer]
PublicKey = SITE_A_PUBLIC_KEY
Endpoint = site-a.example.com:51820
AllowedIPs = 10.20.0.1/32, 10.30.0.0/24
PersistentKeepalive = 25

На обоих шлюзах нужны forwarding, firewall и обратные маршруты. NAT между площадками обычно не нужен.

NetworkManager

sudo nmcli connection import type wireguard file ./wg0.conf
sudo nmcli connection up wg0
sudo nmcli connection down wg0

OpenVPN

OpenVPN использует TLS и PKI. Обычно применяется tun. UDP предпочтителен; TCP полезен в ограниченных сетях, но VPN поверх TCP может снижать производительность.

Установка

# Debian/Ubuntu
sudo apt install openvpn easy-rsa

# Fedora/RHEL-подобные
sudo dnf install openvpn easy-rsa

# Arch Linux
sudo pacman -S openvpn easy-rsa

Создание PKI

make-cadir ~/openvpn-ca
cd ~/openvpn-ca
./easyrsa init-pki
./easyrsa build-ca
./easyrsa gen-req server nopass
./easyrsa sign-req server server
./easyrsa gen-req client1 nopass
./easyrsa sign-req client client1
./easyrsa gen-crl
openvpn --genkey secret tls-crypt.key

Закрытый ключ CA желательно хранить отдельно от публичного VPN-сервера. Каждый клиент должен иметь отдельный сертификат.

Сервер

Пример /etc/openvpn/server/server.conf:

port 1194
proto udp
dev tun

ca /etc/openvpn/server/ca.crt
cert /etc/openvpn/server/server.crt
key /etc/openvpn/server/server.key
crl-verify /etc/openvpn/server/crl.pem
tls-crypt /etc/openvpn/server/tls-crypt.key

server 10.21.0.0 255.255.255.0
topology subnet
push "route 10.30.0.0 255.255.255.0"
push "dhcp-option DNS 10.20.0.1"

keepalive 10 120
persist-key
persist-tun
user nobody
group nogroup
verb 3
explicit-exit-notify 1

Запуск и проверка:

sudo systemctl enable --now openvpn-server@server
systemctl status openvpn-server@server
journalctl -u openvpn-server@server
ip address show tun0

Имя systemd-юнита может отличаться:

systemctl list-unit-files | grep -i openvpn

Клиент

client
dev tun
proto udp
remote vpn.example.com 1194
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
verb 3

<ca>
...
</ca>
<cert>
...
</cert>
<key>
...
</key>
<tls-crypt>
...
</tls-crypt>
sudo openvpn --config client1.ovpn
sudo nmcli connection import type openvpn file ./client1.ovpn

Full tunnel:

push "redirect-gateway def1"

Split tunnel:

push "route 10.30.0.0 255.255.255.0"
push "route 10.40.0.0 255.255.255.0"

Отзыв клиента:

./easyrsa revoke client1
./easyrsa gen-crl

После этого новый crl.pem необходимо установить на сервер.


IPsec/IKEv2

IPsec защищает IP-трафик, а IKEv2 согласует параметры, выполняет аутентификацию и управляет ключами. В Linux часто применяется strongSwan.

Порты и протоколы:

Установка strongSwan

# Debian/Ubuntu
sudo apt install strongswan strongswan-pki

# Fedora/RHEL-подобные
sudo dnf install strongswan

# Arch Linux
sudo pacman -S strongswan

Современный интерфейс strongSwan — swanctl; традиционный — ipsec.conf. Сертификат сервера должен содержать DNS-имя, например vpn.example.com, в SAN. CA должна быть доверенной клиентом.

Пример IKEv2 remote access

/etc/swanctl/swanctl.conf:

connections {
  ikev2-eap {
    version = 2
    send_cert = always
    proposals = aes256gcm16-prfsha384-ecp384,aes256-sha256-modp2048
    pools = vpn-pool

    local {
      auth = pubkey
      certs = server-cert.pem
      id = vpn.example.com
    }
    remote {
      auth = eap-mschapv2
      eap_id = %any
    }
    children {
      net {
        local_ts = 0.0.0.0/0
        esp_proposals = aes256gcm16-ecp384,aes256-sha256
      }
    }
  }
}

pools {
  vpn-pool {
    addrs = 10.22.0.0/24
    dns = 10.20.0.1
  }
}

secrets {
  eap-user1 {
    id = user1
    secret = "REPLACE_WITH_A_STRONG_PASSWORD"
  }
}

Каталоги swanctl:

/etc/swanctl/x509/       сертификаты узлов
/etc/swanctl/x509ca/     сертификаты CA
/etc/swanctl/private/    закрытые ключи
sudo swanctl --load-all
sudo swanctl --list-conns
sudo swanctl --list-certs
sudo swanctl --list-sas

Нужные EAP-плагины и имя службы зависят от пакета:

systemctl list-unit-files | grep -E 'strongswan|charon'

Firewall:

sudo iptables -A INPUT -p udp --dport 500 -j ACCEPT
sudo iptables -A INPUT -p udp --dport 4500 -j ACCEPT
sudo iptables -A INPUT -p esp -j ACCEPT

Для клиентов также настраиваются forwarding и при необходимости NAT.

Site-to-site

connections {
  site-b {
    version = 2
    remote_addrs = 203.0.113.20
    local {
      auth = pubkey
      certs = site-a.pem
      id = site-a.example.com
    }
    remote {
      auth = pubkey
      id = site-b.example.com
    }
    children {
      lan-to-lan {
        local_ts = 10.30.0.0/24
        remote_ts = 10.40.0.0/24
        start_action = start
        close_action = restart
        dpd_action = restart
      }
    }
  }
}

На второй стороне локальные и удалённые параметры меняются местами.


L2TP/IPsec

L2TP создаёт туннель, а IPsec защищает его. В Linux часто используются strongSwan, xl2tpd и PPP.

Порты: UDP 500, 4500, 1701 и ESP. UDP 1701 не следует открывать в интернет без ограничения политикой IPsec.

# Debian/Ubuntu
sudo apt install strongswan xl2tpd ppp

Пример /etc/ipsec.conf:

config setup
  uniqueids=no

conn l2tp-psk
  type=transport
  keyexchange=ikev1
  authby=psk
  left=%defaultroute
  leftprotoport=17/1701
  right=%any
  rightprotoport=17/%any
  auto=add

/etc/ipsec.secrets:

: PSK "REPLACE_WITH_A_LONG_RANDOM_SECRET"
sudo chmod 600 /etc/ipsec.secrets

/etc/xl2tpd/xl2tpd.conf:

[global]
port = 1701

[lns default]
ip range = 10.23.0.10-10.23.0.200
local ip = 10.23.0.1
require authentication = yes
require chap = yes
refuse pap = yes
pppoptfile = /etc/ppp/options.xl2tpd
length bit = yes

/etc/ppp/options.xl2tpd:

name l2tp-server
refuse-pap
refuse-chap
refuse-mschap
require-mschap-v2
proxyarp
mtu 1280
mru 1280
lock
hide-password

/etc/ppp/chap-secrets:

user1  l2tp-server  REPLACE_WITH_A_STRONG_PASSWORD  *
sudo chmod 600 /etc/ppp/chap-secrets
systemctl list-unit-files | grep -E 'strongswan|ipsec|xl2tpd'

PSK является общим секретом IPsec и не заменяет учётные данные PPP. Общий PSK неудобен для индивидуального отзыва, поэтому L2TP/IPsec обычно оставляют для совместимости.


DNS, маршруты и MTU

VPN может направлять весь DNS через туннель или применять split DNS только для внутренних доменов.

resolvectl status
resolvectl query internal.example
dig @10.20.0.1 internal.example

Если доступ по IP работает, а по имени — нет, проверьте DNS-адрес, маршрут, UDP/TCP 53, разрешённые подсети на DNS-сервере и интеграцию клиента с NetworkManager или systemd-resolved.

Для доступа к внутренней сети нужен обратный маршрут к VPN-подсети. Альтернатива — SNAT/MASQUERADE, но тогда внутренние узлы не видят реальные адреса клиентов.

Инкапсуляция уменьшает MTU. Признаки проблемы: небольшие пакеты проходят, большие соединения зависают.

ping -M do -s 1372 1.1.1.1
tracepath 1.1.1.1

Для WireGuard часто используется MTU около 1420, но значение зависит от нижележащей сети.


Диагностика

ip -brief address
ip route
ip rule
ip route get 10.30.0.10
sysctl net.ipv4.ip_forward
sudo nft list ruleset
sudo iptables -L -n -v
sudo iptables -t nat -L -n -v

Захват внешнего трафика:

sudo tcpdump -ni any udp port 51820
sudo tcpdump -ni any udp port 1194
sudo tcpdump -ni any 'udp port 500 or udp port 4500'

WireGuard:

sudo wg show

Если latest handshake отсутствует, проверяются ключи, Endpoint, порт и firewall. Если handshake есть, но трафика нет, проверяются AllowedIPs, маршруты, forwarding и NAT.

OpenVPN:

journalctl -u openvpn-server@server --since today
sudo openvpn --config client1.ovpn --verb 4

strongSwan:

sudo swanctl --list-sas
sudo ipsec statusall
ip xfrm state
ip xfrm policy

Проверка внутри туннеля:

sudo tcpdump -ni wg0
sudo tcpdump -ni tun0

Если пакет виден внутри VPN, но не выходит наружу, причина обычно в forwarding, firewall, NAT или обратном маршруте.


Безопасность и типичные ошибки

timedatectl status
openssl x509 -in server.crt -noout -subject -issuer -dates -ext subjectAltName

Если туннель поднят, но сеть недоступна, последовательно проверяйте маршрут клиента, ip_forward, FORWARD, NAT и обратный маршрут.


Краткая памятка

# WireGuard
sudo systemctl enable --now wg-quick@wg0
sudo wg show

# OpenVPN
sudo openvpn --config client.ovpn
sudo journalctl -u openvpn-server@server

# strongSwan
sudo swanctl --load-all
sudo swanctl --list-sas
sudo ipsec statusall

# Сеть
ip -brief address
ip route
sysctl net.ipv4.ip_forward
sudo nft list ruleset

Рекомендуемый порядок внедрения: выбрать протокол и подсеть, настроить DNS-имя и время, создать ключи или сертификаты, подключить одного тестового клиента, открыть нужные порты, включить forwarding, добавить маршруты или NAT, проверить DNS и MTU, затем настроить автозапуск, отзыв доступа, резервное копирование и мониторинг.