Рассмотренные ниже приемы будут полезны для пользователей прокси-серверов/VPN и позволяют скрывать запрашиваемые по DNS имена доменов.
Время на чтение: ~5 минут.
Сложность: Middle AnyKey Developer (нужно уметь запустить терминал).
Введение
Когда создавался интернет, то никаких доменов не существовало, были только ip-адреса отправителя и получателя.
Ясное дело, что все эти цифры, разделенные точками, сложно держать в голове, и в 1983 году была предложена система доменных имен DNS aka Domain Name System (а не магазин), которая стала стандартом в далеком 1986 году. DNS представляет собой систему доверенных корневых серверов, которые обмениваются данными между собой. В этой базе хранятся ip-адреса доменов (A и AAAA записи, последняя для ipv6), а так же дополнительная информация (TXT, CNAME, MX, NS, SOA, PTR и SRV-записи).
Когда вы переходите по ссылке или вбиваете адрес в поле для ввода, то браузер извлекает из него имя домена и делает DNS-запрос чтобы узнать ip-адрес конечного сервера. На этом этапе мы палим имя домена, к которому обращаемся, так как UDP-трафик не шифруется. В этом нет особого смысла при обычном использовании, так как СОРМ и аналогичные системы слежки и так видят ip-адрес, к которому вы в дальнейшем обращаетесь, а значит знают куда вы лазаете.
у UDP проблемы с использованием TLS, из двух существующих решений: QUIC и DTLS, только QUIC предложен в качестве стандарта DNS over QUIC (DoQ). Тут он не рассматиривается
Рассмотренные ниже приемы будут полезны для пользователей прокси-серверов/VPN. Они универсальны в отличии от настроек для отдельных приложений, например, браузера типа настройки Use proxy to perform DNS queries (SOCKS v5 only)
в Mozilla FireFox.
Общее у всех решений: мы запускаем локальный DNS-сервер (прокси), который приходящие к нему UDP-запросы перенаправляет на реальный DNS-сервер с использованием шифрования.
Подготовка
Обязательно запрещаем Network Manager перезаписывать /etc/resolv.conf
:
$ sudo -e /etc/NetworkManager/conf.d/dns.conf
[main]
dns=none
Перезапускаем для немедленного применения:
$ sudo systemctl restart NetworkManager
Если у вас нет systemd пропускаем
systemd-resolved
представляет собой локальный DNS-сервер. Его нужно запустить, если он еще не запущен:
sudo systemctl enable --now systemd-resolved.service
DNS Over TLS (DoT) / DNSSec
Этот способ хорош тем, что ничего дополнительно ставить не нужно. Systemd-resolved давно поддерживает DNSSEC
, а значит, будет работать и в умеренно старых дистрибутивах на базе systemd. Как выше уже писалось в UDP с поддержкой TLS существует неопределенность, а поэтому для обращения к конечным DNS серверам вместо UDP используется TCP. Схема: клиент обращается по UDP к локальному DNS, а тот делает DNS-запросы с использованием TLS поверх TCP.
# Ищем секцию [Resolve] и прописываем настройки
$ sudo -e /etc/systemd/resolved.conf
...
[Resolve]
...
DNS=1.1.1.1
FallbackDNS=1.0.0.1
DNSSEC=yes
DNSOverTLS=yes
# Содержимое всего файла должно быть таким
$ sudo -e /etc/resolv.conf
nameserver 127.0.0.53
# Перезапускаем сервис для применения настроек
$ systemctl restart systemd-resolved.service
# Проверяем
$ resolvectl
Global
Protocols: +LLMNR +mDNS +DNSOverTLS DNSSEC=yes/supported
resolv.conf mode: foreign
Current DNS Server: 1.1.1.1
DNS Servers: 1.1.1.1
Fallback DNS Servers: 1.0.0.1
# Делаем тестовый запрос
$ dig example.com
; <<>> DiG 9.18.24 <<>> example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 58280
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;example.com. IN A
;; ANSWER SECTION:
example.com. 6439 IN A 93.184.216.34
;; Query time: 0 msec
;; SERVER: 127.0.0.53#53(127.0.0.53) (UDP)
;; WHEN: Sun Mar 03 13:17:55 MSK 2024
;; MSG SIZE rcvd: 56
SERVER: 127.0.0.53#53(127.0.0.53) (UDP)
Означает что запросы к DNS осуществляются через защищенное соединение.
Вместо DNS=1.1.1.1 (Cloudflare) можно указать гугловый DNS 8.8.8.8 и фолбечный 8.8.4.4 к нему
А как быть тем, кому религиозные убеждения не позволяют использовать systemd? - Для таких есть подгончик от меня.
ОБЯЗАТЕЛЬНО! Для начала заходим на гитхаб моего репозитория и ставим звезду.
Качаем репозиторий и переходим в каталог:
$ git clone https://github.com/s3rgeym/dot-proxy
$ cd dot-proxy
Редактируем .env
чтобы сменить DNS.
Запускаем DoT-прокси:
docker-compose up -d
Меняем /etc/resolv.conf
:
nameserver 127.0.0.52
Проверяем:
$ dig www.linux.org.ru | grep -i server
;; SERVER: 127.0.0.52#53(127.0.0.52) (UDP)
Если не устраивает мое поделие, то можно обратиться к классике типа Unbound.
DNS Over HTTPS (DoH)
Этот способ использовался ранее, но все еще актуален. Локальный сервер принимает UDP-запросы и пересылает их на серваки Гугла, Клауда, которые поддерживают DNS Over HTTPS: GET и POST запросы с параметром name
и JSON-лапшой в виде ответа. См. RFC 8484.
# Ставим пакет
$ yay -S dns-over-https
# В качестве nameserver указываем 127.0.0.1
$ sudo -e /etc/resolv.conf
nameserver 127.0.0.1
# Тут можно dns-сервер выбрать
$ sudo -e /etc/dns-over-https/doh-client.conf
$ sudo systemctl enable --now doh-client.service
# Проверяем
$ dig www.google.com | grep -i server
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
Инструкция с Arch Wiki:
Сама утилита:
Прочее:
Более старое решение:
Пример DNS-запроса через HTTPs чисто в академических целях:
$ curl -s 'https://dns.google/resolve?name=example.com&type=A' | jq
{
"Status": 0,
"TC": false,
"RD": true,
"RA": true,
"AD": true,
"CD": false,
"Question": [
{
"name": "example.com.",
"type": 1
}
],
"Answer": [
{
"name": "example.com.",
"type": 1,
"TTL": 371,
"data": "93.184.215.14"
}
]
}