Перейти к содержанию

Как настроить DNS на Ubuntu с VPN

Дано

  1. Имеется личный ноутбук с ОС Ubuntu 22.04.
  2. Для разрешения DNS-имен используется локальный сервис systemd-resolved(1).
  3. На работе выдали настройки VPN-подключения к корпоративной сети.
  4. Сразу после подключения отвалился резолвинг внешних (2) доменных имен. Резолвинг внутренних (3) доменов тоже не работает.
  5. А ещё, VPN-сервер анонсировал дефолтный маршрут к себе и руинит всю маршрутизацию. В общем, не работает ни-че-го :-).
  1. systemd-resolved — это компонент системы инициализации systemd, который отвечает за разрешение DNS-запросов. Он предоставляет кэширование DNS-запросов, поддержку DNS через TLS (DoT) и DNS через HTTPS (DoH), а также может работать с различными источниками DNS, включая традиционные DNS-серверы, MDNS и LLMNR.

    systemd-resolved может управлять DNS-запросами для различных сетевых интерфейсов и поддерживает конфигурацию через D-Bus и конфигурационные файлы.
  2. Внешние домены: Используются для доступа к ресурсам из интернета, доступные для всех пользователей.
  3. Внутренние домены: Используются в локальных сетях и не доступны из интернета (например, домены, используемые в корпоративных сетях).

Задача

  1. Обеспечить корректное резрешение внешних доменов при отключенном VPN с использованием публичных NS-серверов.
  2. Обеспечить корректное резрешение внешних и внутренних DNS-имен при подключенном VPN с использованием публичных и корпоративных NS-серверов. Внешние имена идем разрешать в Интернет. Внутренние — в контур компании.
  3. Обеспечить корректную маршрутизацию трафика при подключенном VPN, чтобы работал доступ как к публичным, так и корпоративным ресурсам. А то DNS-имена могут успешно разрешаться, но Интернет-сайты при этом не загружаться.

Решение

Шаг 1. Настройка резолвинга DNS-имен.

Документация dnsmasq.

  1. Сначала нужно установить dnsmasq. На следующем шаге мы отключаем systemd-resolved и резолвинг DNS-имен не будет работать, т.е. установить пакет не получится.
    sudo apt update
    sudo apt install dnsmasq
    
  2. Затем нужно остановить и отключить systemd-resolved, т.к. он не поддерживает условный резолвинг по имени доменов. Это когда внешние домены мы идем разрешать на публичные NS-сервера, а предзаданный список внутренних доменов на корпоративные. По крайней мере у меня так и не удалось заставить его корректно работать, сколько я ни указывал опцию Domains=.
    sudo systemctl stop systemd-resolved
    sudo systemctl disable systemd-resolved
    sudo systemctl mask systemd-resolved
    
  3. Далее удаляем символическую ссылку /etc/resolv.conf:
    sudo unlink /etc/resolv.conf
    
  4. Создаем новый файл /etc/resolv.conf:
    sudo nano /etc/resolv.conf
    
  5. Добавляем в него следующую строку:
    # Все локальные сервисы будут идти на этот адрес за разрешением DNS-имён.
    nameserver 127.0.0.53
    
  6. Открываем файл конфигурации dnsmasq:
    sudo nano /etc/dnsmasq.conf
    
  7. Вносим следующие изменения:
    /etc/dnsmasq.conf
    # Never forward plain names (without a dot or domain part)
    domain-needed
    
    # Add other name servers here, with domain specs if they are for
    # non-public domains.
    # Corporate NS1
    server=/your-corporate-domain.dev/YOUR_CORPORATE_NS1_IP
    server=/your-corporate-domain.tech/YOUR_CORPORATE_NS1_IP
    ...
    # Corporate NS2
    server=/your-corporate-domain.dev/YOUR_CORPORATE_NS2_IP
    server=/your-corporate-domain.tech/YOUR_CORPORATE_NS2_IP
    ...
    
    # You can control how dnsmasq talks to a server: this forces
    # queries to 10.1.2.3 to be routed via eth1
    # server=10.1.2.3@eth1
    # Настройки для корпоративных доменов.
    # Корпоративные DNS-серверы через VPN-туннель.
    server=YOUR_CORPORATE_NS1_IP@tun0
    server=YOUR_CORPORATE_NS2_IP@tun0
    ...
    
    # Настройки для всех остальных доменов.
    # Публичные DNS-серверы через интерфейс WiFi.
    server=1.1.1.1@wlp0s20f3 (1)
    server=8.8.8.8@wlp0s20f3
    ...
    
    # If you want dnsmasq to listen for DHCP and DNS requests only on
    # specified interfaces (and the loopback) give the name of the
    # interface (eg eth0) here.
    # Repeat the line for more than one interface.
    #interface=
    # Or you can specify which interface _not_ to listen on
    #except-interface=
    # Or which to listen on by address (remember to include 127.0.0.1 if
    # you use this.)
    listen-address=127.0.0.53 (2)
    listen-address=172.17.0.1 (3)
    
    # Set the cachesize here.
    cache-size=150
    
    # If you want to disable negative caching, uncomment this.
    no-negcache
    
  8. Перезапускаем dnsmasq:
    sudo systemctl restart dnsmasq
    
  1. Идентификатор интерфейса см. с помощью команды nmcli или nmcli device show | grep GENERAL.DEVICE.
  2. Слушать на localhost для обслуживания запросов от сервисов и приложений хоста.
  3. Слушать на дефолтном IP шлюза сети Docker для обслуживания запросов из контейнеров. В команды запуска контейнеров нужно добавлять аргумент --dns 172.17.0.1.

Теперь для резолвинга DNS-имен будет использоваться dnsmasq. Запросы для корпоративных доменов будут направляться через VPN-туннель к корпоративным DNS-серверам, а все остальные запросы будут обрабатываться публичными DNS-серверами.

Далее необходимо настроить VPN-соединение.

Шаг 2. Настройка VPN-соединения.

  1. Заходим в настройки VPN-соединения в GUI (NetworkManager) Ubuntu.
  2. Вкладка IPv4:
    1. IPv4 Method: Automatic (DHCP);
    2. DNS: Automatic;
    3. Routes: Automatic;
    4. Use this connection only for resources on its network — включить. Это деактивирует получение default маршрута из VPN-туннеля.

Осталось проверить сетап.

Шаг 3. Диагностические команды (опционально)

sudo systemctl status dnsmasq
journalctl -u dnsmasq
sudo lsof -i :53
sudo netstat -tuln | grep :53
sudo ss -tuln | grep :53

Шаг 4. Проверка разрешения DNS-имен.

  1. При отключенном VPN-туннеле:
    1. Проверка разрешения DNS-имен:
      # внешний домен должен успешно отрезолвиться, иначе тест провален
      nslookup external.domain
      
    2. Проверка доступности Интернет-сайтов:
      1. Открыть в браузере Интернет-сайт. Должен загрузиться, иначе тест провален.
  2. При включенном VPN-туннеле:
    1. Проверка разрешения DNS-имен:
      # внешний домен должен успешно отрезолвиться, иначе тест провален
      nslookup external.domain
      
      # внутренний домен должен успешно отрезолвиться, иначе тест провален
      nslookup internal.tomain
      
    2. Проверка доступности внешних и внутренних сайтов:
      1. Открыть в браузере Интернет-сайт. Должен загрузиться, иначе тест провален.
      2. Открыть в браузере корпоративный сайт. Должен загрузиться, иначе тест провален.

Если все проверки прошли успешно, поздравляю! 🎉

Сетап работает корректно, можно эффективно работать с внешними и корпоративными ресурсами при поднятом VPN-туннеле.

Что дальше?

  1. Нашли эту статью полезной? Поделитесь ею и помогите распространить знания!
  2. Нашли ошибку или есть идеи 💡 о том, что и как я могу улучшить? Напишите мне в Telegram.
  3. Хотите узнать обо мне больше? Читайте здесь.