Как работает DNS-over-HTTPS в связке с прокси: конфликты и правильная настройка
Содержание
- DNS-over-HTTPS и прокси: разбор полётов
- Как DoH вообще работает
- Где прокси вклинивается в этот процесс
- Конфликт №1: системный резолвер против DoH
- Конфликт №2: DoH-клиент и прокси-аутентификация
- Конфликт №3: кэширование и TTL
- Правильная настройка: вариант с системным DoH
- Правильная настройка: вариант с локальным резолвером
- Конфликт №4: SNI и DNS
- Конфликт №5: IPv6 и MTU
- Пример настройки для nginx
- Практический пример: Python-скрипт с DoH и прокси
- Что делать, если ничего не работает
- Итоги
DNS-over-HTTPS и прокси: разбор полётов
DNS-over-HTTPS (DoH) — штука полезная. Шифрует запросы к резолверу, прячет их от провайдера. Но когда рядом появляется прокси, начинается цирк. Запросы уходят не туда, кэш живёт своей жизнью, а приложения смотрят на тебя как на врага.
Разберём, почему это происходит и как настроить связку без боли.
Как DoH вообще работает
Обычный DNS — это UDP-пакет на порт 53. Всё видно, всё можно подменить. DoH заворачивает запрос в HTTPS-запрос на известный резолвер, например `https://cloudflare-dns.com/dns-query`. Ответ приходит тоже по HTTPS.
Порт 443, TLS-шифрование, обычный HTTP-трафик. Для провайдера это просто запрос на сайт. Никакой магии.
Где прокси вклинивается в этот процесс
Прокси работает на уровне TCP-соединений. Когда приложение хочет открыть `example.com`, оно сначала спрашивает DNS, а потом уже идёт через прокси.
Но вот незадача: если приложение настроено на DoH, оно отправляет DNS-запрос по HTTPS. А HTTPS — это TCP-соединение. И оно должно идти через прокси.
Тут и начинается веселье.
Конфликт №1: системный резолвер против DoH
У тебя в системе настроен DoH через системные настройки (Windows 11, например). Прокси тоже прописан в системе. Приложение делает DNS-запрос через DoH, но системный резолвер говорит: "Слушай, у нас тут прокси, давай-ка я сам всё решу".
В итоге DoH-запрос уходит напрямую, минуя прокси. Или наоборот — уходит через прокси, но прокси его не понимает, потому что это не обычный DNS.
Пример: Windows 11 с включённым DoH на Cloudflare. Прокси — Squid на порту 3128. Приложение пытается резолвить через DoH, но системный DNS-клиент перехватывает запрос и отправляет его в прокси как обычный DNS-over-TCP. Squid смотрит на это недоумённо и возвращает ошибку.
Конфликт №2: DoH-клиент и прокси-аутентификация
DoH-клиенты часто не умеют работать с прокси. Точнее, умеют, но через костыли. Например, `curl` с поддержкой DoH требует, чтобы ты явно указал прокси для HTTPS-соединения.
```bash
curl --doh-url https://cloudflare-dns.com/dns-query \
--proxy http://proxy.example.com:3128 \
https://example.com
```
Но большинство приложений так не умеют. Они просто используют системные настройки.
Конфликт №3: кэширование и TTL
DoH-резолверы отдают записи с нормальным TTL. Но прокси может кэшировать DNS-ответы. Если прокси кэширует старый IP, а DoH вернул новый — получишь соединение с битым адресом.
Особенно весело с IPv6. Прокси может отдавать только IPv4, а DoH возвращает AAAA-запись. Приложение пытается подключиться по IPv6 через IPv4-прокси — и всё падает.
Правильная настройка: вариант с системным DoH
Если у тебя Windows 10/11 или macOS с системным DoH, то прокси должен быть настроен как SOCKS5. Почему? Потому что SOCKS5 работает на уровне TCP, и он не лезет в DNS.
Вот пример для Windows:
```powershell
netsh winhttp set proxy proxy-server="socks=proxy.example.com:1080" bypass-list="localhost;127.0.0.1"
```
После этого DoH-запросы уходят через SOCKS5-прокси, а ответы приходят нормально. Прокси не пытается резолвить имена сам — он просто передаёт трафик.
Правильная настройка: вариант с локальным резолвером
Ставим локальный DoH-резолвер, например `dnsproxy` от AdGuard. Он слушает на 127.0.0.1:53 и пересылает запросы через DoH наверх.
```bash
dnsproxy --listen 127.0.0.1:53 \
--upstream https://cloudflare-dns.com/dns-query \
--proxy http://proxy.example.com:3128
```
Теперь все приложения, которые ходят на системный DNS, попадают в dnsproxy. А он уже разруливает через прокси и DoH.
Конфликт №4: SNI и DNS
Когда DoH-запрос идёт через прокси, прокси видит SNI (Server Name Indication) — имя хоста в TLS-рукопожатии. Если это DoH-резолвер, прокси может решить, что это обычный HTTPS-трафик, и попытаться его кэшировать или фильтровать.
Решение — использовать выделенный домен для DoH, который прокси не фильтрует. Например, `dns.google` или `mozilla.cloudflare-dns.com`. Они обычно не попадают под фильтры.
Конфликт №5: IPv6 и MTU
DoH-ответы могут содержать AAAA-записи. Если твой прокси не поддерживает IPv6, а DoH вернул IPv6-адрес, приложение попытается подключиться по IPv6 и зависнет на таймауте.
Решение — на прокси отключить IPv6 или заставить DoH-резолвер возвращать только A-записи. В dnsproxy для этого есть флаг:
```bash
dnsproxy --ipv6-disabled
```
Пример настройки для nginx
Если ты используешь nginx как прокси, то можно настроить резолвер через DoH вот так:
```nginx
resolver 127.0.0.1:53 valid=30s ipv6=off;
```
Где 127.0.0.1:53 — это твой локальный dnsproxy. nginx будет ходить к нему, а тот уже решит, как резолвить — через DoH или обычный DNS.
Практический пример: Python-скрипт с DoH и прокси
```python
import socket
import requests
def resolve_via_doh(hostname):
r = requests.get(
'https://cloudflare-dns.com/dns-query',
params={'name': hostname, 'type': 'A'},
headers={'Accept': 'application/dns-json'},
proxies={'https': 'http://proxy.example.com:3128'}
)
data = r.json()
return [ans['data'] for ans in data['Answer'] if ans['type'] == 1]
hostname = 'example.com'
ips = resolve_via_doh(hostname)
print(f'Resolved {hostname} to {ips}')
sock = socket.create_connection((ips[0], 443), timeout=10)
print(f'Connected to {ips[0]}')
```
Тут ключевой момент: `proxies={'https': ...}`. Без этого requests пойдёт напрямую, и DoH-запрос не попадёт в прокси.
Что делать, если ничего не работает
1. Проверь, что DoH-резолвер доступен без прокси: `curl https://cloudflare-dns.com/dns-query?name=example.com`
2. Проверь, что прокси пропускает HTTPS: `curl --proxy http://proxy.example.com:3128 https://example.com`
3. Смотри логи dnsproxy — там видно, откуда приходят запросы и куда уходят.
4. Если используешь системный DoH, отключи его и поставь dnsproxy. Так проще дебажить.
Итоги
DoH и прокси — не враги, но требуют аккуратной настройки. Главное правило: DoH-запросы должны идти через тот же путь, что и остальной трафик. Иначе получишь кучу таймаутов и странных ошибок.
Локальный dnsproxy решает 90% проблем. Остальные 10% — это когда прокси решает, что он умнее тебя, и начинает фильтровать DoH-трафик. Тут уже только выделенный IP для DoH-сервера или отключение фильтрации.
Настрой один раз — и забудь про DNS-проблемы. Пока не сменишь провайдера.