VPN-клиент на Linux: как NetworkManager управляет маршрутами и DNS при подключении туннеля

Когда VPN-соединение поднимается на Linux-десктопе, за кулисами работает NetworkManager: он добавляет маршруты через туннельный интерфейс, перенастраивает DNS-резолвер и следит за тем, чтобы трафик шёл именно туда, куда ожидает пользователь. Понимание этой механики помогает диагностировать утечки DNS, настраивать split tunneling и разбираться, почему после подключения VPN перестали открываться локальные ресурсы.

Архитектура: что делает NetworkManager при подключении VPN​


NetworkManager не реализует VPN-протоколы самостоятельно. Для каждого типа туннеля существует плагин:

  • NetworkManager-openvpn — для OpenVPN
  • NetworkManager-wireguard (или nm-wireguard) — для WireGuard
  • NetworkManager-strongswan — для IKEv2/IPsec
  • NetworkManager-libreswan — для Libreswan/IPsec

Плагин получает параметры из профиля соединения, запускает соответствующий VPN-демон или настраивает интерфейс, а затем передаёт NetworkManager набор маршрутов и DNS-серверов, которые тот применяет к системе.

Профили хранятся в /etc/NetworkManager/system-connections/ в формате keyfile (INI-подобный формат). Каждый профиль содержит секции [connection], [ipv4], [ipv6] и специфичную для VPN секцию (например, [vpn]).

Управление маршрутами​


При активации VPN-соединения NetworkManager выполняет два действия:

  1. Создаёт или настраивает туннельный интерфейс. Для WireGuard это wg0, wg1 и т. д. Для OpenVPN — tun0 или tap0. Интерфейс получает IP-адрес из пула VPN-сервера.
  2. Добавляет маршруты через этот интерфейс. Конкретный набор зависит от конфигурации.

Full tunnel (весь трафик через VPN)​


Если в профиле не указано ipv4.never-default = true, NetworkManager добавляет маршрут по умолчанию (0.0.0.0/0) через туннельный интерфейс. Оригинальный default route заменяется или получает бо́льшую метрику, чтобы туннельный маршрут имел приоритет.

В случае WireGuard это напрямую связано с параметром AllowedIPs: значение 0.0.0.0/0 означает, что все исходящие пакеты шифруются и отправляются через туннель. При использовании плагина NetworkManager для WireGuard этот параметр из конфигурационного файла транслируется в маршрут по умолчанию через интерфейс wg0.

Split tunnel (часть трафика через VPN)​


Если ipv4.never-default = true, NetworkManager не добавляет default route через туннель. Вместо этого добавляются только маршруты к конкретным подсетям, указанным в конфигурации VPN-сервера или вручную в профиле.

Пример: корпоративный VPN даёт доступ к 10.0.0.0/8, но весь остальной трафик идёт напрямую. В профиле это выглядит так:

INI:
[ipv4]
method=auto
never-default=true
route1=10.0.0.0/8

Или через nmcli:

Bash:
nmcli connection modify "Corp VPN" ipv4.never-default yes
nmcli connection modify "Corp VPN" +ipv4.routes "10.0.0.0/8"

Метрики маршрутов​


Когда в системе несколько интерфейсов с маршрутами по умолчанию (например, Wi-Fi и VPN), NetworkManager использует метрику (ipv4.route-metric) для определения приоритета. Меньшая метрика = выше приоритет. Значения по умолчанию зависят от типа соединения и версии NetworkManager; как правило, VPN-соединения получают меньшую метрику, чем проводные или беспроводные интерфейсы, что обеспечивает приоритет туннеля.

Проверить текущие метрики:

Bash:
nmcli -f NAME,DEVICE,TYPE connection show --active
ip route show table main

Если маршруты конфликтуют, метрику можно задать явно:

Bash:
nmcli connection modify "My VPN" ipv4.route-metric 50

Управление DNS​


DNS — наиболее частый источник проблем при работе VPN на Linux. NetworkManager поддерживает несколько бэкендов для применения DNS-настроек:

БэкендКак работаетГде встречается
systemd-resolvedПередаёт DNS-серверы через D-Bus в systemd-resolved, который ведёт per-link конфигурациюFedora, Ubuntu (начиная с 22.04), Arch
dnsmasqЗапускает локальный dnsmasq как кэширующий резолвер, пересылает запросы к нужным серверамСтарые версии Ubuntu, опционально
resolvconfЗаписывает в /etc/resolv.conf через утилиту resolvconfDebian, Gentoo
none / directNetworkManager сам пишет /etc/resolv.confМинимальные установки

Определить активный бэкенд:

Bash:
grep -i dns /etc/NetworkManager/NetworkManager.conf
resolvectl status   # если используется systemd-resolved

Приоритеты DNS-серверов​


Когда одновременно активны несколько соединений (Wi-Fi + VPN), каждое может предлагать свои DNS-серверы. NetworkManager разрешает конфликт через ipv4.dns-priority:

  • Значение по умолчанию: 0.
  • Отрицательное значение (например, -100) означает, что DNS этого соединения имеет наивысший приоритет и используется эксклюзивно.
  • Положительное значение — сервер добавляется в список, но не вытесняет другие.

Типичная настройка для VPN, чтобы гарантировать использование только VPN-DNS:

Bash:
nmcli connection modify "My VPN" ipv4.dns-priority -100

DNS-домены поиска​


VPN-сервер может передавать домены поиска (search domains). Например, корпоративный VPN добавляет corp.internal, и запрос gitlab резолвится как gitlab.corp.internal. Это настраивается через ipv4.dns-search:

Bash:
nmcli connection modify "Corp VPN" ipv4.dns-search "corp.internal"

Предотвращение утечек DNS​


Утечка DNS при работе VPN происходит, когда запросы уходят не через туннель, а через DNS-сервер провайдера. Причины:

  1. NetworkManager не переназначил DNS. Бэкенд resolvconf или прямая запись в /etc/resolv.conf может не обновиться, если VPN-плагин не передал серверы корректно.
  2. systemd-resolved кэширует старый сервер. Per-link DNS не обновился, и запросы уходят через link с более высоким приоритетом.
  3. IPv6 DNS не перекрыт. VPN туннелирует только IPv4, а DNS-запрос уходит по IPv6 к серверу провайдера.

Проверка текущего состояния​


Bash:
## Текущий резолвер
cat /etc/resolv.conf

## Если systemd-resolved:
resolvectl status
resolvectl dns

## Тестовый запрос с указанием интерфейса
resolvectl query example.com --interface=tun0

Для комплексной проверки утечек существуют внешние сервисы (dnsleaktest.com, ipleak.net), которые показывают, какие DNS-серверы фактически обрабатывают запросы. Подробнее — в материале DNS leak: как VPN может скрыть IP, но выдать DNS-запросы, и как это проверить.

Рекомендуемая конфигурация против утечек​


Bash:
## Принудительно использовать только DNS VPN-сервера
nmcli connection modify "My VPN" ipv4.dns-priority -100

## Отключить IPv6 на туннеле, если VPN не поддерживает IPv6
nmcli connection modify "My VPN" ipv6.method disabled

## Перезапустить соединение
nmcli connection down "My VPN" && nmcli connection up "My VPN"

Диагностика через nmcli и ip​


Полезные команды для проверки состояния после подключения VPN:

Bash:
## Активные соединения и их устройства
nmcli connection show --active

## Детали конкретного соединения (маршруты, DNS)
nmcli connection show "My VPN"

## Таблица маршрутов
ip route show

## Адреса на туннельном интерфейсе
ip addr show tun0    # для OpenVPN
ip addr show wg0     # для WireGuard

## Статус systemd-resolved по интерфейсам
resolvectl status tun0
resolvectl status wg0

Типичные проблемы и решения​


VPN подключается, но трафик не идёт через туннель​


Причина: метрика маршрута по умолчанию через VPN выше, чем у основного интерфейса. Проверьте ip route show — default route должен указывать на туннельный интерфейс с наименьшей метрикой.

Решение:

Bash:
nmcli connection modify "My VPN" ipv4.route-metric 50

После отключения VPN нет доступа в интернет​


NetworkManager не восстановил оригинальный default route. Это происходит, если VPN-плагин некорректно удалил маршруты или если NetworkManager был перезапущен во время активной сессии.

Решение:

Bash:
nmcli networking off && nmcli networking on
## или
systemctl restart NetworkManager

DNS не переключается на сервер VPN​


Проверьте, что VPN-профиль действительно передаёт DNS-серверы. Для OpenVPN это директива dhcp-option DNS в конфигурации сервера. Для WireGuard DNS-сервер обычно указывается в секции [Interface] клиентского конфига как DNS = ..., и плагин NetworkManager должен его подхватить.

Если серверы не появляются в resolvectl status, проверьте логи:

Bash:
journalctl -u NetworkManager --since "5 min ago" | grep -i dns

Конфликт с systemd-resolved и dnsmasq​


Если в системе одновременно запущены systemd-resolved и dnsmasq (например, dnsmasq как часть libvirt), они могут конфликтовать за порт 53. NetworkManager в этом случае не может корректно применить DNS.

Проверка:

Bash:
ss -tlnp | grep :53

Если порт занят несколькими процессами, отключите один из бэкендов или настройте dnsmasq на другой порт.

Взаимодействие с firewall и kill switch​


NetworkManager не управляет правилами iptables/nftables напрямую. Если нужно гарантировать, что трафик не пойдёт мимо туннеля (kill switch), это реализуется отдельно через правила файрвола.

Принцип kill switch: разрешить исходящий трафик только через туннельный интерфейс, а всё остальное — заблокировать, оставив исключение для самого VPN-сервера (чтобы туннель мог установиться).

Пример для nftables (WireGuard, сервер 203.0.113.1, порт 51820):

Bash:
## Разрешить трафик к VPN-серверу (для установки туннеля)
nft add rule inet filter output ip daddr 203.0.113.1 udp dport 51820 accept

## Разрешить весь трафик через туннельный интерфейс
nft add rule inet filter output oifname "wg0" accept

## Заблокировать остальной исходящий трафик
nft add rule inet filter output drop

Правила применяются последовательно: первое совпадение определяет действие. Без kill switch при обрыве туннеля трафик мгновенно пойдёт через основной интерфейс, что может привести к утечке реального IP. Подробнее о том, что видит провайдер при использовании VPN и без него — в материале Что видит интернет-провайдер при использовании VPN: метаданные, DNS и границы приватности.

Итоговый чек-лист настройки​


  • Убедитесь, что ipv4.never-default соответствует желаемому режиму (full/split tunnel).
  • Установите ipv4.dns-priority -100 для VPN-соединения, если хотите эксклюзивное использование VPN-DNS.
  • Отключите IPv6 на туннеле, если VPN-провайдер его не поддерживает.
  • Проверьте resolvectl status после подключения: DNS-серверы должны принадлежать VPN.
  • Настройте kill switch через nftables, если критична защита от утечек при обрыве.
  • Протестируйте на dnsleaktest.com или аналогичном сервисе.

Источники​


 
Назад
Верх Низ