Як зробити DNS-запити приватними на рівні всієї системи у Debian/Ubuntu? Простий і надійний шлях — поєднати systemd-resolved як локальний кешуючий резолвер із cloudflared як проксі для DNS-over-HTTPS (DoH). У цій інструкції ви отримаєте зрозумілий план дій, fallback-варіанти та перевірки. Усе — через термінал Linux, без зайвих слів 🙂
Що саме ми налаштуємо
Ми встановимо й увімкнемо cloudflared у режимі proxy-dns на локальному порту (5053), а systemd-resolved направимо туди всі DNS-запити. Upstream-сервери в cloudflared працюватимуть по DoH (Cloudflare). Додамо fallback, щоб мережа не "падала", навіть якщо локальний DoH зупиниться.
Підготовка: перевірте systemd-resolved
Спочатку впевніться, що systemd-resolved увімкнений, а ваш /etc/resolv.conf вказує на локальний stub 127.0.0.53. Це базові мережеві налаштування перед інтеграцією з DoH.
sudo systemctl enable --now systemd-resolved
systemctl --no-pager status systemd-resolved
resolvectl status
ls -l /etc/resolv.conf
# Якщо це не симлінк на stub, виправляємо:
sudo ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
Після цього резолвер системи керується systemd-resolved. Далі встановимо cloudflared через apt команди.
Встановлення cloudflared (DNS-over-HTTPS проксі)
Додавання репозиторію та інсталяція
Офіційний репозиторій Cloudflare має окремий компонент для cloudflared. Виконайте в терміналі Linux:
sudo apt update
sudo apt install -y curl gnupg ca-certificates lsb-release
curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | \
sudo gpg --dearmor -o /usr/share/keyrings/cloudflare-main.gpg
echo "deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared $(lsb_release -cs) main" | \
sudo tee /etc/apt/sources.list.d/cloudflared.list > /dev/null
sudo apt update
sudo apt install -y cloudflared
Якщо ваш випуск дистрибутива не підтримується цим репозиторієм, можна встановити .deb з GitHub Releases.
ARCH=$(dpkg --print-architecture) # amd64/arm64/armhf і т.д.
wget -q https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${ARCH}.deb
sudo apt install -y ./cloudflared-linux-${ARCH}.deb
Сервіс cloudflared у режимі proxy-dns
Створимо окремого системного сервіс-користувача та systemd-юнит, що запускає DoH-проксі на порту 5053 з двома upstream-адресами Cloudflare:
sudo useradd -r -s /usr/sbin/nologin -U -M cloudflared 2>/dev/null || true
sudo tee /etc/systemd/system/cloudflared-dns.service > /dev/null <<'EOF'
[Unit]
Description=Cloudflared DNS over HTTPS proxy
After=network-online.target
Wants=network-online.target
[Service]
User=cloudflared
Group=cloudflared
AmbientCapabilities=CAP_NET_BIND_SERVICE
ExecStart=/usr/bin/cloudflared proxy-dns \
--port 5053 \
--upstream https://1.1.1.1/dns-query \
--upstream https://1.0.0.1/dns-query \
--no-autoupdate
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now cloudflared-dns
systemctl --no-pager status cloudflared-dns
Швидкий тест локального порту:
dig @127.0.0.1 -p 5053 cloudflare.com A +short
Прив’язка systemd-resolved до cloudflared і fallback
Тепер направимо всі резольви системи на локальний DoH-проксі. Використаємо drop-in для зручності оновлень — це маленька порада Linux, щоб не редагувати головний файл конфігурації.
sudo install -d /etc/systemd/resolved.conf.d
sudo tee /etc/systemd/resolved.conf.d/10-doh-local.conf > /dev/null <<'EOF'
[Resolve]
DNS=127.0.0.1:5053
# Якщо cloudflared раптом помре, буде plaintext fallback нижче (компроміс доступності vs. приватність)
FallbackDNS=9.9.9.9 1.1.1.1
DNSStubListener=yes
# ВАЖЛИВО: не вмикаємо DoT тут, бо наш основний DNS локується на 127.0.0.1:5053
DNSOverTLS=no
EOF
sudo systemctl restart systemd-resolved
resolvectl status | sed -n '/Current DNS Server/,+5p'
Якщо ви хочете шифрований fallback без plaintext, підніміть другий DoH-проксі (наприклад, ще один cloudflared на порту 5054 із Quad9 або Google DoH) і додайте обидва локальні адреси в DNS=:
# Приклад багатосерверної схеми в drop-in
[Resolve]
DNS=127.0.0.1:5053 127.0.0.1:5054
FallbackDNS=
DNSOverTLS=no
Тестування і діагностика
Перевіряємо, що запити йдуть через cloudflared і все стабільно відповідає:
# Який DNS-сервер активний
resolvectl status | grep -A2 "Current DNS Server"
# Чи резолвиться домен через системний резолвер
resolvectl query kernel.org
# Прямий запит у локальний DoH-проксі
dig @127.0.0.1 -p 5053 example.com +short
# Чи слухає cloudflared порт 5053
ss -lntup | grep 5053
# Логи сервісу в реальному часі
journalctl -u cloudflared-dns -f
Порада: для складних кейсів підніміть рівень логів у cloudflared додатковим параметром --loglevel debug в ExecStart і перезапустіть сервіс.
Альтернативні способи
- AdGuard dnsproxy: універсальний DNS-проксі з DoH/DoT/DoQ. Заміна cloudflared, більше контролю.
- dnscrypt-proxy: шифрований DNS (DNSCrypt/DoH), великий список провайдерів.
- Unbound + DoT: якщо DoH не обов’язковий, а підходить DNS-over-TLS — потужний локальний резолвер з кешем.
- systemd-resolved + DoT: нативно підтримується; але саме DoH поки що реалізуємо зовнішнім проксі.
GUI-спосіб (Ubuntu Desktop)
Якщо ви на робочому столі Ubuntu і не хочете лізти в усі файли конфігурації, можна просто вказати локальний DNS у налаштуваннях мережі:
- Відкрийте Settings → Network → ваш інтерфейс (Wired/Wi‑Fi) → шестерня.
- У вкладці IPv4 (і IPv6 за потреби) вимкніть Automatic (DHCP) DNS та впишіть
127.0.0.1. - Перепідключіться до мережі. Переконайтеся, що systemd-resolved активний.
Цей варіант просто скеровує запити на локальний резолвер; сам DoH все одно забезпечує cloudflared.
FAQ
Чи підтримує systemd-resolved DoH нативно?
Ні, наразі systemd-resolved нативно підтримує DoT, а DoH робимо через зовнішній проксі (наприклад, cloudflared або dnsproxy).
Порт 5053 уже зайнято. Що робити?
Змініть порт у юніті cloudflared, наприклад на 5300: у ExecStart вкажіть --port 5300, перезапустіть сервіс і оновіть DNS=127.0.0.1:5300 у drop-in для systemd-resolved.
Як змусити всі програми використовувати systemd-resolved?
Переконайтеся, що /etc/resolv.conf — це симлінк на /run/systemd/resolve/stub-resolv.conf, і ваші програми не хардкодять власні DNS. Для контейнерів і VPN інтерфейсів налаштуйте передавання DNS коректно.
VPN перестав резолвити домени
Часто VPN-клієнт проштовхує власні DNS. Перевірте resolvectl domain і resolvectl status, переконайтесь, що маршрути доменів для VPN інтерфейсу задані, або вручну додайте DNS VPN інтерфейсу через NetworkManager, зберігаючи 127.0.0.1 першим у списку.
Як повернути все назад?
sudo rm -f /etc/systemd/resolved.conf.d/10-doh-local.conf
sudo systemctl restart systemd-resolved
sudo systemctl disable --now cloudflared-dns
sudo apt remove -y cloudflared
# Повернути типовий resolv.conf від resolved (за потреби):
sudo ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
Порада від Kernelka
Для надійності додайте спостереження за сервісом cloudflared: у юніті вже є Restart=on-failure, але ви можете створити простий systemd timer, який періодично виконує resolvectl query one.one.one.one і, якщо тест не проходить, перезапускає сервіс. Це маленький лайфхак із розділу "поради Linux" 😉
Підсумок
- Увімкнули systemd-resolved та перевірили /etc/resolv.conf.
- Встановили cloudflared і підняли його як DoH-проксі на 127.0.0.1:5053.
- Спрямували DNS у systemd-resolved на локальний порт, додали fallback.
- Протестували роботу через resolvectl, dig і логи systemd.
- Розглянули альтернативи (dnsproxy, dnscrypt-proxy, Unbound/DoT) і GUI-вказівки.
Готово! Тепер ваші DNS-запити шифруються DoH на рівні системи. Безпечно, стабільно і контрольовано 💪