DNS
Сет определяет, какой резолвер отвечает на домены, которые он нацеливает. Всё остальное продолжает уходить на тот резолвер, который выбрал клиент. На этой странице описано, что именно перехватывает b4, что сет делает с совпавшим запросом и какие общие настройки DNS действуют на все сеты.
Что перехватывает b4
| Транспорт | Как попадает в b4 | Когда |
|---|---|---|
| UDP порт 53 | Правила очереди в PREROUTING и OUTPUT, для запросов (dport 53) и для ответов (sport 53) | Всегда, пока b4 запущен |
| TCP порт 53 | REDIRECT в таблице nat на локальный слушатель, по умолчанию порт 5453 | Только пока хотя бы у одного включённого сета задан DNS-сервер или DoH-адрес и включён параметр Перехватывать DNS поверх TCP |
В обоих случаях это касается и трафика, идущего с устройств сети, и запросов, которые роутер делает для себя. Запросы, которые b4 отправляет за клиента, и его запросы через резолвер сета несут метку очереди, а эти правила пропускают пакеты с ней, поэтому через них такой запрос обратно в очередь не попадает. Запросы, которые b4 делает через резолвер самого роутера, метки не несут.
Всё, что описано на этой странице, работает с DNS на порту 53. Если устройство само резолвит через DoH, DoT или DoQ, запрос уходит как TLS или QUIC на порт 443 или 853, и b4 его не прочитает: резолвер сета, его закрепления и его блокировки к этому имени не применяются, а маршрутизирующий сет не узнаёт из таких ответов ни одного адреса.
Обычные источники этого - браузер с включённым собственным защищённым DNS (Firefox, Chrome), Android Private DNS и резолвер, прописанный как DoH на самом устройстве. Чтобы работать с DNS через b4, выключите зашифрованный DNS на таких устройствах и оставьте им роутер.
Зашифрованный форвардер на самом роутере - это другое дело, и он не мешает. Устройства по-прежнему обращаются к роутеру на обычный порт 53, b4 перехватывает там, и до форвардера доходит только то, что b4 пропустил.
Как сет обрабатывает запрос
Имя из запроса сверяется с целями сета так же, как SNI: запись домена покрывает его поддомены, поддерживаются записи regexp:. Обычные записи проверяются раньше регулярных выражений, поэтому домен, указанный в одном сете, не перехватывается заглушкой regexp:.* из другого.
Совпавший запрос b4 проводит по шагам в таком порядке:
- Блокировка. Если режим маршрутизации сета -
block, запрос получает NXDOMAIN или отбрасывается, в зависимости от действия блокировки. См. Блокировка. - Закреплённые адреса. Если для имени есть закрепление, b4 отвечает из него и на этом останавливается. Это работает независимо от того, включено ли перенаправление ниже.
- Резолвер. Если перенаправление включено и резолвер задан, b4 разрешает имя сам и отвечает клиенту напрямую. Иначе запрос уходит без изменений.
- Ответ. Адреса из ответа запоминаются для клиента и записываются в IP-сет сета, если включена маршрутизация. Ответ, пересланный или закреплённый, который приносит адреса, не записанные b4 в сет в последнее время, задерживается, пока b4 не закончит обновление сета для этих адресов, но не дольше 250 мс каждый раз, когда b4 его видит, поэтому следующее за ним соединение обычно идёт маршрутом сета. При движке TUN ответ не задерживается; см. Маршрутизация.
Типы резолверов
Резолвер задаётся в Сеты → сет → DNS & Маршрутизация → Перенаправление DNS.
| Режим | Поле в конфигурации | Что делает b4 |
|---|---|---|
| Обычный DNS (UDP) | dns.target_dns | Сам отправляет запрос на этот IP, при необходимости фрагментируя его (Фрагментировать DNS-запросы), чтобы пройти DPI, который вычитывает доменные имена из запросов |
| DNS-over-HTTPS | dns.doh_url | Отправляет запрос зашифрованным HTTPS-запросом: сначала POST, а если сервер его не принимает - GET |
DoH-адрес имеет приоритет: если заполнены оба поля, используется DoH-адрес, а IP игнорируется. Адрес должен начинаться с https://, это проверяется при сохранении конфигурации.
Запрос с адреса собственного резолвера сета уходит без изменений, а не возвращается ему же, если b4 не блокирует этот запрос и не отвечает на него из закрепления. Резолвер в другом месте сети, который обращается к вышестоящему резолверу по обычному DNS, передаёт запрос клиента дальше через роутер, и если вернуть этот запрос ему же, он ждал бы весь таймаут запроса; любой другой запрос с этого адреса тоже уходит без изменений, в том числе запросы контейнеров и VPN-клиентов, которые выходят в сеть через NAT на хосте резолвера. DoH-адрес сравнивается так же, если сервер в нём указан IP-адресом. Сравнивается только адрес, указанный в сете: запрос, который резолвер отправляет с другого своего адреса, например запрос по IPv4 от резолвера, указанного в сете IPv6-адресом, всё равно возвращается к нему. Для резолвера на самом роутере сравнение не выполняется, чтобы собственные запросы роутера уходили к нему. Такой резолвер, а также резолвер роутера, когда резолвер в сети использует его как вышестоящий, должен обращаться к своему вышестоящему резолверу по протоколу, который b4 не перехватывает, например по DNS поверх HTTPS или TLS.

Отправить один сервис на отдельный резолвер
Частая причина перенаправить один сет - сервис, который отказывается работать из вашего региона. За этим стоят две разные вещи, и только одна из них про DNS.
Имя разрешается не туда. Какой адрес вы получите для имени, зависит от того, кто спросил: geo-DNS отдаёт ближайший к резолверу фронтенд, и резолвер из другого места получает другой ответ. Некоторые публичные резолверы идут дальше и держат собственные фронтенды для фиксированного списка сервисов: они отвечают адресом своего релея, который читает SNI и передаёт соединение дальше. И в том, и в другом случае соединение оказывается на пути, который сервис принимает, а остальной ваш DNS от такого сета не меняется.
Сервис смотрит на адрес, с которого вы подключаетесь. Ответ резолвера ваш собственный адрес не меняет, поэтому проверка, которая происходит уже после установки соединения (аккаунт, оплата, ключ API, привязанный к региону), от смены резолвера не зависит. Здесь нужен другой выход наружу: см. маршрутизацию трафика.
Для первого случая заведите сет, нацеленный только на домены этого сервиса, включите перенаправление и укажите DoH-адрес резолвера. Не добавляйте эти домены в сет-заглушку на всю сеть: смысл как раз в том, чтобы по-другому обрабатывался только этот сервис.
Резолвер, который отвечает адресами собственных релеев, видит, какие из этих имён вы запрашиваете, и дальше несёт этот трафик через себя. Это осознанное решение о доверии. Направляйте на такой резолвер только те домены, которым это нужно, а обычный просмотр оставьте резолверу, который выбрали бы сами по себе.
Закреплённые адреса
Закрепление подменяет то, что DNS выдаёт для имени, без правки hosts на каждом устройстве. Поле заполняется в порядке hosts-файла, по строке на адрес:
157.240.0.174 www.instagram.com
157.240.205.63 scontent.cdninstagram.com scontent-a.cdninstagram.com
- Сначала адрес, затем имена, для которых им нужно отвечать.
- Закрепление действует на каждое имя и его поддомены, побеждает самая длинная подходящая запись.
- Закрепление работает только для имени, которое сет уже нацеливает. Закрепление имени, не покрытого целями сета, не даёт ничего: интерфейс предупреждает об этом и предлагает добавить имя в домены сета.
- Список закреплений - это весь адресный ответ для имени. Запросы A и AAAA получают закреплённые адреса соответствующего семейства; запрос AAAA к имени, закреплённому только за IPv4, а также запросы CNAME, SVCB, HTTPS и ANY получают пустой ответ, а не ответ резолвера, потому что такие ответы несли бы CNAME сайта, и системный кэш уходил бы по нему мимо закреплений, как только истекал ответ с закреплёнными адресами. Запрос A к имени, закреплённому только за IPv6, по-прежнему уходит на резолвер, потому что клиенту только с IPv4 больше взять адрес неоткуда; туда же уходят остальные типы записей, среди них MX, TXT и SRV.
- В сете без маршрутизации закреплённый адрес, до которого роутер не достучался по TCP на порт 443, в ответ не попадает. b4 подключается к каждому такому адресу при старте, при сохранении сета и каждые
system.ip_health.retest_interval_secсекунд (по умолчанию 300), а переставший отвечать адрес перепроверяется с тем же интервалом. Закрепления сета с маршрутизацией не проверяются: проверка подключается напрямую с роутера, а соединения сета уходят через его маршрут, поэтому адрес, недоступный напрямую, может оказаться правильным. Раунд, в котором не ответил ни один адрес, как при обрыве аплинка, ничего не доказывает и вердиктов не меняет. Когда недоступны все адреса семейства, закрепления всё равно отдаются в ответ, так что закреплённый хост, который просто не слушает порт 443, своё закрепление сохраняет; только при включённом обнаружении блокировки по IP такой запрос уходит на резолвер. - Закреплённые ответы отдаются с TTL 60 секунд.
- Закрепления читаются, даже когда Включить перенаправление DNS выключено, так что сет может закрепить несколько имён и оставить всё остальное резолверу клиента.
В файле конфигурации те же данные хранятся наоборот - как dns.pins, где имени сопоставлены его адреса.
Когда резолвер не отвечает
Резолвер, который не ответил вовремя или вернул ошибку, не обрывает разрешение имени. b4 отвечает последним удачным ответом, который хранит для этого имени, а если такого нет - отправляет запрос тому резолверу, к которому обращался сам клиент, и отдаёт полученный ответ. Три неудачи подряд выводят заданный резолвер из цепочки на 30 секунд, поэтому пропавший резолвер стоит одного таймаута, а не одного на каждый запрос.
Сет может потребовать обратного переключателем Отдавать SERVFAIL, если резолвер недоступен (dns.strict). С ним резолвер, который не ответил, даёт SERVFAIL, b4 не откатывается на обычный DNS, и имя, которое b4 взял на себя, либо разрешается через заданный резолвер, либо не разрешается вовсе.
Fail-closed вместе с недоступным резолвером означает, что в сете не резолвится ничего. На цензурируемом подключении сам DoH-сервер является мишенью, поэтому резолвер, отвечавший на момент сборки сета, может перестать отвечать позже, и вместе с ним ляжет каждый домен сета, хотя стратегия обхода под ним продолжает работать.
Запросы, которые b4 делает сам
Некоторые имена сета b4 разрешает и для себя. Он заранее разрешает домены сета с включённой маршрутизацией, а для сета в режиме прокси ищет адрес имени, когда клиент его SOCKS5-прокси запрашивает это имя при выключенной опции Передавать имя домена в upstream, когда upstream отклоняет имя и когда соединение уходит в прямое. Если перенаправление включено и резолвер задан, эти запросы тоже идут к нему, а не к собственному резолверу роутера, а после изменения настроек резолвера домены сета разрешаются заново.
Ответ резолвера сета окончательный, что бы в нём ни было, так же как при передаче клиенту через перенаправление: имени нет, адреса нет, SERVFAIL или REFUSED. Если резолвер не ответил вовремя или недоступен, запрос уходит к резолверу роутера, а при включённом Отдавать SERVFAIL, если резолвер недоступен завершается ошибкой. Собственные запросы роутера к доменам сета тоже проходят через перенаправление, поэтому, пока не началась пауза, описанная ниже, такой откат может занять два таймаута запроса. Эти запросы учитываются в общем с перенаправлением счёте неудач: после трёх подряд резолвер пропускается на 30 секунд, запросы сразу идут к резолверу роутера, а сет с включённым fail-closed в это время не разрешает свои домены заранее. Последний удачный ответ для них не используется, а обычный DNS отправляется без фрагментации.
Откат на IPv4
Пока в разделе Настройки, Основные, Движок пакетов не включена Поддержка IPv6, b4 обрабатывает только IPv4. Сайт с двойным стеком, на который нацелен сет, иначе открывался бы по IPv6, где у b4 нет никаких правил, и сет обходился бы стороной, при этом внешне ничего бы не сломалось.
Чтобы закрыть самый частый путь туда, b4 убирает IPv6-адреса из DNS-ответов для доменов, совпавших с сетом, оставляя клиенту IPv4-адреса, которые b4 действительно защищает. Ответ переписывается, а не отклоняется: записи A остаются, записи AAAA убираются, и клиент сам откатывается на IPv4.
- Это касается только имён, совпавших с сетом. Все остальные имена получают полный ответ, а IPv6 в сети никак не затрагивается.
- Как только поддержка IPv6 включена, переписывание прекращается само: обходить становится нечего.
- Сет, чьи цели закреплены за IPv6 через
targets.ip_versionсо значением6, сохраняет свои IPv6-ответы: ради IPv6 такой сет и существует. - Переписанные ответы видны как
dns-ipv6-strippedв результате.
Переключатель называется Форсировать IPv4 для совпавших доменов и находится в карточке IPv4 / IPv6 раздела Настройки, Основные, Движок пакетов, по умолчанию он включён. Выключить его - то же самое, что поставить system.dns.keep_ipv6_answers в true: записи AAAA будут проходить как есть. Пока включена Поддержка IPv6, переключатель неактивен.
Здесь то же ограничение, что и во всём остальном на этой странице. Клиент, который резолвит через собственный DoH, DoT или DoQ, ответа b4 не показывает, поэтому сохраняет IPv6-адреса и всё равно доходит до сайта по IPv6. То же касается адреса, который уже лежит в кеше клиента или прописан в hosts. Откат сужает щель, но не закрывает её: полное решение - включить поддержку IPv6, чтобы у b4 были правила в обоих семействах.
Общие настройки DNS
Карточка DNS в разделе Настройки, Основные, DNS содержит перехват DNS поверх TCP и таймауты, которые действуют на все сеты.

Зачем здесь DNS поверх TCP
Обычно DNS ходит по UDP. Резолвер, у которого ответ не влезает в UDP-пакет, помечает его усечённым, и клиент повторяет запрос по TCP - так бывает с длинными списками адресов, записями DNSSEC и передачей зон. Некоторые stub-резолверы предпочитают TCP сразу, а клиент, который хочет обойти то, что следит за UDP, может уйти в TCP намеренно.
Это обычные DNS-запросы, и без перехвата они доходят до резолвера, выбранного клиентом, то есть резолвер сета, его закрепления и его блокировки для них не работают. Параметр Перехватывать DNS поверх TCP закрывает этот путь: TCP-порт 53 заворачивается в b4, и дальше применяется та же обработка сетом, что и для UDP.
| Параметр | Поле в конфигурации | По умолчанию | Значение |
|---|---|---|---|
| Перехватывать DNS поверх TCP | system.dns.tcp_disabled | включено (false) | Если выключить, клиент, откатившийся на TCP, доходит до апстрим-резолвера, а DNS-сервер сета не используется |
| Порт слушателя | system.dns.tcp_port | 5453 | На этом локальном порту b4 слушает DNS поверх TCP, а правило файрвола отправляет туда соединения, идущие на порт 53. Снаружи роутера этот порт не используется, клиенты как обращались к порту 53, так и обращаются. Меняйте, только если 5453 уже занят другой программой |
| Таймаут запроса | system.dns.query_timeout_sec | 5 | Сколько ждать резолвер сета, прежде чем уйти на запасной путь, или прежде чем ответить SERVFAIL, если сет настроен на fail-closed. Одинаково для UDP и TCP |
| Таймаут простоя | system.dns.tcp_idle_sec | 30 | Сколько держать открытым простаивающее TCP-соединение в ожидании следующих запросов |
| Таймаут чтения/записи | system.dns.tcp_io_sec | 10 | Предельное время на один запрос или ответ в установленном соединении |
| Таймаут пересылки | system.dns.tcp_dial_sec | 5 | Сколько ждать при пересылке несовпавшего TCP-запроса на резолвер, выбранный клиентом |
| Форсировать IPv4 для совпавших доменов | system.dns.keep_ipv6_answers | включено (false) | Находится в карточке IPv4 / IPv6 раздела Настройки, Основные, Движок пакетов. Переключатель и поле инвертированы: включённый переключатель означает, что keep_ipv6_answers равно false и IPv6-адреса вырезаются из ответов для совпавших доменов. Выключенный оставляет записи AAAA на месте. См. Откат на IPv4 |
В файле конфигурации хранятся только значения, отличающиеся от умолчаний, поэтому блок system.dns обычно отсутствует, пока ничего из этого не менялось.
Перехват TCP требует REDIRECT в таблице nat. Там, где ядро его не предоставляет, b4 пишет предупреждение, и DNS поверх TCP для этого семейства адресов остаётся на резолвере клиента. На перехват UDP это не влияет.
Отправить весь DNS в DoH
Сет, который нацелен на все домены, превращает перенаправление внутри сета в перенаправление для всей сети. Импортируйте его через Сеты → Импорт/Экспорт:
{
"b4_version": "dev",
"name": "all DOH",
"tcp": { "dport_filter": "53" },
"udp": { "dport_filter": "53" },
"fragmentation": { "strategy": "none" },
"faking": { "sni": false },
"targets": { "sni_domains": ["regexp:.*"] },
"enabled": true,
"dns": {
"enabled": true,
"doh_url": "https://wikimedia-dns.org/dns-query"
}
}
regexp:.* совпадает с любым именем, поэтому каждый запрос, который не забрал другой сет, разрешается через DoH - для всех устройств сети и для самого роутера. Стратегии обхода здесь выключены: этот сет существует, чтобы отвечать на DNS, а не чтобы менять трафик.
Домены, перечисленные в другом сете явно, продолжают уходить на резолвер того сета, потому что обычные записи проверяются раньше регулярных выражений. Ставьте сет-заглушку последним, чтобы было видно, какие сеты имеют перед ним приоритет.
dport_filterОни действительно ограничивают сет: с udp.dport_filter в значении 53 сет не применяется к QUIC на порту 443, а все порты, перечисленные в любом сете, дополнительно попадают в то, что b4 забирает в очередь.
Чего они не делают - так это не включают обработку DNS. Порт 53 разбирается раньше, чем читается любой фильтр портов, поэтому перенаправление работает и с двумя пустыми полями. Оставить их здесь всё же разумно: так сет с regexp:.* не забирает себе заодно все TLS-соединения. Единственная плата - tcp.dport_filter со значением 53 заводит TCP-порт 53 в очередь ради стратегий обхода, которыми этот сет не пользуется.
Что при этом меняется
- Локальные имена перестают разрешаться. Имена роутера, имена в
.lanи всё прочее, что отдаёт собственный резолвер роутера, попадает на публичный резолвер, который про них не знает. Закрепите нужные имена или нацельте заглушку на более узкое выражение. - Один резолвер тянет на себе весь catch-all. Пока DoH-сервер недоступен, каждое имя сета отвечается из кеша или собственным резолвером клиента, а не тем, ради которого сет создавался. В режиме fail-closed тот же отказ означает, что эти имена не разрешаются вовсе. Доступность резолвера с вашего подключения здесь важнее списка его возможностей.
- DNS поверх TCP подтягивается следом. Как только такой сет появляется, TCP-порт 53 тоже заворачивается в b4, и клиент, повторяющий запрос по TCP, получает тот же ответ, а не проскакивает мимо.
Как посмотреть результат
Каждое решение b4 по запросу видно на странице Трафик и в логах - вместе с протоколом, сетом, доменом и клиентом.
| Результат | Значение |
|---|---|
dns-doh-><хост> | Разрешено через DoH на этом сервере |
dns-forward-><ip> | Разрешено самим b4 на этом обычном DNS-сервере |
dns-passthrough | Совпало с сетом, но резолвер в сете не задан, поэтому запрос ушёл без изменений |
dns-pin | Отвечено закреплённым адресом |
dns-pin-empty | У закреплённого имени спросили тип записи, которого в списке закреплений нет, поэтому ответ пустой |
dns-heal | В ответе заменены недоступные адреса, работой детектора блокировки IP в сете |
dns-sinkhole | Отвечено NXDOMAIN блокирующим сетом |
dns-block | Отброшено блокирующим сетом |
dns-servfail | Резолвер сета не ответил, и запасного ответа тоже не нашлось, либо сет настроен на fail-closed |
dns-fallback-cache | Резолвер сета не ответил, поэтому повторно отданы последние удачные адреса для этого имени |
dns-fallback-upstream | Резолвер сета не ответил и в кеше ничего не было, поэтому запрос ушёл тому резолверу, к которому обращался клиент |
dns-bad-target | В поле DNS-сервера сета не корректный IP-адрес, поэтому запрос ушёл без изменений |
dns-from-target | Запрос пришёл с адреса собственного резолвера сета, поэтому ушёл без изменений, а не вернулся к нему. См. Типы резолверов |
dns-ipv6-disabled | Запрос, пришедший по IPv6, совпал с сетом при выключенной поддержке IPv6, поэтому ушёл без изменений, а не был обработан сетом |
dns-ipv6-stripped | Из ответа убраны IPv6-адреса, клиенту оставлен IPv4-путь, который защищает b4. См. Откат на IPv4 |
dns-heal+ipv6-stripped | С одним ответом произошло и то, и другое: недоступные адреса заменены, а IPv6-адреса убраны |
В режиме TUN запросы на порт 53 перехватываются, а ответы видны только тогда, когда b4 держит весь маршрут по умолчанию. Перенаправления и закрепления работают в любом случае, потому что эти ответы b4 формирует сам. Если b4 не может поставить правило NOTRACK, TUN захватывает только трафик самого устройства, поэтому DNS других хостов доходит до b4, только когда его обрабатывает резолвер на этом устройстве, см. Движок пакетов.