Как получить DNS от OpenVPN в Arch Linux

На Arch Linux есть специфическая ситуация с получением DNS-серверов при подключении через OpenVPN: это не работает из коробки. Для корректной настройки требуется запускать кастомные скрипты при поднятии и закрытии туннеля. Готовый скрипт можно взять здесь. Файл update-systemd-resolved нужно скопировать в /etc/openvpn/. В конфигурационный файл клиента /etc/openvpn/client/client.conf добавляем следующее:

script-security 2
up /etc/openvpn/update-systemd-resolved
up-restart
down /etc/openvpn/update-systemd-resolved
down-pre

Чтобы весь DNS-трафик шел через туннель, в конфигурационный файл можно добавить:

dhcp-option DOMAIN-ROUTE .

После этого необходимо сделать файл исполняемым и назначить правильного владельца:

chmod +x /etc/openvpn/update-systemd-resolved
chown openvpn:network /etc/openvpn/update-systemd-resolved

Чтобы скрипт мог менять настройки systemd-resolved от имени пользователя openvpn, нужно разрешить ему соответствующие действия через Polkit. Для этого создаём файл /etc/polkit-1/rules.d/00-openvpn-resolved.rules со следующим содержимым:

polkit.addRule(function(action, subject) {
    if (action.id == 'org.freedesktop.resolve1.set-dns-servers' ||
        action.id == 'org.freedesktop.resolve1.set-domains' ||
        action.id == 'org.freedesktop.resolve1.set-dnssec') {
        if (subject.user == 'openvpn') {
            return polkit.Result.YES;
        }
    }
});

Что делает этот скрипт:

  1. Проверяет, какая именно операция выполняется через Polkit (установка DNS, доменов или DNSSEC).
  2. Если действие выполняет пользователь openvpn, оно разрешается (Result.YES).
  3. Это позволяет скрипту update-systemd-resolved менять настройки DNS systemd-resolved без необходимости запускать его от root напрямую.

После настройки нужно перезапустить соответствующие службы и проверить работу. Перезапускаем systemd-resolved:

systemctl restart systemd-resolved

Перезапускаем OpenVPN-клиент:

systemctl restart openvpn-client@client

Проверяем статус DNS и туннеля:

systemd-resolve --status 

Если всё настроено правильно, вывод будет примерно таким:

Link 4 (tun0)
    Current Scopes: DNS LLMNR/IPv4 LLMNR/IPv6 mDNS/IPv4 mDNS/IPv6
         Protocols: +DefaultRoute +LLMNR +mDNS -DNSOverTLS DNSSEC=no/unsupported
Current DNS Server: 1.1.1.1
       DNS Servers: 1.1.1.1 2.2.2.2
        DNS Domain: mydomain.com mydomain.ru
     Default Route: yes
     

Объяснение:

Если нужно, чтобы dns-запросы определённого домена шли через DNS-серверы VPN-интерфейса, можно добавить его вручную через resolvectl. Например:

resolvectl domain tun0 "~ru"

После этого все DNS-запросы .ru будут идти через VPN-туннель tun0, а не через основной интернет-интерфейс.