VPN на OpenWrt: точечный обход блокировок по доменам — настройка

Автор: Редактор блога HubHide VPN

Главная претензия к VPN на роутере звучит одинаково: включил — и половина нужного отвалилась. Банк не пускает, госпортал ругается, доставка не понимает, где вы живёте. Желание понятное: пусть через туннель идёт только то, что без него не работает, а остальное напрямую. На стоковых прошивках это делается мучительно или не делается вовсе. На OpenWrt делается, и хорошо. Ценой того, что придётся залезть в консоль и понять, как связаны три вещи: список доменов, DNS и таблица маршрутизации.

И предупреждение сразу, а не в конце, потому что в конце его никто не читает. Вы будете править маршрутизацию и фаервол на устройстве, через которое выходит в интернет весь дом, и неудачная строчка оставляет квартиру без сети — иногда так, что обратно в веб-интерфейс вы уже не зайдёте и пойдёте искать скрепку. Я однажды в такое въехал субботним вечером, и это был мой худший вечер за год. Держите под рукой инструкцию по сбросу и умейте попадать в failsafe-режим.

Чем OpenWrt лучше стоковой прошивки

Разница не в количестве галочек, а в природе системы: OpenWrt — это Linux на вашем роутере, со своим менеджером пакетов, конфигами в текстовых файлах и полноценным фаерволом. Что это даёт мне практически.

  • Ставится любой софт под вашу архитектуру, а не только утверждённый вендором.
  • Правила маршрутизации пишутся какие угодно, а не какие предусмотрел производитель.
  • DNS-сервер доступен целиком, вместе с возможностью реагировать на конкретные домены.
  • Всё воспроизводимо: настройки живут в текстовых файлах, я раскатываю их на другой роутер за минуту.

Минус один, зато весомый: делать придётся руками, мастера в три клика нет, и LuCI многое умеет, но самое интересное живёт в консоли. Нужна та же идея без консоли — смотрите в сторону выборочной маршрутизации на Keenetic, там это решается политиками доступа мышкой, хотя гибкости меньше. Общая логика раздельного пропуска трафика — в разборе split tunneling.

Что поставить перед началом

Начинаю я всегда с обновления списка пакетов:

opkg update

Дальше, к слову, набор для WireGuard:

opkg install wireguard-tools kmod-wireguard luci-proto-wireguard

Последний добавляет WireGuard в список типов интерфейса в LuCI. Без него всё пишется в конфиги руками — тоже вариант, но мышкой, если честно, приятнее. А теперь пункт, на котором спотыкаются все: я и сам споткнулся, полдня не понимая, почему схема, собранная строго по инструкции, не складывает в набор ни одного адреса.

Штатный dnsmasq в OpenWrt собран в урезанном виде и не умеет складывать результаты резолвинга в наборы адресов. А без этого вся затея с маршрутизацией по доменам не работает вообще. Нужна полная сборка:

opkg install dnsmasq-full --download-only

opkg remove dnsmasq && opkg install dnsmasq-full

Команды разделены намеренно, и это не педантизм. Удаление dnsmasq оставляет сеть без DNS, и если полная сборка в этот момент не скачается, вы останетесь с неработающим роутером и без возможности что-нибудь скачать. Сначала качаем, потом меняем. Ещё пригодятся ip-full и curl для автообновления списков. И проверьте место командой df -h: на роутерах с восемью мегабайтами флеша всё это может не влезть — обычная история для устройств постарше.

[Изображение: вывод установки пакетов и проверка свободного места на флеш-памяти]

Поднимаем туннель

Два пути, и выбор, по моему опыту, зависит от того, насколько агрессивно у вас фильтруют трафик.

WireGuard. Работает в ядре, а значит быстро и с минимальной нагрузкой. Настраивается через LuCI: новый интерфейс, протокол WireGuard, приватный ключ, адрес внутри туннеля, публичный ключ сервера, endpoint, разрешённые адреса. Не забудьте keepalive — без него туннель за провайдерским NAT засыпает. И шаг, который забывают примерно все: интерфейс нужно определить в зону фаервола, создать для туннеля отдельную зону, разрешить ей исходящие и настроить переадресацию из локальной сети. Пока интерфейс вне зон, трафик через него не пойдёт ни при каких маршрутах, сколько бы вы их ни правили. Я правил.

VLESS через прокси-клиент. Нужен там, где WireGuard опознаётся и режется на уровне провайдера. Как именно системы фильтрации это делают, я разбирал в статье про механику ТСПУ и DPI; коротко — у WireGuard характерный вид пакетов, а у VLESS с Reality его нет. Ставится отдельным пакетом, дальше трафик заворачивается на него прозрачно. И скажу честно: набор пакетов и синтаксис сильно зависят от версии OpenWrt и от клиента, так что универсальная инструкция здесь была бы враньём — смотрите документацию под вашу ветку. Важно другое: прокси-клиент работает в пространстве пользователя, а не в ядре, и нагружает процессор заметно сильнее, на слабом роутере разница бывает кратной.

Совет простой, и он мой любимый: начните с WireGuard. Поднялся и живёт стабильно — не усложняйте. VLESS доставайте, когда WireGuard не работает.

Селективная маршрутизация: как это вообще устроено

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

Цепочка получается такая:

  1. Список доменов. То, что должно ходить через VPN.
  2. DNS. Резолвит имена и складывает полученные адреса в набор.
  3. Набор адресов. Живой список IP, который постоянно пополняется.
  4. Правило фаервола. Помечает пакеты, идущие на адреса из набора.
  5. Правило маршрутизации. Отправляет помеченные пакеты в отдельную таблицу, где шлюзом стоит туннель.

На современных версиях OpenWrt это делается связкой dnsmasq и nftables. В конфигурации DNS для домена указывается набор, куда складывать адреса:

list nftset '/example.com/4#inet#fw4#vpn_domains'

По частям: домен, четвёрка — это IPv4, дальше семейство таблиц, имя таблицы фаервола и имя набора. И оговорюсь: синтаксис зависит от версии. В ветках с nftables используется nftset, в старых с iptables — ipset и другой формат строки, так что проверьте, что стоит у вас, прежде чем копировать команды из интернета. Половина проблем тут — от инструкции под другую ветку. Я на этом терял вечера.

Дальше маршрутная часть. Создаётся отдельная таблица, в ней шлюзом назначается туннельный интерфейс:

ip route add default dev wg0 table 100

И правило, отправляющее помеченный трафик туда:

ip rule add fwmark 0x1 table 100

Осталось правило фаервола, которое вешает метку на пакеты с адресом назначения из набора. Собирайте его через конфигурацию firewall, а не руками: иначе не переживёт перезагрузку, я проверял.

[Изображение: схема связки — список доменов, DNS, набор адресов, метка, таблица маршрутизации]

Списки доменов: где брать и как обновлять

Руками такой список не ведут. Вернее, ведут два дня, потом бросают, я пробовал. Есть готовые подборки, которые сообщество поддерживает и обновляет — по сервисам, по категориям, по признаку недоступности; искать их стоит в репозиториях, посвящённых обходу блокировок, а конкретных ссылок не даю, они живут недолго. Механика автообновления простая: скрипт качает список, преобразует в формат конфигурации DNS, перезапускает dnsmasq, вешается на расписание и работает без вас. Дальше практические соображения, которые сэкономят нервы.

Не берите гигантские списки. Каждая строка в конфигурации DNS — это память, а её на роутере мало: десятки тысяч доменов на устройстве со 128 мегабайтами оперативки способны уронить dnsmasq. Начните с сотни-двух нужных и расширяйте по надобности.

Свой короткий список держите отдельно. У каждого свой набор: рабочие сервисы, стриминг, один мессенджер. Пусть лежит в файле, который не затирается автообновлением.

Проверяйте после обновления. Битый список ломает DNS целиком, то есть дома пропадает весь интернет, а не только заблокированное. Разумный скрипт сначала проверяет синтаксис на копии и только потом применяет.

Помните про поддомены. Правило на example.com обычно покрывает и всё, что ниже, но сервисы часто размазаны по доменам: картинки на одном, видео на втором, API на третьем. Половина случаев «добавил домен, всё равно не работает» — ровно про это, я проверял.

Почему без правильного DNS ничего не поедет

Этот раздел я бы напечатал крупным шрифтом, если бы мог. Схема держится на одном условии: устройства в вашей сети должны спрашивать DNS именно у роутера. Запрос ушёл мимо — адрес в набор не попал, метка не поставилась, маршрут не применился, трафик пошёл напрямую, и самое противное, что выглядит всё настроенным, а вы будете упорно искать ошибку в маршрутах, где её нет. А мимо роутера DNS уходит постоянно, и причин хватает.

  • В настройках устройства вручную прописан сторонний DNS-сервер.
  • Браузер использует DNS поверх HTTPS со своим сервером — в современных браузерах это часто включено по умолчанию и полностью обходит роутер.
  • Приложение ходит к своему DNS напрямую, игнорируя системные настройки.
  • Устройство получило адрес DNS-сервера по IPv6, и этот адрес не ваш роутер.

Что с этим делают. Перехватывают DNS на уровне фаервола: всё, что идёт на 53-й порт наружу, заворачивается на роутер независимо от адресата. Шифрованный DNS так не перехватить, его блокируют отдельно либо отключают руками в браузере. Кстати, про IPv6: если провайдер его выдаёт, а маршрутизацию вы настроили только для IPv4, часть трафика пойдёт мимо всей конструкции, и проще всего выключить IPv6, пока не разберётесь. Про этот класс проблем есть отдельный разбор утечек DNS, WebRTC и IPv6. Запомните формулу: нет перехвата DNS — нет точечного обхода. Остальное вторично.

Проверяем, что нужное идёт куда надо

Проверка тут двусторонняя, и обе стороны одинаково важны. Сначала убедитесь, что заблокированное идёт через туннель: откройте страницу проверки соединения — с поправкой на то, что она сама должна попасть в ваш список доменов, иначе честно покажет домашний адрес. Проще проверять на конкретном сервисе из списка: открывается — маршрут работает. Потом убедитесь, что остальное идёт напрямую: зайдите на российский сайт, показывающий IP, и посмотрите, видите ли адрес провайдера. Видите адрес VPN-сервера — в туннель ушло больше, чем планировалось. Из консоли я смотрю две вещи: что накопилось в наборе, командой nft list set с указанием таблицы и имени набора, и путь до конкретного адреса командой ip route get. Пустой набор, кстати, почти всегда означает, что DNS туда ничего не складывает.

[Изображение: вывод содержимого набора адресов и проверка маршрута до конкретного хоста]

Полезная привычка, к которой я пришёл не сразу: после каждого изменения проверяйте обе стороны. Легко починить одно и незаметно сломать другое.

Хватит ли мощности вашему роутеру

Одного ответа нет, но ориентиры внятные. Значение имеют три ресурса: флеш (влезет ли софт), оперативная память (переживёт ли dnsmasq ваши списки) и процессор (какая будет скорость).

Класс роутера Флеш и память Чего ожидать
Старые устройства 8 МБ флеш, 64 МБ RAM Полный набор пакетов может не влезть. Списки только короткие. Скорость через туннель низкая
Средний сегмент 16 МБ флеш, 128 МБ RAM Рабочий минимум. WireGuard тянет, прокси-клиенты уже тяжело
Современные 32 МБ и больше, 256 МБ RAM и больше Комфортно всё, включая VLESS через прокси
Мини-ПК и x86 Без ограничений Упирается в канал провайдера, а не в железо

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

Что делать, когда туннель упал

Он упадёт. Вопрос в том, чем это обернётся, и развилку тут надо пройти заранее. Ладно, по порядку.

Первый вариант: пропускать напрямую. Туннель умер — помеченные пакеты уходят через провайдера. Интернет дома работает, заблокированное не открывается. Удобно, но не подходит, если вам важно, чтобы этот трафик не шёл в открытую.

Второй: блокировать. Туннель умер — помеченный трафик никуда не идёт. Строже и предсказуемее: человек видит «сайт недоступен» вместо тихой подмены маршрута. Для дома я советую первый вариант, для рабочих задач — второй.

Реализуется правилом в отдельной таблице: либо запасной маршрут через провайдера, либо явное отбрасывание пакетов. Мониторинг делается скриптом на расписании: пингует дальний конец туннеля, при нескольких неудачах подряд перезапускает интерфейс. Ключевое слово — «подряд». Один потерянный пинг ничего не значит, а скрипт, дёргающий интерфейс от каждой сетевой икоты, делает только хуже, и я такие скрипты видел. И банальное, но работающее: поднимите второй туннель до другого узла и переключайтесь, если первый не встаёт. Конфигурации на несколько серверов места на роутере не занимают.

[Изображение: схема поведения сети при падении туннеля — прямой выход против блокировки]

Если собрать всё вместе

Точечный обход на OpenWrt — цепочка из пяти звеньев: список доменов, DNS, набор адресов, метка на пакете, отдельная таблица маршрутизации. Порвётся любое — перестанет работать вся конструкция, причём тихо, без сообщений об ошибке. Чаще всего рвётся звено с DNS. Проверяйте его первым. И не гонитесь за огромными списками, начните с того, что нужно лично вам, а главное — не тестируйте это на единственном роутере в доме, если не готовы объяснять домашним, почему вечером нет интернета: возьмите старый роутер или разверните OpenWrt на виртуалке. Схема капризная, но, когда заработала, работает годами и внимания не требует.

Конфигурации под роутер — WireGuard и VLESS, на несколько узлов сразу — лежат в личном кабинете HubHide готовыми: четырнадцати дней теста без карты хватит, чтобы собрать схему и убедиться, что железо тянет. Не сходится — поддержка подскажет по модели. Клиенты под остальные устройства — на странице загрузок.

Частые вопросы

Как настроить VPN на OpenWrt?

Установите пакеты WireGuard и полную сборку dnsmasq, создайте туннельный интерфейс через LuCI, обязательно определите его в зону фаервола и настройте переадресацию из локальной сети. Дальше поднимайте селективную маршрутизацию, если через туннель нужен не весь трафик.

Как пустить через VPN только часть сайтов?

Через связку DNS и наборов адресов. Вы задаёте список доменов, DNS роутера при резолвинге складывает адреса в набор, правило фаервола помечает пакеты на эти адреса, а правило маршрутизации отправляет помеченное в таблицу, где шлюзом стоит туннель. Остальное идёт напрямую.

Почему точечный обход не работает?

В девяти случаях из десяти виноват DNS. Устройство спросило адрес не у роутера, а у стороннего сервера или через шифрованный DNS в браузере — адрес не попал в набор, маршрут не применился. Проверьте, что DNS-запросы перехватываются роутером, и отключите IPv6, если он не настроен параллельно.

Хватит ли мощности роутера?

Для WireGuard хватает большинства устройств с 16 мегабайтами флеша и 128 мегабайтами оперативной памяти. Для прокси-клиента с VLESS нужно заметно больше — он работает вне ядра и сильнее нагружает процессор. Плюс селективной схемы в том, что через туннель идёт малая часть трафика, так что требования к железу ниже, чем при полном туннелировании.

Вам будет интересно