DNS конвертер

Участились случаи подмены нешифрованных udp:53 запросов. При этом tcp:53 обычно не трогается. Claude написал udp:53>tcp:53 локальный конвертер на Go для линукса. Предлагаю потестить.

dnsproxy.go (5,9 КБ)

dns-tcp-proxy: слушает DNS-запросы по UDP на локальном порту и
пересылает их upstream-серверу по TCP (DNS-over-TCP, RFC 7766).

Зачем: некоторые провайдеры подменяют/блокируют обычный
нешифрованный UDP:53, но не трогают TCP:53. glibc-резолвер сам
никогда не переключится на TCP, кроме случая truncated-ответа,
поэтому нужен локальный “переводчик” протокола.

Использование:
go build -o dns-tcp-proxy dnsproxy.go
sudo setcap 'cap_net_bind_service=+ep' ./dns-tcp-proxy
./dns-tcp-proxy -listen 127.0.0.1:53 -upstream 1.1.1.1:53

Затем указать 127.0.0.1 как DNS-сервер системы, например в /etc/resolv.conf.

Ещё пояснение от Claude:

Написал такой прокси на Go — с пулингом TCP-соединения и pipelining (не по одному хендшейку на запрос, а один живой TCP-коннекшен с ремаппингом ID для параллельных запросов):

Что внутри и почему так:

Как работает — прямое проксирование, без флага TC. Один живой TCP-коннекшен к upstream переиспользуется для всех запросов (pipelining, RFC 7766), с ремаппингом DNS ID, чтобы правильно раздать ответы обратно нужным UDP-клиентам. При обрыве TCP-соединения — автопереподключение. Всё это протестировал прямо здесь: 5 параллельных запросов с разными ID корректно размэтчились, а реконнект после убитого upstream-сервера тоже отработал сам.

Почему это лучше идеи с TC-флагом: не нужен лишний UDP-раунд-трип перед TCP, не зависит от того, правильно ли конкретное приложение обрабатывает truncation, и ответ может быть любого размера (loopback UDP не фрагментируется, в отличие от реального сетевого пути).

Из подводных камней — на большинстве дистрибутивов порт 127.0.0.53:53 уже занят systemd-resolved, так что в README расписал оба варианта: полностью его отключить, либо оставить и перенаправить его же upstream на прокси через resolved.conf.

И да, честно предупреждал в начале: если DPI провайдера начнёт мешать и голому TCP:53 (это сложнее, чем блайндовый UDP-спуфинг, но не невозможно) — этот инструмент не спасёт, там уже нужен DoT с TLS.

И если кто хочет systemd службу:

dns-tcp-proxy.service (474 байта)

Вроде, должно работать на винде. Там ничего unix специфичного. Могу собрать для win7.

Зачем это если есть dnscrypt proxy и ему подобные?

у меня smartdns на роутере и на винде если нужно smartdns-rs. перенаправляет на doh doq dot куда угодно. проверяет на пинг или тсп, выбирает из нескольких резолверов самый “быстрый” ip и тд

doh, dnscrypt тоже вариант, но их нужно настраивать. dnscrypt регион не передаёт, может выдавать заблокированные ip.
Бывает у человека винда седьмая без поддержки doh, с помощью zapret+yt-dlp качает с ютуба. И вот ему, в теории, утилита пригодится восстановить резолв ютуба.
У меня брат на запрете сидел, покая я на впн не подсадил.
Но вообще да, в таких случаях проще подыскать udp:53, которые не перехватываются, если такие есть. Или в hosts вписать.
Ну, а я просто люблю тестировать новые нетипичные утилиты.

Тестирование показало хорошую производительность.

На win7 не запускается с ошибкой

listen udp 127.0.0.1:53: bind: An attempt was made to access a socket in a way forbidden by its access permissions.

Может, надо запустить от админа. И в файерволе разрешить. Claude предупреждал о проблемах с правами. Я проверю.

Запускаю от админа, файрволл у меня сторонний, попробую поковырять

если это вопрос про smartdns-rs, то лучше у них гитхабе спросить. Там кто-то ставил на 32 битную 7 винду. только версию нужно правильную скачать.

Нет, про утилиту из шапки)

В DNS серверах (по крайней мере в Technitium DNS Server, BIND9) принудительный DNS-over-TCP настраивается из коробки. Уже давно пора себе настроить локальный кэширующий stub резольвер (с redundancy и concurrency).

На win11 по крайней мере запускается без этой ошибки. Правда, проверить коннекты не смог. Меня выкинуло из триальной виртуалки с виндой (есть такие сервисы в интернете), когда в сетевом адаптере пытался указать dns 127.0.0.1.
Чтобы проверить на win7 придётся терзать брата.

А собственно зачем, когда есть уже стабильные и проверенные решения?

Там и инструкции есть как настроить и службу запустить, чтобы автозапуск был

Это называется “спортивный интерес”) Ну и плюс простота настройки для “чайников” (“однокнопочное” решение)

Код посмотри, он не надежный, нет возможности указать сразу несколько разных днс.

Крч советую лучше dnscrypt поставить и один раз настроить его.

Спасибо, хотя нет необходимости меня в этом убеждать). И кстати помимо dnscrypt есть много др. решений

В интернете много упоминаний этой ошибки, например https://stackoverflow.com/questions/10461257/an-attempt-was-made-to-access-a-socket-in-a-way-forbidden-by-its-access-permissi
В основном, советуют проверить файервол. Встречается также такое:

Вероятнее всего, причина кроется в обновлении Windows, которое ограничило доступ к определенным портам на компьютерах под управлением Windows. Список портов, исключенных из доступа вашей учетной записи, можно просмотреть, выполнив следующую команду: netsh interface ipv4 show excludedportrange protocol=tcp

или protocol=udp.
Дело в том, что я тестил на win11 серверной, т.е. windows server. Возможно, там таких ограничений нет.

Порт 53 сменить врядли возможно, но можно успользовать другой IP, вроде 127.0.0.2.

dnscrypt не передаёт регион. Если его использовать, нужно выбирать московские резолверы.
Иначе, если у вас резолвер допустим во Франции (scaleway-fr), он вам выдаст французские сдны, которые могут быть в блоке на тспу. Я уже с таким сталкивался.
Можно, правда, использовать doh в dnscrypt, не знаю как там. Но вообще в doh задержка повыше, т.к. там tls. Но у dnscrypt есть кэширование.
Лично я такого монстра стараюсь не запускать без особой нужды. В основном, dnscrypt мне нужен для блокировок доменов и логов. Но у меня всегда включен впн, это другой случай.

ECS поддерживается:

Такие редкие исключения можно описать FWD записями для необходимых зон (как, например, для .onion).

Для достижения resiliency лучше систему разрешения имён отделить от туннелирования (настроив outbound interface), пока есть такая возможность.

На данный момент склоняюсь в сторону чего-то вроде https://github.com/TechnitiumSoftware/DnsServer

**Критерий		Unbound				Technitium DNS		AdGuard Home	dnscrypt-proxy**
Интерфейс		Текстовый конфиг	Отличный Web-UI		Отличный Web-UI	Текстовый конфиг
Режим рекурсии	Да (основной)		Да					Ограниченно		Нет (только прокси)
Входящий DoH	Да (HTTP/2)			Да					Да				Да
Исходящий DoH	Нет (только DoT)	Да (включая HTTP/3)	Да				Да
Сложность		Средняя/Высокая		Легкая				Очень легкая	Средняя