Openwrt dns over https настройка

Обновлено: 03.07.2024

Начиная с Chaos Calmer 15.05, dnscrypt-proxy и libsodium присутствуют в официальном репозитории:

Кроме того, существует пакет luci-app-dnscrypt-proxy, позволяющий настраивать dnscrypt-proxy через веб-интерфейс LuCi.

Специальная сборка для архитектуры ar71xx от black-roland

Сборка от black-roland имеет ряд преимуществ перед официальным репозиторием Chaos Calmer: пакеты dnscrypt-proxy и libsodium более свежие (и поддерживают Barrier Breaker), dnscrypt-proxy поддерживает использование эфемерных ключей, procd и позволяет одновременно запускать несколько копий себя (если первый DNS -сервер по каким-либо причинам будет недоступен, система использует второй).

Добавляем в файл /etc/opkg.conf источник в зависимости от используемой версии OpenWrt. Для этого выполняем в консоли следующие команды:

Trunk:

Уже содержит актуальную версию dnscrypt-proxy с поддержкой запуска нескольких копий. Ничего добавлять не требуется.

Chaos Calmer:

Barrier Breaker:

Обновляем список пакетов и устанавливаем dnscrypt-proxy и libsodium . Примечание: без обновленной библиотеки служба не запустится (по крайней мере в мультисерверном варианте), при недостатке места библиотеку следует удалить принудительно.

Настройка

По умолчанию dnscrypt-proxy использует адрес и порт 127.0.0.1:5353 . Нужно настроить OpenWrt для отправки DNS -запросов на этот адрес.

dnscrypt-proxy

Настраиваем, редактируя файл /etc/config/dnscrypt-proxy :

Следующие параметры поддерживаются только в Trunk:

Название Тип Обязательность Значение по умолчанию Описание
client_key string нет отсутствует Идентификация клиента публичным ключом. По умолчанию (для затруднения отслеживания) клиент использует случайно сгенерированную ключевую пару. Эта настройка заставляет использовать статическую пару, что, например, позволяет DNS -провайдеру предлагать премиум-сервис клиентам, чьи запросы подписаны определёнными публичными ключами. Клиент не может расшифровать поступающие ответы без знания приватного ключа. Значение этой настройки представляет собой путь к файлу, содержащему приватный ключ. Соответствующий ему публичный ключ вычисляется автоматически.
syslog boolean нет 1 Отправка событий демону syslog.
syslog_prefix string нет dnscrypt-proxy Строка, предваряющая записи в журнале.

Следующие параметры присутствуют в файле /etc/config/dnscrypt-proxy , но не поддерживаются, поскольку (на данный момент) DNSCrypt в OpenWrt собирается без поддержки плагинов:

Дополнительные параметры, при необходимости, указываются в скрипте инициализации (файл /etc/init.d/dnscrypt-proxy ).

Добавляем dnscrypt-proxy в автозагрузку и запускаем:

Обратите внимание: если dnscrypt-proxy не запускается автоматически после перезагрузки системы, возможно, он пытается запуститься ещё до того, как полностью поднят сетевой интерфейс. Добавьте в файл /etc/rc.local перед строчкой “exit 0”:

Кроме того, на маршрутизаторе должно быть установлено точное время.

dnsmasq

Настраиваем dnsmasq для использования dnscrypt-proxy на 127.0.0.1:5353. Полужирным выделены строки, которые нужно изменить в файле /etc/config/dhcp :

отключили обработку файла /tmp/resolv.conf.auto , поскольку он указывает dnsmasq использовать DNS -серверы провайдера. добавили настройку noresolv , которая (по тем же причинам) отключает обработку файла /etc/resolv.conf .

Перезапускаем dnsmasq (или перезагружаем маршрутизатор):

Использование нескольких серверов

Работает с dnscrypt-proxy из стандартного репозитория Chaos Calmer 15.05.1, но для предыдущих выпусков, скорее всего, недоступно

Добавляем дополнительный сервер в файл /etc/config/dnscrypt-proxy (обратите внимание, что они должны размещаться на разных портах):

Создаём файл /etc/resolv-crypt.conf , содержащий единственную строку: options timeout:1. Эта настройка заставляет dnsmasq после секундного ожидания ответа от первого DNS -сервера переключиться на следующий.

Перезагружаем маршрутизатор, либо перезапускаем dnscrypt-proxy и dnsmasq :

Очищаем кэш DNS на клиентских устройствах

Обратите внимание: команды должны быть выполнены в командной строке с правами администратора.

image

После сравнительно недавнего анонса компанией Mozilla запуска поддержки DNS-over-HTTPS (DoH) в продакшн в сети не утихают споры, зло это или благо. По моим ощущениям, позиция "зло" базируется в основном на том, что при этом манипуляция вашими DNS-запросами даже в полезных для вас целях будет затруднена, поэтому я пока что остаюсь на позиции "благо".

В Российской Федерации операторы связи, поставленные в очень жесткие условия нашим законодательством, вынуждены строить изощренные многоуровневые системы блокировок доступа к запрещенному Роскомнадзором на территории РФ контенту, на одном из уровней которых более-менее успешно работает перехват DNS-запросов. Использование DoH позволит обойти этот уровень, что в совокупности с использованием VPN может несколько облегчить вам жизнь. Обратите внимание, само по себе решение не может избавить вас от блокировок, потому что вряд ли в России есть провайдер, полагающийся только на фильтрацию через DNS. Вам нужен еще какой-то вариант обойти блокировки, например VPN, один из описанных в моих предыдущих статьях.

Парадоксально, но в текущем паноптикуме оператору связи ничем не грозит ваш обход его блокировок (с использованием специальных средств для этого), поэтому если вы опасаетесь навредить ему таким образом — эти опасения напрасны.

Но переходить на специальный браузер, чтобы обойти перехват DNS — не наш путь. Наш путь — перевести все устройства домашней сети на DoH, быстро, эффективно и без лишних трудозатрат.

Disclaimer

Поскольку публиковать способы обхода блокировок доступа к информации, запрещенной на территории Российской Федерации, не очень законно, целью этой статьи будет рассказать о методе, позволяющем автоматизировать получение доступа к ресурсам, разрешенным на территории Российской Федерации, но из-за чьих-то действий недоступным напрямую через вашего провайдера. А доступ к другим ресурсам, получаемый в результате действий из статьи, является досадным побочным эффектом и целью статьи ни в коем случае не является.

Разворачиваем собственный DNS-сервер на базе Pi-Hole, использующий Cloudflare DoH для запросов в мир. Цель — зашифровать все DNS-запросы и обойти таким образом операторскую фильтрацию через перехват DNS. Полезный бонус — фильтрация рекламы.

Никаких волшебных know-how не открывается, простая пошаговая инструкция для тех, кому не хочется разбираться во всех хитросплетениях самому.

Что вам для этого потребуется

  1. Доверять Cloudflare. На самом деле это очень важный пункт, поскольку в описываемой реализации все ваши DNS-запросы обрабатываются сервисом Cloudflare. Если вы ему не доверяете — вам придется внедрить другое решение (и это немногим сложнее, чем описанное, но целью этой статьи не является).
  2. Иметь возможность поддерживать в домашней сети постоянно работающий сервер с Linux, который будет обслуживать DNS-запросы ваших устройств. Требование Pi-Hole — от 512M оперативной памяти (впрочем, работу с меньшим объемом сам не проверял). Если ваш роутер или NAS умеют виртуальные машины — это прекрасный вариант, если на полке где-то завалялась Raspberry Pi или другой микрокомпьютер на ARM — не менее хорошо, если на антресолях в коридоре жужжит виртуальная ферма на ESXi — то что я вам рассказываю, вы и сами всё знаете. Если у вас ничего из этого нет — самые младшие решения, типа Orange Pi Zero, на вторичном рынке можно найти за единицы сотен рублей либо привезти из Али за плюс-минус те же деньги. Но выбор платформы сильно выходит за рамки этой статьи, поэтому считаем, что у вас что-то есть. Впрочем, вопросы на этот счет можно задавать в комментариях.
  3. Вы должны иметь представление о использовании Linux и сетевых технологиях. Или хотя бы хотеть получить такое представление. Поскольку объять необъятное в этот раз я не готов, некоторые непонятные для вас моменты вам придется изучить самостоятельно. Впрочем, на конкретные вопросы, конечно же, отвечу в комментариях и вряд ли окажусь единственным отвечающим, так что не стесняйтесь спрашивать.

Исходные данные

IPv4-адрес нашего сервера в домашней сети: 192.168.1.10 и он назначен как статический.

Настройки на Linux выполняем от root (т.е. перед началом настройки выполняем команду sudo su -).

Кратко — логика решения

  1. Устанавливаем и настраиваем Pi-Hole
  2. Устанавливаем и настраиваем cloudflared
  3. Настраиваем ваш домашний роутер
  4. Решаем проблемы

Собственно решение

1. Устанавливаем и настраиваем Pi-Hole

Pi-Hole — это известная домашняя платформа, предназначенная прежде всего для борьбы с рекламой через блокирование запросов к доменам из централизованно обновляемого списка. Не то чтобы это был необходимый компонент решения, но если начал собирать домашний DNS, становится трудно остановиться. А если серьезно — Pi-Hole, возможно, и не идеален, но снимает большой объем головной боли с человека, которому надо "чтобы работало".

Чтобы установить Pi-Hole на уже имеющийся у нас запущенный Linux-сервер, нам достаточно выполнить одну команду:

И далее запущенный скрипт проведет вас по шагам установки.

В момент, когда он спросит вас про выбор Upstream DNS Provider, вы можете выбрать любой, поскольку на следующем шаге мы всё равно будем его менять. Все остальные параметры можно смело оставлять по умолчанию.

В конце инсталляции скрипт покажет вам сгенерированный случайным образом пароль от веб-интерфейса, который вам было бы полезно записать.

Если что-то при установке пошло не так — можно использовать альтернативные способы, описанные тут.

2. Устанавливаем и настраиваем cloudflared

Тут для установки нам потребуется приложить немного больше усилий, но тоже ничего особо сложного.

Выбираем и загружаем инсталлятор для нашей платформы.

После выполнения последней команды мы должны получить вывод, подобный следующему:

Если он у вас такой (естественно, номер версии и билда может отличаться) — то поздравляю, установка прошла успешно. Теперь дело за настройкой.

Создаем пользователя для работы сервиса:

Создаем файл конфигурации сервиса /etc/default/cloudflared:

И даем на него и на исполняемый файл права свежесозданному пользователю:

Далее создаем файл /lib/systemd/system/cloudflared.service, который даст нам возможность интеграции сервиса в systemd:

Активируем сервис и запускаем его:

Если всё получилось — вы увидите, что сервис в состоянии active (running).

Вы можете проверить работу сервиса, например командой dig:

Осталось только подключить сервис к Pi-Hole. Для этого вы заходите в веб-интерфейс Pi-Hole (тут вам пригодится записанный в первом этапе пароль), идете в пункт меню Settings — DNS и делаете его выглядящим приблизительно вот так:

Screenshot of Pi-hole configuration

Если вы забыли записать пароль — ничего страшного, заходите на сервер через ssh и исполняете команду pihole -a -p, она позволит задать новый пароль. Ну и в целом посмотрите ключи команды pihole, там много интересного. Например, обновление системы делается одной командой pihole -up.

3. Настраиваем ваш домашний роутер

Всё многообразие роутеров я, конечно, закрыть этим текстом не могу. Но для большинства домашних роутеров справедливы следующие моменты:

1) У роутера можно задать кастомный DNS-сервер в настройках WAN-интерфейса, даже если IP-адрес получается от провайдера динамически

2) Роутер выдает внутренним клиентам свой адрес в качестве DNS и переправляет их запросы на тот сервер, который указан в настройках WAN

Соответственно, в этом случае нам необходимо и достаточно прописать адрес нашего Pi-Hole в качестве DNS-сервера в настройках WAN-интерфейса домашнего роутера. Важно, чтобы он был единственным DNS-сервером в настройках, если будет указан какой-то еще — роутер будет балансировать запросы между ними по только ему известному принципу и такая ситуация крайне неудобна для отладки проблем в сети.

Если вдруг что-то пошло не так и сервис перестал работать, указанную выше настройку достаточно поменять на адрес DNS-сервера вашего провайдера или, например, 8.8.8.8, а уже потом начинать разбираться.

Если у вас роутер более умный и, например, имеет возможность указать в DHCP, какой адрес раздавать клиентам в качестве DNS-сервера, можете пойти по альтернативному пути и настроить раздачу адреса Pi-Hole клиентам напрямую. Это немного разгрузит роутер, но зато усложнит вышеописанный откат с использования сервиса.

В случае, если что-то не будет получаться — спрашивайте в комментариях, найдем решение.

4. Решаем проблемы

В целом после выполнения вышеописанных пунктов у вас уже всё должно быть хорошо, но бывают нюансы, с которыми я и мои клиенты иногда сталкивались.

Обнаружить такую проблему достаточно просто — если вы пытаетесь зайти на заблокированный сервер, ваш браузер показывает вам ошибку ERR_NAME_NOT_RESOLVED или подобную, а проверка в командной строке через nslookup <имя сервера> в ответ выдает 0.0.0.0.

Также регулярно бывает, что Pi-Hole инсталлируют на сервер, на котором уже работает какой-то веб-сервис. В этом случае вы не получите доступа к веб-интерфейсу управления. Как разруливать такой конфликт — зависит от конкретной ситуации, но основные пути решения — это:

Заключение

Как и обещал, не написал ничего нового. Для многих читателей эта схема понятна и очевидна, и или уже внедрена, или не внедрена за ненадобностью. Многие другие построили что-то подобное по-другому, с использованием тех же или иных компонентов. Предлагаю рассматривать этот пост скорее как заготовку для вашего собственного решения, если оно вам когда-либо потребуется. Но, выполнив его как пошаговую инструкцию, вы уже получите сервис, закрывающий ваши базовые потребности в фильтрации рекламы и использовании DoH.

Для успешного решения проблемы необходимо сделать два шага:

Есть множество инструментов для решения этой проблемы:

Второй способ для роутера представляется более предпочтительным т.к. позволит не только обходить блокировки, но и настроить локальный DNS сервер. Этот способ потребует установки оснастки luci-app-unbound и ее зависимостей, собственно пакета unbound-daemon и unbound-control для сопряжения с локальным DHCP сервером odhcpd.

Большая часть настроек оставлена по умолчанию.





Собственно, настройка шифрования DNS запросов.



Под капотом.

Процесс /usr/sbin/unbound -d запускается с конфигурацией -c /var/lib/unbound/unbound.conf . Файл конфигурации формируется динамически при запуске unbound . В нем есть параметр, который влияет на производительность: num-threads: 1 . В конфигураторе web интерфейса этот параметр отсутствует, но он доступен через прямое редактирование файла конфигурации /etc/config/unbound - option num_threads '2' . Однако, его изменение не влияет на результирующий файл /var/lib/unbound/unbound.conf .
Как выяснилось проблема заключается в сборке самого unbound . Файл конфигурации создается из исходного запуском скрипта /usr/lib/unbound/unbound.sh в котором присутствуют строки, которые это проясняют:

Проблема вторая. Туннель с шифрованием.

Для начала настраиваем доступ к удаленному серверу, в поле Server указываем IP адрес и параметры сервера:





Надеюсь у читателя есть под рукой Linux консоль, которая может или точно понадобится для дпльнейшей настройки. В принципе это можно делать прямо на роутере, если установить нужные пакеты: bind-dig, bind-host, bind-libs, dropbear. Затем подключиться к консоли роутера по ssh и ввести команду:

Переходим на первую вкладку.


И включаем редирект.



На данном этапе настройку можно закончить. Перенаправление в тоннель будет работать при заходе на введенные вручную IP адреса.

Расширенная настройка с использованием файла /etc/net_block

После успешной настройки тоннеля и редиректа можно посмотреть содержимое списков туннелируемых IP адресов командой:

Перенаправляемые в тоннель IP адреса будут находиться в списке ss_rules_dst_forward . Списки создаются при запуске процесса /etc/init.d/shadowsocks-libev скриптом /usr/bin/ss-rules :

Как видно, список может состоять из отдельных адресов и подсетей hash:net . По умолчанию список может содержать 65536 элементов.
Посмотрим список заблокированных IP адресов. Например, его можно получить следующей командой в Linux консоли:

После выполнения команды файл ip_block будет содержать заблокированные IPv4 адреса. Увы, напрямую этот файл использовать не получится, т.к. он содержит очень большое количество адресов, намного превосходящее заданное по умолчанию 65536 строк и еще потому, что исходный список будет очень долго загружаться конфигуратором, даже если изменить заданные по умолчанию ipset параметры.

Идея состоит в том, чтобы преобразовать исходный файл ip_block в файл net_block , который содержит вместо отдельных IP адресов список подсетей. Сделать это можно скриптом на python3 ip2net.py , например, таким:

После выполнения команды получим список подсетей, который вполне поместится в ss_rules_dst_forward :

Полученный файл net_block можно дополнить какими-то своими адресами, записав их в другой файл, например, block и добавить к файлу подсетей командой:

Если своих адресов не много, их можно вносить напрямую, добавляя строки Dst ip/net forward в web интерфейсе на вкладке Redir Rules .


Создать свои сертификаты, подсунуть luci и добавить во все свои браузеры.

Важно: добавление в браузер сертификата, сгенерированного самим luci, проблему не решит, поскольку сертификат самоподписанный (т.е. он один), а браузеры ужесточили правила проверки. Чтобы им угодить, нужна цепочка как минимум из двух сертификатов: корневого (добавляется в браузер) и конечного (подсовывается luci вместе с корневым).

Нагуглить правильное руководство оказалось сложнее, чем я думал. Типичные ошибки в найденных руководствах по созданию сертификатов:

  • Слишком сложно (т.е. лишние действия)
  • Отсутствие команд по созданию корневого CA
  • Создание сертификата без subjectAlternative Name

Как только найду хотя бы одно правильное руководство, добавлю ссылку.

Буду надеяться, что такое руководство в принципе существует.



Правим на предмет req_distinguished_name (оставляем только CN = openwrt ), и на предмет alt_names :

И еще на предмет опции -subj при создании CA-сертификата: -subj "/CN=OpenWRT Router CA/"

AEP ★★★★★ ( 03.04.19 08:12:47 )
Последнее исправление: AEP 03.04.19 08:21:27 (всего исправлений: 1)


Это «слишком сложно», надо ставить go

Какие-то жирные зависимости..


Ошибка возникла при редактировании. Похоже, при редактировании вставлена пустая строка, или в конце строки удален символ «\». Попробуй оригинальный скрипт без редактирования, потом понемножку правь, между правками удаляй каталог tls.

AEP ★★★★★ ( 03.04.19 11:35:27 )
Последнее исправление: AEP 03.04.19 11:35:40 (всего исправлений: 1)


Это не личный сертификат, а сертификат удостоверяющего центра. Импорт на другой вкладке диалога сертификатов.

Блин, вот я балда. Все работает, больше спасибо!

Создать свои сертификаты, подсунуть luci и добавить во все свои браузеры.

А есть вариант без добавления в браузеры?


Теоретически, да. На практике именно с OpenWRT не проверял.

Читайте также: