В отличие от Podkop и ему подобных, этот способ позволяет более точно заворачивать трафик посредством снифинга целевого домена и подключать внешние списки заблокированных сайтов с автоматическим обновлением.
Не нашёл хороших русскоязычных руководств по этой теме, настроил у себя и решил написать инструкцию.
Требования к оборудованию
OpenWrt 24.10.0 или новее.
Не менее 256 МБ ОЗУ.
Не менее 64 МБ ПЗУ (я не проверял на 64 МБ — зависит от того, сколько занимает система для вашего роутера; 128 МБ точно хватит). В теории можно упаковать исполняемый файл sing-box с помощью UPX, но это может увеличить расход оперативной памяти.
На Filogic 820 примерная пропускная способность — 600–800 Мбит/с. На MT7621 должно получиться не менее 100 Мбит/с, возможно больше.
Перенаправление трафика в sing-box. OpenWrt-Momo
Большинство руководств, которые я видел, предполагают использовать софт, в котором маршрутизация происходит до sing-box (например, Podkop или RuAntiBlock).
Если пользователь хочет проводить всю маршрутизацию силами sing-box или xray, обычно предлагается самостоятельно создавать все необходимые правила перенаправления трафика, как в этом руководстве. Это сложно и неудобно (что если вы не хотите направлять весь трафик, а только от определённых клиентов локальной сети или на определённые порты?). Я пробовал настраивать это вручную ещё в 2024 году, у меня ничего не получилось и я надолго забросил эту идею.
Недавно обнаружил, что китайские разработчики сделали пакет для OpenWrt, который делает ровно то, что нужно: направляет трафик в sing-box, позволяя ограничить перенаправляемый трафик по целевым портам и по источникам в локальной сети. Также этот софт может получать настройки из внешнего источника (получает файл конфига по ссылке; для безопасности можно использовать HTTP Basic Authorization).
Итак, рассмотрим интерфейс китайского пакета Momo для OpenWrt:
Главная страница.
Здесь есть кнопки для перезагрузки конфигурации и полного перезапуска сервиса.

Choose Profile: выбрать из настроенных профилей.
Start Delay: задать задержку запуска после старта устройства.
Scheduled Restart: создать cron-задачу для перезапуска сервиса по расписанию (основное назначение - очистка лога sing-box, поскольку он сбрасывается только после перезапуска сервиса).
Test Profile: перед запуском профиля выполняет
sing-box checkдля проверки корректности конфига.Fast Reload: при изменении конфига вместо перезапуска sing-box заставляет текущий процесс перечитать конфиг.
Core Only: отключает все функции перенаправления и просто запускает sing-box.
Загрузка файлов конфига с устройства, их удаление или добавление подписки.

Интерфейс для добавления подписки.

Вкладка, дающая возможность редактировать конфиги прямо из интерфейса.

Вкладка с логами самого Momo и sing-box.

Главная функциональная вкладка для настройки перенаправления трафика в sing-box.

IPv4 DNS Hijack и IPv6 DNS Hijack: перехват IPv4/IPv6 DNS-запросов и их направление в sing-box. Авторы рекомендуют включать оба, если вы планируете обрабатывать DNS силами sing-box: даже если у вас нет IPv6-интернета, локальные компьютеры всё равно могут делать DNS-запросы к роутеру по IPv6 (через link-local).
IPv4 Proxy и IPv6 Proxy: перенаправление IPv4 и IPv6 трафика в sing-box. IPv6 можно выключить, если у вас его нет.
Fake-IP Ping Hijack: в sing-box есть механизм выдачи вместо реальных IP адресов адресов из заданного диапазона (fake-IP) для доменов, которые нужно обрабатывать внутри sing-box. На слабых устройствах можно выдавать адреса из этого диапазона и перенаправлять только запросы к этим адресам в sing-box. Эта опция позволяет возвращать реальный ping до конечного адреса, а не 1 мс до самого роутера. Если вы не настраивали Fake-IP, вам это не нужно, далее я не буду касаться настройки Fake-IP.
TCP Mode: режим перенаправления для TCP-трафика. Нам нужен TPROXY, т.к. TUN гораздо более затратен по CPU для sing-box.
UDP Mode: режим перенаправления для UDP-трафика. Также предпочитаем TPROXY по тем же причинам.
Позволяет по различным критериям включить или отключить перенаправление трафика, источником которого является сам роутер в sing-box. Я просто выключил.

Позволяет по IPv4 / IPv6 / MAC клиента включить или отключить для него перенаправление трафика или перехват DNS-запросов.

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

А если только для определённого хоста то так:

Помимо локальной сети можно добавить другой интерфейс, например гостевой или интерфейс клиентов VPN.

Bypass China Mainland IP: опция, не нужная нам (не направляет трафик к китайским подсетям в sing-box).
-
Destination TCP Port to Proxy: направление в sing-box только части целевых TCP-портов. Используется, чтобы не нагружать sing-box торрент-трафиком (для большого количества соединений требуется много ОЗУ; при 256 МБ ОЗУ может перестать хватать примерно на ~2000 соединений).
Порты, которые я добавил:20, 21 FTP
80, 443, 8080–8880 HTTP/HTTPS
110, 143, 465, 587, 993, 995 почта
2000–2099 есть информация, что используются для Discord
-
Destination UDP Port to Proxy перенаправление UDP-портов в sing-box:
443 QUIC
19294–19344, 50000–50032 Discord
Bypass DSCP пропуск трафика с определённой DSCP-меткой.
Настройки портов, куда перенаправляется трафик, в Momo нет, он читает их из конфигурации sing-box.
Составление конфигурации sing-box
Sing-box использует JSON-формат конфига, описанный на официальном сайте. Здесь упомяну только то, что нам потребуется.
Каркас конфигурации
{
"log": {},
"dns": {},
"endpoints": [],
"inbounds": [],
"outbounds": [],
"route": {},
"experimental": {}
}
Раздел log
Задаёт уровень логов, файл для вывода и т.д.
https://sing-box.sagernet.org/configuration/log/
"log": {
"level": "warn"
},
Раздел dns
Позволяет задать DNS-серверы, на которых будет происходить обработка запросов, и выбирать DNS-сервер в зависимости от домена.
https://sing-box.sagernet.org/configuration/dns/
"dns": {
"servers": [
{
"type": "udp",
"tag": "yandex-dns",
"server": "77.88.8.8",
"detour": "direct-out"
},
{
"type": "udp",
"tag": "NSDI-dns",
"server": "195.208.5.1",
"detour": "direct-out"
},
{
"type": "https",
"tag": "cloudflare-dns",
"server": "1.1.1.1",
"detour": "direct-out"
},
{
"type": "https",
"tag": "google-dns",
"server": "8.8.8.8",
"detour": "direct-out"
},
{
"type": "https",
"tag": "Quad9-dns",
"server": "dns.quad9.net",
"domain_resolver": "yandex-dns",
"detour": "direct-out"
}
],
"rules": [
{
"rule_set": "geosite-category-ru",
"server": "NSDI-dns"
},
{
"rule_set": "refilter_domains",
"server": "Quad9-dns"
}
]
},
Quad9 используется, поскольку этот сервис не передаёт IP клиента, запросившего адрес (были случаи, когда зарубежные DNS намеренно отдавали некорректный адрес при запросе с русского IP).
Раздел endpoints
Позволяет задавать WireGuard и Tailscale-соединения.
https://sing-box.sagernet.org/configuration/endpoint/
"endpoints": [
{
"type": "wireguard",
"tag": "warp",
"detour": "direct-out",
"system": false,
"mtu": 1280,
"address": [
"172.16.0.2/32",
"*:*:*/128"
],
"private_key": "*",
"peers": [
{
"address": "162.159.192.1",
"port": 2408,
"public_key": "bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=",
"allowed_ips": [
"0.0.0.0/0",
"::/0"
],
"persistent_keepalive_interval": 30,
"reserved": "dHbH"
}
],
"amnezia": {
"jc": 120,
"jmin": 23,
"jmax": 911
}
}
],
Внимание: amnezia доступна только при использовании форка.
Раздел inbounds
Здесь настраиваются способы получения трафика.
https://sing-box.sagernet.org/configuration/inbound/
"inbounds": [
{
"type": "tproxy",
"tag": "tproxy-in",
"listen": "::",
"listen_port": 12345,
"tcp_fast_open": true
},
{
"type": "direct",
"tag": "dns-in",
"listen": "::",
"listen_port": 5354
}
],
Важно: блоки tproxy-in и dns-in надо называть именно так, Momo ищет их при чтении файла, чтобы получить порт. Можно дополнительно создать mixed-прокси, для которого весь трафик будет идти в туннель.
Раздел outbounds
Выходы для трафика: нужно настроить прокси, через который будет выводиться заблокированный трафик. При использовании форка доступны дополнительные типы, включая XHTTP.
https://sing-box.sagernet.org/configuration/outbound/
"outbounds": [
{
"type": "direct",
"tag": "direct-out",
"connect_timeout": "20s",
"domain_resolver": {
"server": "yandex-dns",
"strategy": "ipv4_only"
}
},
{
"type": "urltest",
"tag": "block-check",
"outbounds": [
"warp",
"tunnel"
],
"url": "http://cp.cloudflare.com/generate_204",
"interval": "1m"
},
{
"packet_encoding": "xudp",
"server": "*",
"server_port": 443,
"uuid": "*",
"type": "vless",
"tag": "tunnel",
"tcp_fast_open": true,
"tcp_multi_path": true,
"reuse_addr": true,
"flow": "xtls-rprx-vision",
"tls": {
"enabled": true,
"server_name": "*",
"utls": {
"enabled": true,
"fingerprint": "firefox"
},
"reality": {
"enabled": true,
"public_key": "*",
"short_id": "*"
}
},
"domain_resolver": {
"server": "Quad9-dns",
"strategy": "prefer_ipv6"
}
}
],
directотправляет трафик напрямую.urltestпозволяет выбрать наиболее быстрый/рабочий outbound (поддерживает endpoints).Для каждого outbound можно задать, какой DNS-сервер использовать и как выбирать IP (стратегии:
ipv4_only,prefer_ipv6и т.д.).
Раздел route
Один из ключевых разделов: определяет, какой трафик куда пойдёт. Также позволяет подключать rule_set, подготовленные другими людьми.
https://sing-box.sagernet.org/configuration/route/
Я вижу два основных подхода:
Направить все соединения к российским ресурсам напрямую; остальное в туннель.
Направлять в туннель только то, что есть в списках заблокированного; всё остальное напрямую.
Также можно сочинить множество собственных правил (например, для блокировки рекламы). Я знаю два возможных источника списков заблокированного:
antizapret-sing-box: огромный список; с большой вероятностью там будет любой заблокированный ресурс, но из-за отсутствия аккуратной очистки там много мёртвых доменов, что негативно влияет на производительность и потребление памяти.
Re-filter-lists: попытка создать более чистый список (была статья на Хабре). Минусы: автор редко обновляет список (раз в пару месяцев или реже) и принимает решения о добавлении доменов по своим критериям. (Личный пример: я предложил три аниме-сайта с подтверждением блокировки с сайта Роскомнадзора, включая известный MyAnimeList; все три предложения были отклонены без объяснения. Другие предложения, в том числе мои, обрабатывались нормально.)
В примерах ниже использую Re-filter.
Вариант направления по спискам
"route": {
"rules": [
{
"action": "sniff"
},
{
"protocol": "dns",
"action": "hijack-dns"
},
{
"inbound": "dns-in",
"action": "hijack-dns"
},
{
"ip_is_private": true,
"outbound": "direct-out"
},
{
"protocol": "bittorrent",
"outbound": "direct-out"
},
{
"rule_set": "refilter_domains",
"outbound": "block-check"
},
{
"action": "resolve",
"strategy": "ipv4_only"
},
{
"rule_set": "refilter_ipsum",
"outbound": "block-check"
}
],
"rule_set": [
{
"tag": "refilter_domains",
"type": "remote",
"format": "binary",
"url": "https://github.com/1andrevich/Re-filter-lists/releases/latest/download/ruleset-domain-refilter_domains.srs"
},
{
"tag": "refilter_ipsum",
"type": "remote",
"format": "binary",
"url": "https://github.com/1andrevich/Re-filter-lists/releases/latest/download/ruleset-ip-refilter_ipsum.srs"
}
],
"auto_detect_interface": true,
"default_domain_resolver": "google-dns"
},
Объяснение правил:
sniffпозволяет sing-box определить протокол трафика. Без него нельзя узнать, что трафик DNS, bittorrent и т.д.hijack-dnsперенаправляет обработку DNS во внутренний DNS sing-box. Отдельно дляdns-inпотому что у меня был случай, когда трафик не распознавался как DNS, и тысячи UDP-соединений забили память роутера.ip_is_privateесли на tproxy попали соединения на локальные IP, их нужно отправить напрямую (Momo, по идее, не должен их заворачивать, но перестраховка не лишняя).bittorrentесли торрент-трафик оказался на портах, которые мы заворачиваем на sing-box, лучше направить его напрямую (включая соображения возможных проблем от хостера).refilter_domainsиrefilter_ipsumразделены, т.к. туннель может иметь IPv6-адрес при отсутствии такового у провайдера; при попадании на соответствующий outbound разрешение будет происходить по правилам этого outbound.resolveменяем в зависимости от наличия или отсутствия IPv6 у домашнего провайдера.
Вариант: российские ресурсы напрямую, остальное в туннель
"route": {
"rules": [
{
"action": "sniff"
},
{
"protocol": "dns",
"action": "hijack-dns"
},
{
"inbound": "dns-in",
"action": "hijack-dns"
},
{
"ip_is_private": true,
"outbound": "direct-out"
},
{
"protocol": "bittorrent",
"outbound": "direct-out"
},
{
"rule_set": "geosite-category-ru",
"outbound": "direct-out"
},
{
"action": "resolve",
"strategy": "ipv4_only"
},
{
"rule_set": "geoip-ru",
"outbound": "direct-out"
}
],
"rule_set": [
{
"tag": "geosite-category-ru",
"type": "remote",
"format": "binary",
"url": "https://raw.githubusercontent.com/Chocolate4U/Iran-sing-box-rules/rule-set/geosite-category-ru.srs"
},
{
"tag": "geoip-ru",
"type": "remote",
"format": "binary",
"url": "https://raw.githubusercontent.com/Chocolate4U/Iran-sing-box-rules/rule-set/geoip-ru.srs"
}
],
"auto_detect_interface": true,
"default_domain_resolver": "google-dns",
"final": "block-check"
},
final sing-box по умолчанию отправляет трафик в первый outbound; с помощью final можно переопределить выход по умолчанию.
Раздел experimental
Позволяет управлять хранением кэша rule_set и включить внешний мониторинг.
https://sing-box.sagernet.org/configuration/experimental/
"experimental": {
"cache_file": {
"enabled": false
},
"clash_api": {
"external_controller": "[::]:9090"
}
}
Здесь я отключаю кэш, чтобы приложение лишний раз не записывало в постоянную память роутера. Мониторинг можно посмотреть через YACD
Внимание: если открыть HTTPS-версию вместо HTTP, современные браузеры могут разрешать доступ только к localhost, это ограничение браузеров ради безопасности (чтобы сайты не могли сканировать локальную сеть).
Пример окна мониторинга:


Дополнительно
Для перенаправления на TPROXY требуются пакеты
kmod-nf-tproxyиkmod-nft-socket.Если у вас, как и у меня, не работает китайский репозиторий (у меня он заблокирован и даже через европейский прокси не работает), просто скачайте из релизов пакеты под вашу архитектуру и установите, например:
momo_2025.08.11-r3_aarch64_cortex-a53.ipkиluci-app-momo_1.0.5-r1_all.ipk.Рекомендую установить
kmod-tcp-bbr, он даёт преимущества BBR для всех tcp соединений, которые будут идти через sing-box.Чтобы уменьшить шанс падения при нехватке памяти при неожиданно большом количестве соединений, можно поставить
zram-swap.После установки sing-box отключите его сервис, дальше его будет запускать Momo. Внимание: OpenWrt отключает автозагрузку только после перезапуска.
Можно попробовать избежать падений, добавив в init.d-файл Momo значение переменной окружения
GOMEMLIMITс нужным лимитом. Это заставит sing-box раньше вызывать сборщик мусора, но замедлит его в эти моменты. Для 256 МБ памяти без использования zram-swap разумный лимит около 100 МБ.
Методы установки DSCP метки
transmission поддерживает установку меток через параметр peer_socket_tos. Исходный код
qBittorrent имеет параметры peer-tos и peer-dscp но по информации от 23 года добавляет метку не изначально а уже после установления соединения с пиром что мешает обработке соединений правилами.
в Windows можно любому приложению задать DSCP групповой политикой или через powershell команды.
New-NetQosPolicy -Name "qb" -AppPathNameMatchCondition "qbittorrent.exe" -PolicyStore GPO:localhost -DSCPAction 8
Get-NetQosPolicy
Remove-NetQosPolicy -Name "qb"
Комментарии (10)

Rubilnik
18.12.2025 06:11В отличие от Podkop и ему подобных, этот способ позволяет более точно заворачивать трафик посредством снифинга целевого домена и подключать внешние списки заблокированных сайтов с автоматическим обновлением.
Стоп, но podkop же тоже так умеет. Как локальные списки, так и текстовые и из внешних источников.

SlavaSch
18.12.2025 06:11И маршрутизацию подкоп делает силами sing-box

abubaca4 Автор
18.12.2025 06:11Версия которой я пользовался примерно год назад делала NFTSet из заблокированных доменов и при запросе адреса оттуда делала маршрут на этот адрес в прокси.
Если они перешли полностью на использование sing-box, то это в чём то положительное изменение тк точность стала выше, но одновременно и отрицательное, тк маршрутизация с его помощью более ресурсо затратна и помешает работе на слабых роутерах.

SlavaSch
18.12.2025 06:11Как раз почти год назад переезд на коробку и случился)
Для слабых устройств есть вариант, например, со скрипто getDomains - да, не так удобно, но вполне рабочее решение. А кому надо удобно - всегда можно взять роутер за 3-4к рублей с 256-512МБ ОЗУ, 128МБ ПЗУ и на 820 филоджике

abubaca4 Автор
18.12.2025 06:11В последний раз когда я пользовался подкопом он поддерживал только .lst списки с одним доменом/подсетью на строку. При этом внешний список с периодическим обновлением можно было задать только на один из двух выходов трафика, при этом второй выход трафика имел меньший приоритет(те нельзя направить трафик во второй выход если он был задан в первом например в автоматически обновляемом списке). При этом какие то 25к подсетей вешали подкоп намертво поскольку он их добавлял правилами маршрутизации по 1 штуке.
Поддержка списков sing-box прямо это позитивное изменение, но я всё равно предпочту сам написать конфиг для sing-box, как я его написал для всех телефонов где он используется и компьютеров.

itdog
18.12.2025 06:11В отличие от Podkop и ему подобных, этот способ позволяет более точно заворачивать трафик посредством снифинга целевого домена
Вам уже указали на ошибку. Как видите, лучше всё-таки смотреть исходный код проекта перед публикацией статьи на Хабре.
Или даже проще, можно поставить podkop и посмотреть конфиг sing-box и dnsmasq.
Или ещё проще, посмотрите схему работы на картинке: https://podkop.net/docs/fakeip/
А по вашей реализации. Процессор, который сниффает весь трафик - это лёгкий, но не лучший подход для soho-роутера. Тем более вы знаете, что такое FakeIP/FakeDNS.
За рекламу, хоть и такую, спасибо.
glebliutsko
В Dnsmasq (который по умолчанию используется в openwrt как DNS) есть опция NFTSet/IPSet. Позволяет задать список доменов и их отрезолвенные IP класть в nftables/ipset.
Ну а далее, уже правилами nftables с трафиком можно делать что угодно. Например ставить метку на пакет и маршрутизирвоать по ней, натравливать на соединение zapret для обмана DPI.
Zipdots
С ресурсами за CDN будет проблемка
abubaca4 Автор
Podkop и RuAntiBlock примерно так и работают.
Вносят все домены в NFTSet, далее когда по какому то домену есть запрос сохраняют ip со сроком жизни кеша 2 часа и делают для этого ip маршрут в прокси. Если у домена было много ip то берётся только один из них.
Я не отрицаю что этот способ более производительный но
Что если у пользователя настроен DoH(многие современные браузеры это делают автоматически и это надо отключать)?
Что если пользователь уже получил ip от dns на мобильном интернете, пришёл домой и у него в кеше остался ip про который роутер не знает?
Что если множество сайтов сидят за CDN и блока по ip нет, только по домену силами тпсу? Гоним трафик на все сайты в прокси?
Sing-box лишён всех этих проблем так как достаёт домен прямо из запроса.
glebliutsko
По моим наблюдениям android сбрасывает локальный dns кэш при переключении между сетями.
Не проверял, но подозреваю, что sing-box тоже пустит трафик для всего IP в VPN. Определить нужен ли VPN для сайта нужно ещё во время отправки TCP-SYN, а это происходит сильно раньше, чем браузер раскроет домен отправив SNI.
Если у вас нет своей ASN, то маршрутизировать трафик анализом SNI не получится физически, т.к. если мы переключем маршрут для уже установленного TCP соединения, то оно сломается, т.к. разный внешний IP.
Тут согласен. К сожалению, браузеры решили, что они в праве по умолчанию переопределять настойки ОС. Приходится постоянно отключать, что бы не только NFTSet работал, но и локальные домены резолвились.
В целом не имею ничего против sing-box, и не настаиваю на своем способе. Просто он мне кажется слишком громостким для роутера.