Выявление пакетов от DPI на роутере

Всем привет! Задача проста: выявлять и направлять через VPS заблокированные ресурсы на уровне домашнего роутера. Сейчас пытаюсь реализовать на базе микротика. На данный момент отлавливаю ответ от DPI следующим правилом:

/ip firewall filter add action=add-src-to-address-list address-list=rkn address-list-timeout=1w chain=forward comment=
“RST to Address list” connection-state=established in-interface=pppoe-out1 packet-size=40 protocol=tcp
src-port=443,80 tcp-flags=rst

Затем соединения с хостами, из сформировавшегося списка “подозрительных” ip-адресов направляю через VPN:

/ip firewall mangle
add action=mark-routing chain=prerouting dst-address-list=rkn new-routing-mark=rkn passthrough=yes

Проблема в том, что правило фильтра слишком широкое, и в список попадает много лишних, легитимных соединений. В статье на хабре ValdikSS писал: “В случае с HTTPS-сайтами, DPI присылает TCP Reset-пакет, тоже с Identification = 1 и Flags = 0”, но в моём случае это не так почему-то, всё наоборот: DF-флаг на месте (1), identification = 0. Провайдер - ростелеком, Нижний Новгород.

Подскажите, можно-ли как-то средствами микротика однозначно идентифицировать ответ от DPI (TCP-reset)?

Эта информация чуть ли не пятилетней давности, с тех пор многие системы DPI изменились или были заменены.

Почему из всех возможных методов обхода блокировок вы выбрали именно этот? Вас чем-то не устроили «классические» методы маршрутизации заблокированных адресов (которые тоже могут маршрутизировать много «лишнего»)?

Приветствую! Так вот как раз и не устроили тем, что маршрутизируют много «лишнего», ищу способ исправить этот момент

Привет!
У меня провайдер тоже ростелеком. В принципе с его DPI (не ТСПУ) в целом легко бороться.
На микроте две команды:
под https значение ttl=equal возможно придется подобрать индивидуально Wireshark в помощь.

1    block - http
      chain=forward action=drop protocol=tcp in-interface=ether1 src-port=80 content=Location: http://warning.rt.ru/ log=no log-prefix="" 

 2    block - https
      chain=forward action=drop tcp-flags=rst protocol=tcp ttl=equal:118 in-interface=ether1 src-port=443 packet-size=40 log=no log-prefix=""

Ну и в дополнении к этому Настройка BGP для обхода блокировок, версия 3.1. И немного Q&A / Хабр

P.S.
Ростелеком вроде не баловался подменой DNS, но все равно запросы лучше также в тунель отправлять

Привет! Увы, это решение уже не работает должным образом, по крайней мере в Нижнем Новгороде :frowning:

А DNS заворачиваете в туннель?

DNS через DoH Cloudflare

Поделюсь своим способом.
Мой провайдер осуществляет блокировку интересным способом, отправляя FIN,ACK пакет после ClientHello. Видимо они думали что это усложнит жизнь тем кто захочет обойти блокировку DPI.

Фейковый пакет FIN,ACK мало чем отличается от других кроме всегда одинакового TTL=57 что недостаточно для выявления блокировки.

Но я нашел способ его выявлять практически со 100% гарантией.

Принцип работы
Мы создаем два правила. Первое помечает все соединения в которых мы нашли ClientHello пакет.
Второе правило ловит следующий пакет и проверяет его на FIN,ACK при условии что объем переданных пакетов в соединении не превышает 1000 байт. Значение в 1000 байт я подбирал экспериментально. Если 2-ое правило срабатывает то добавляем ip сервера в список для обхода блокировок.

Вероятность что в первых 1000 байт соединения, отсылая приветствие, мы получим пинок под зад стремится к нулю, следовательно нас блокируют.

Реализация

В IP-Firewall-Mangle создаем два правила:

Первое правило:

Посмотреть



Второе правило:

Посмотреть



Данный способ также хорошо подойдет если провайдер отсылает фейковый RST пакет, т.к мы отсекаем пакеты после 1000 байт и тем самым уменьшаем вероятность ложного срабатывания.

Заметил у своего провайдера новый тип блокировки

Теперь после clienthello делается drop пакетов вместо FIN,ACK

Добавил новое правило на роутер, теперь ищется пакет от клиента PSH,ACK после clienthello. Пока тестирую на ложные срабатывания

Также придумал как обнаруживать блокировку по ip. Но скорее всего будет много ложных срабатываний. Тесты покажут.

Все это наводит меня на мысли что нужно делать active probing на стороне клиента. Чтобы автоматически и достоверно определять факт блокировки

В этом, собственно, и вопрос: как качественно сделать этот самый “Active Probing”? Желательно, средствами Микротика…

Средствами микротика никак. Насколько мне известно функционал routeros не позволяет отправлять свои пакеты.

Лишь только дропанием каких-либо пакетов можно обойти только пассивный DPI, который не может блокировать пакеты по признаку соединения. Активный DPI после срабатывания блочит весь tcp сеанс.
Сейчас провайдеров лишь только с пассивным DPI не так много осталось.

На routeros есть scripting, возможно с ним что-то можно соорудить.
Можно запускать докер контейнеры с linux, но не могу сказать насколько они окажутся урезанными в возможностях

Речь не про дроп пакетов. Идея состоит в том чтобы роутер мог автоматически определять факт блокировки. Это позволит отказаться от многотысячных списков и ручного наполнения. Комфорт просто несоизмеримый. Заходишь на сайт - connection reset. Нажимаешь F5 и сайт открывается. А если приложение где тысячи доменов заблочены по маске? Пару раз посвайпал и все работает.

Вот у меня и крутится в голове идея про active probing для клиента.

Выглядит не просто реализуемым.
Особенно на таких ограниченных поделках как mikrotik.

Нужно каким-то образом распознать факт обращения к IP, по факту вызвать некий обработчик
Либо нужно распознать через пассивный анализ трафика факт сброса соединения и тоже вызвать некий обработчик.
Либо повеситься на ресолв DNS и проверять каждый заресолвленный IP.
Обработчик может, например, добавить IP в ipset/nfset. Это не так сложно , сложнее первое.
Само ядро просто так не может взять и запустить процесс по приходу определенных пакетов.
Будь такое возможно, и бурст таких пакетов запустил бы тысячи, если не миллионы процессов.
Напрашивается написание некого NFQUEUE обработчика, а чтобы сократить ему сложноту и снизить нагрузку, можно использовать описанный выше в теме подход с маркировкой соединения через connmark.
Но это все, разумеется, выходит за уютный счастливый мирок любителя микроты.
Преодоление сопротивления микротоделателей для доступа к linux явно не стоит того, проще снести это все и накатить openwrt. Или пробовать докер. Но что там с неймспейсами - это вопрос

Еще потенциальная проблема может быть с отслеживанием аномальных ситуаций. Сброс может произойти по желанию самого сервера, если он, например, перегружен. Чтобы каждый такой чих не приводил к вечному занесению IP. А как сделать невечное ? В ipset это невозможно, там нет даты/времени добавления. Тереть каждый день ? Тогда придется каждый день заново нажимать F5.
Можно сделать отдельный set для успешных соединений. Если хоть раз прокатило - больше не проверять. Не проверять повторно и неуспешные.