Skip to content

Huawei-LTE-routers-mods/zapret

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

zapret v.28

English
-------

For english version refer to docs/readme.eng.txt

Для чего это надо
-----------------

Обойти блокировки веб сайтов http.

Как это работает
----------------

У провайдеров в DPI бывают бреши. Они случаются от того, что правила DPI пишут для
обычных пользовательских программ, опуская все возможные случаи, допустимые по стандартам.
Это делается для простоты и скорости. Нет смысла ловить хакеров, которых 0.01%,
ведь все равно эти блокировки обходятся довольно просто даже обычными пользователями.

Некоторые DPI не могут распознать http запрос, если он разделен на TCP сегменты.
Например, запрос вида "GET / HTTP/1.1\r\nHost: kinozal.tv......"
мы посылаем 2 частями : сначала идет "GET ", затем "/ HTTP/1.1\r\nHost: kinozal.tv.....".
Другие DPI спотыкаются, когда заголовок "Host:" пишется в другом регистре : например, "host:".
Кое-где работает добавление дополнительного пробела после метода : "GET /" => "GET  /"
или добавление точки в конце имени хоста : "Host: kinozal.tv."

Как это реализовать на практике в системе linux
-----------------------------------------------

Как заставить систему разбивать запрос на части ? Можно прогнать всю TCP сессию
через transparent proxy, а можно подменить поле tcp window size на первом входящем TCP пакете с SYN,ACK.
Тогда клиент подумает, что сервер установил для него маленький window size и первый сегмент с данными
отошлет не более указанной длины. В последующих пакетах мы не будем менять ничего.
Дальнейшее поведение системы по выбору размера отсылаемых пакетов зависит от реализованного
в ней алгоритма. Опыт показывает, что linux первый пакет всегда отсылает не более указанной
в window size длины, остальные пакеты до некоторых пор шлет не более max(36,указанный_размер).
После некоторого количества пакетов срабатывает механизм window scaling и начинает
учитываться фактор скалинга, размер пакетов становится не более max(36,указанный_рамер << scale_factor).
Не слишком изящное поведение, но поскольку на размеры входящик пакетов мы не влияем,
а объем принимаемых по http данных обычно гораздо выше объема отсылаемых, то визуально
появятся лишь небольшие задержки.
Windows ведет себя в аналогичном случае гораздо более предсказуемо. Первый сегмент
уходит указанной длины, дальше window size меняется в зависимости от значения,
присылаемого в новых tcp пакетах. То есть скорость почти сразу же восстанавливается
до возможного максимума.

Перехватить пакет с SYN,ACK не представляет никакой сложности средствами iptables.
Однако, возможности редактирования пакетов в iptables сильно ограничены.
Просто так поменять window size стандартными модулями нельзя.
Для этого мы воспользуемся средством NFQUEUE. Это средство позволяет
передавать пакеты на обработку процессам, работающим в user mode.
Процесс, приняв пакет, может его изменить, что нам и нужно.

iptables -t mangle -I PREROUTING -p tcp --sport 80 --tcp-flags SYN,ACK SYN,ACK -j NFQUEUE --queue-num 200 --queue-bypass

Будет отдавать нужные нам пакеты процессу, слушающему на очереди с номером 200.
Он подменит window size. PREROUTING поймает как пакеты, адресованные самому хосту,
так и маршрутизируемые пакеты. То есть решение одинаково работает как на клиенте,
так и на роутере. На роутере на базе PC или на базе OpenWRT.
В принципе этого достаточно.
Однако, при таком воздействии на TCP будет небольшая задержка.
Чтобы не трогать хосты, которые не блокируются провайдером, можно сделать такой ход.
Создать список заблоченых доменов или скачать его с rublacklist.
Заресолвить все домены в ipv4 адреса. Загнать их в ipset с именем "zapret".
Добавить в правило :

iptables -t mangle -I PREROUTING -p tcp --sport 80 --tcp-flags SYN,ACK SYN,ACK -m set --match-set zapret src -j NFQUEUE --queue-num 200 --queue-bypass

Таким образом воздействие будет производиться только на ip адреса, относящиеся к заблокированным сайтам.
Список можно обновлять через cron раз в несколько дней.
Если обновлять через rublacklist, то это займет довольно долго. Более часа. Но ресурсов
этот процесс не отнимает, так что никаких проблем это не вызовет, особенно, если система
работает постоянно.

Если DPI не обходится через разделение запроса на сегменты, то иногда срабатывает изменение
"Host:" на "host:". В этом случае нам может не понадобится замена window size, поэтому цепочка
PREROUTING нам не нужна. Вместо нее вешаемся на исходящие пакеты в цепочке POSTROUTING :

iptables -t mangle -I POSTROUTING -p tcp --dport 80 -m set --match-set zapret dst -j NFQUEUE --queue-num 200 --queue-bypass

В этом случае так же возможны дополнительные моменты. DPI может ловить только первый http запрос, игнорируя
последующие запросы в keep-alive сессии. Тогда можем уменьшить нагрузку на проц, отказавшись от процессинга ненужных пакетов.

iptables -t mangle -I POSTROUTING -p tcp --dport 80 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:5 -m set --match-set zapret dst -j NFQUEUE --queue-num 200 --queue-bypass

Случается так, что провайдер мониторит всю HTTP сессию с keep-alive запросами. В этом случае
недостаточно ограничивать TCP window при установлении соединения. Необходимо посылать отдельными
TCP сегментами каждый новый запрос. Эта задача решается через полное проксирование трафика через
transparent proxy (TPROXY или DNAT). TPROXY не работает с соединениями, исходящими с локальной системы,
так что это решение применимо только на роутере. DNAT работает и с локальными соединениеми,
но имеется опасность входа в бесконечную рекурсию, поэтому демон запускается под отдельным пользователем,
и для этого пользователя отключается DNAT через "-m owner". Полное проксирование требует больше ресурсов
процессора, чем манипуляция с исходящими пакетами без реконструкции TCP соединения.

iptables -t nat -I PREROUTING -p tcp --dport 80 -j DNAT --to 127.0.0.1:1188
iptables -t nat -I OUTPUT -p tcp --dport 80 -m owner ! --uid-owner tpws -j DNAT --to 127.0.0.1:1188

ПРИМЕЧАНИЕ: DNAT на localhost работает в цепочке OUTPUT, но не работает в цепочке PREROUTING без включения параметра route_localnet :

sysctl -w net.ipv4.conf.<incoming_interface_name>.route_localnet=1

Можно использовать "-j REDIRECT --to-port 1188" вместо DNAT , однако в этом случае процесс transparent proxy
должен слушать на ip адресе входящего интерфейса или на всех адресах. Слушать на всех - не есть хорошо
с точки зрения безопасности. Слушать на одном (локальном) можно, но в случае автоматизированного
скрипта придется его узнавать, потом динамически вписывать в команду. В любом случае требуются дополнительные усилия.

Если ваше устройство поддерживает аппаратное ускорение (flow offloading, hardware nat, hardware acceleration), то iptables могут не работать.
При включенном offloading пакет не проходит по обычному пути netfilter. 
Необходимо его отключить. Да, ваш хилый роутер уже не потянет гигабит, даже 200-250 не потянет, а на торрентах и того меньше.
Но если у вас такой линк, и вы хотите продвинутых вещей от роутера, то вам стоит задуматься о покупке mini pc с двумя или более gigabit ethernet.

В новых ядрах (и в более старых, openwrt портировал изменение на 4.14) присутствует software flow offloading (SFO).
Пакеты, проходящие через SFO, так же проходят мимо большей части механизмов iptables.
При включенном SFO работает DNAT/REDIRECT (tpws). Эти соединения исключаются из offloading.
Однако, остальные соединения идут через SFO, потому NFQUEUE будет срабатывать только до помещения
соединения в flowtable. Практически это означает, что nfqws будет работать на window size changing,
но не будут работать опции по модификации содержимого пакетов.
Offload включается через специальный target в iptables "FLOWOFFLOAD". Не обязательно пропускать весь трафик через offload.
Можно исключить из offload соединения, которые должны попасть на tpws или nfqws.
Однако, openwrt не предусматривает выборочного управления offload. Если вы хотите с этим связаться,
вам придется городить свой собственный огород вокруг этого.

Особенности применения ip6tables
--------------------------------

ip6tables работают почти точно так же, как и ipv4, но есть ряд важных нюансов.
В DNAT следует брать адрес --to в квадратные скобки. Например :

 iptables -t nat -I OUTPUT -p tcp --dport 80 -m owner ! --uid-owner tpws -j DNAT --to [::1]:1188
 
Параметра route_localnet не существует для ipv6.
DNAT на localhost (::1) возможен только в цепочке OUTPUT.
В цепочке PREROUTING DNAT возможен на любой global address или на link local address того же интерфейса,
откуда пришел пакет.
NFQUEUE работает без изменений.

Когда это работать не будет
---------------------------

* Если подменяется DNS. С этой проблемой легко справиться.
* Если блокировка осуществляется по IP.
* Если соединение проходит через фильтр, способный реконструировать TCP соединение, и который
следует всем стандартам. Например, нас заворачивают на squid. Соединение идет через полноценный стек tcpip
операционной системы, фрагментация отпадает сразу как средство обхода. Squid правильный, он все найдет
как надо, обманывать его бесполезно.
НО. Заворачивать на squid могут позволить себе лишь небольшие провайдеры, поскольку это очень ресурсоемко.
Большие компании обычно используют DPI, который расчитан на гораздо большую пропускную способность.
Может применяться комбинированный подход, когда на DPI заворачивают только IP из "плохого" списка,
и дальше уже DPI решает пропускать или нет. Так можно снизить нагрузку на DPI в десятки, если не сотни раз,
а следовательно не покупать очень дорогие решения, обойдясь чем-то существенно более дешевым.
Мелкие провайдеры могут покупать услугу фильтрации у вышестоящих, чтобы самим не морочиться, и
они уже будут применять DPI.

nfqws
-----

Эта программа - модификатор пакетов и обработчик очереди NFQUEUE.

 --debug=0|1				; 1=выводить отладочные сообщения
 --daemon				; демонизировать прогу
 --pidfile=<file>			; сохранить PID в файл
 --user=<username>			; менять uid процесса
 --uid=uid[:gid]			; менять uid процесса
 --qnum=200				; номер очереди
 --wsize=4				; менять tcp window size на указанный размер
 --hostcase				; менять регистр заголовка "Host:" по умолчанию на "host:".
 --hostnospace				; убрать пробел после "Host:" и переместить его в конец значения "User-Agent:" для сохранения длины пакета
 --hostspell=HoST			; точное написание заголовка Host (можно "HOST" или "HoSt"). автоматом включает --hostcase
 --dpi-desync                           ; атака по десинхронизации DPI
 --dpi-desync-fwmark=<int|0xHEX>        ; бит fwmark для пометки десинхронизирующих пакетов, чтобы они повторно не падали в очередь. default = 0x40000000
 --dpi-desync-ttl=<int>                 ; установить ttl для десинхронизирующих пакетов
 --dpi-desync-fooling=none|md5sig|badsum ; дополнительные методики как сделать, чтобы десинхронизирующий пакет не дошел до сервера
 --dpi-desync-retrans=0|1               ; 1(default)=дропать оригинальный пакет с данными, заменяя его подделкой, заставляя ОС выполнять ретрансмиссию через 0.2 сек
 --dpi-desync-skip-nosni=0|1		; 1(default)=не применять dpi desync для запросов без hostname в SNI, в частности для ESNI
 --hostlist=<filename>			; применять dpi-desync только к хостам из листа

Параметры манипуляции могут сочетаться в любых комбинациях.

ЗАМЕЧАНИЕ. Как описано ранее, linux при измененном window size ведет себя странно, иначе, чем windows.
Следующие сегменты не восстанавливают свою полную длину. Потому соединение может идти долгое время пачками мелких пакетов.
Параметры модификации содержимого пакета (--hostcase, ...) могут не срабатывать, потому что nfqws не работает с соединением,
а лишь с отдельными пакетами, в которых искомое может не быть найдено, т.к. разбросано по нескольким пакетам.
Если источник пакетов - windows, этой проблемы нет.

АТАКА ДЕСИНХРОНИЗАЦИИ DPI
Суть ее в следующем. После выполнения tcp 3-way handshake идет первый пакет с данными от клиента.
Там обычно "GET / ..." или TLS ClientHello. Мы дропаем этот пакет, заменяя поддельной версией
с другим безобидным, но валидным запросом http или https. Надо, чтобы этот пакет дошел до DPI и был воспринят им как хороший запрос,
но не дошел до сервера назначения. На вооружении есть следующие возможности : установить низкий TTL, посылать пакет с инвалидной чексуммой,
добавлять tcp option "MD5 signature". Все они не лишены недостатков.

* md5sig работает не на всех серверах.
* badsum не сработает, если ваше устройство за NAT, который не пропускает пакеты с инвалидной суммой.
  Linux NAT по умолчанию их не пропускает без особой настройки "sysctl -w net.netfilter.nf_conntrack_checksum=0".
  В openwrt она сделана их коробки, в других роутерах как правило нет, и не всегда это можно изменить.
  Если nfqws работает на роутере, то не обязательно выключать nf_conntrack_checksum. Фейковый пакет не проходит FORWARD, он идет через OUTPUT.
  Но если роутер за другим NAT, например провайдерским, и он не пропускает invalid packets, вы ничего не сможете с этим сделать.
* TTL казалось бы - лучший вариант, но он требует индивидуальной настройки под каждого провайдера. Если DPI находится дальше локальных
  сайтов провайдера, то вы можете отрезать себе доступ к ним. Необходим ip exclude list, заполняемый вручную.
  Вместе с ttl можно применять md5sig. Это ничего не испортит, зато дает неплохой шанс работы сайтов, до которых "плохой" пакет дойдет по TTL.
  Если не удается найти автоматическое решение, воспользуйтесь файлом zapret-hosts-user-exclude.txt.

Оригинальный пакет дропнут, ответа от сервера нет. Что будет делать ОС ? Выполнит ретрансмиссию.
Первая ретрансмиссия случается через 0.2 сек, потом задержка увеличивается экспоненциально.
Так что при каждом соединении будет некоторая задержка. Сайты будут загружаться медленнее.
К сожалению, если отсылать поддельный пакет сразу, до вынесения вердикта NFQUEUE на оригинальный пакет, нет никаких гарантий
какой из пакетов пойдет первым. Поэтому требуется задержка, она вызывается через механизм ретрансмиссии.
Можно отключить дроп оригинального пакета. Иногда это работает. Но не очень надежно.
Если использовать hostlist или ограничение по ipset, то можно избежать ненужных задержек для незаблокированных сайтов.

hostlist относится только к атаке desync. он не работает для других параметров. при попытке запустить nfqws с hostlist и без dpi-desync будет ошибка.
Хосты извлекаются из Host: хедера обычных http запросов и из SNI в TLS ClientHello.
Субдомены учитываются автоматически. Поддерживаются листы gzip.

iptables для задействования атаки :

iptables -t mangle -I POSTROUTING -p tcp -m multiport --dports 80,443 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 2:4 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass

connbytes направит в очередь только первый пакет с данными. mark нужен, чтобы сгенерированный поддельный пакет не попал опять к нам на обработку.
nfqws выставляет fwmark при его отсылке.

tpws
-----

tpws - это transparent proxy.
 --debug=0|1|2		; Количество буковок в output : 0(default)=тихо, 1=подробно, 2=отладка
 --daemon               ; демонизировать прогу
 --pidfile=<file>	; сохранить PID в файл
 --user=<username>	; менять uid процесса
 --uid=uid[:gid]	; менять uid процесса
 --bind-addr		; на каком адресе слушать. может быть ipv4 или ipv6 адрес. если не указано, то слушает на всех адресах ipv4 и ipv6
 			; если указан ipv6 link local, то требуется указать с какого он интерфейса через --bind-iface6
 --bind-linklocal=prefer|force	; если prefer, то найти link local от iface6. если не найдено - использовать первый адрес любого типа.
 				; если force и link local не найден - выход по ошибке.
 --bind-iface4=<iface>	; слушать на первом ipv4 интерфейса iface
 --bind-iface6=<iface>	; слушать на первом ipv6 интерфейса iface. при bind-linklocal определяет интерфейс, откуда брать ipv6 link local
 --bind-wait-ifup=<sec>	; ждать до N секунд появления и поднятия интерфейса
 --bind-wait-ip=<sec>	; ждать до N секунд получения IP адреса (если задан --bind-wait-ifup - время идет после поднятия интерфейса)
 --bind-wait-ip-linklocal=<sec> ; (только если заданы --bind-wait-ip и --bind-linklocal=prefer) согласиться на global address после N секунд
 --socks		; вместо прозрачного прокси реализовать socks4/5 proxy
 --no-resolve		; запретить ресолвинг имен через socks5
 --port=<port>		; на каком порту слушать
 --local-rcvbuf=<bytes> ; SO_RCVBUF для соединений client-proxy
 --local-sndbuf=<bytes> ; SO_SNDBUF для соединений client-proxy
 --remote-rcvbuf=<bytes> ; SO_RCVBUF для соединений proxy-target
 --remote-sndbuf=<bytes> ; SO_SNDBUF для соединений proxy-target
 --skip-nodelay		; не устанавливать в исходящих соединения TCP_NODELAY. несовместимо со split.

 --split-http-req=method|host	; способ разделения http запросов на сегменты : около метода (GET,POST) или около заголовка Host
 --split-pos=<offset>	; делить все посылы на сегменты в указанной позиции. Если отсыл длинее 8Kb (размер буфера приема), то будет разделен каждый блок по 8Kb.
 --hostcase             ; менять регистр заголовка "Host:". по умолчанию на "host:".
 --hostspell=HoST	; точное написание заголовка Host (можно "HOST" или "HoSt"). автоматом включает --hostcase
 --hostdot		; добавление точки после имени хоста : "Host: kinozal.tv."
 --hosttab		; добавление табуляции после имени хоста : "Host: kinozal.tv\t"
 --hostnospace		; убрать пробел после "Host:"
 --hostpad=<bytes>	; добавить паддинг-хедеров общей длиной <bytes> перед Host:
 --methodspace		; добавить пробел после метода : "GET /" => "GET  /"
 --methodeol		; добавить перевод строки перед методом  : "GET /" => "\r\nGET  /"
 --unixeol		; конвертировать 0D0A в 0A и использовать везде 0A
 --hostlist=<filename>  ; действовать только над доменами, входящими в список из filename. поддомены автоматически учитываются. в файле должен быть хост на каждой строке.
			; список читается 1 раз при старте и хранится в памяти в виде иерархической структуры для быстрого поиска.
			; для списка РКН может потребоваться система с 128 Mb памяти ! расчитывайте требование RAM для процесса как 3-5 кратный размер файла списка.
			; по сигналу HUP список будет перечитан при следующем принятом соединении
			; список может быть запакован в gzip. формат автоматически распознается и разжимается

Параметры манипуляции могут сочетаться в любых комбинациях.
Есть исключения : split-pos заменяет split-http-req. hostdot и hosttab взаимоисключающи.

На прикладном уровне в общем случае нет гарантированного средства заставить ядро выплюнуть
блок данных, порезанным в определенном месте. ОС держит буфер отсылки (SNDBUF) у каждого сокета.
Если у сокета включена опция TCP_NODELAY и буфер пуст, то каждый send приводит к отсылке
отдельного ip пакета или группы пакетов, если блок не вмещается в один ip пакет.
Однако, если в момент send уже имеется неотосланный буфер, то ОС присоединит данные к нему,
никакой отсылки отдельным пакетом не будет. Но в этом случае и так нет никакой гарантии,
что какой-то блок сообщения пойдет в начале пакета, на что собственно и заточены DPI.
Разбиение будет производится согласно MSS, который зависит от MTU исходящего интерфейса.
Таким образом DPI, смотрящие в начало поля данных TCP пакета, будут поломаны в любом случае.
Протокол http относится к запрос-ответным протоколам. Новое сообщение посылается только тогда,
когда сервер получил запрос и полностью вернул ответ. Значит запрос фактически был не только отослан,
но и принят другой стороной, а следовательно буфер отсылки пуст, и следующие 2 send приведут
к отсылке сегментов данных разными ip пакетами.
Резюме : tpws гарантирует сплит только за счет раздельных вызовов send, что на практике
вполне достаточно для протоколов http(s).

tpws может биндаться только к одному ip или ко всем сразу.
Для бинда на все ipv4 укажите "0.0.0.0", на все ipv6 - "::". Без параметров биндаемся на все ipv4 и ipv6.
Параметры --bind-wait* могут помочь в ситуациях, когда нужно взять IP с интерфейса, но его еще нет, он не поднят
или не сконфигурирован.
В разных системах события ifup ловятся по-разному и не гарантируют, что интерфейс уже получил IP адрес определенного типа.
В общем случае не существует единого механизма повеситься на событие типа "на интерфейсе X появился link local address".

Параметры rcvbuf и sndbuf позволяют установить setsockopt SO_RCVBUF SO_SNDBUF для локального и удаленного соединения.

Если не указан ни один из параметров модификации содержимого, tpws работает в режиме "tcp proxy mode".
Он отличается тем, что в оба конца применяется splice для переброски данных из одного сокета в другой
без копирования в память процесса. Практически - это то же самое, но может быть чуть побыстрее.
TCP проксирование может быть полезно для обхода блокировок, когда DPI спотыкается на экзотических
хедерах IP или TCP. Вы вряд ли сможете поправить хедеры, исходящие от айфончиков и гаджетиков,
но на linux сможете влиять на них в какой-то степени через sysctl.
Когда соединение проходит через tpws, фактически прокси-сервер сам устанавливает подключение к удаленному
узлу от своего имени, и на это распространяются настройки системы, на которой работает прокси.

Режим "--socks" не требует повышенных привилегий (кроме бинда на привилегированные порты 1..1023).
Поддерживаются версии socks 4 и 5 без авторизации. Версия протокола распознается автоматически.
Подключения к IP того же устройства, на котором работает tpws, включая localhost, запрещены.
socks5 позволяет удаленно ресолвить хосты (curl : --socks5-hostname  firefox : socks_remote_dns=true).
tpws поддерживает эту возможность, однако используется блокирующий ресолвинг. Пока система
ресолвит хост (это может занять секунды), вся активность останавливается.
tpws полностью работает на асинхронных сокетах, но ресолвинг может попортить эту модель.
С ним возможны атаки DoS на tpws. Если tpws обслуживает множество клиентов, то из-за частого
ресолвинга качество обслуживания может существенно ухудшиться.
Если удаленный ресолвинг создает проблемы, настройте клиенты на локальный ресолвинг, включите опцию
--no-resolve на стороне tpws.

Параметр --hostpad=<bytes> добавляет паддинг-хедеров перед Host: на указанное количество байтов.
Если размер <bytes> слишком большой, то идет разбивка на разные хедеры по 2K.
Общий буфер приема http запроса - 64K, больший паддинг не поддерживается, да и http сервера
такое уже не принимают.
Полезно против DPI, выполняющих реассемблинг TCP с ограниченным буфером.
Если техника работает, то после некоторого количества bytes http запрос начнет проходить до сайта.
Если при этом критический размер padding около MTU, значит скорее всего DPI не выполняет реассемблинг пакетов, и лучше будет использовать обычные опции --split-…
Если все же реассемблинг выполняется, то критический размер будет около размера буфера DPI. Он может быть 4K или 8K, возможны и другие значения. 

--skip-nodelay может быть полезен, чтобы привести MTU к MTU системы, на которой работает tpws.
Это может быть полезно для скрытия факта использования VPN. Пониженный MTU - 1 из способов обнаружения
подозрительного подключения. С tcp proxy ваши соединения неотличимы от тех, что сделал бы сам шлюз.

Способы получения списка заблокированных IP
-------------------------------------------

1) Внесите заблокирванные домены в ipset/zapret-hosts-user.txt и запустите ipset/get_user.sh
На выходе получите ipset/zapret-ip-user.txt с IP адресами.

Cкрипты с названием get_reestr_* оперируют дампом реестра заблокированных сайтов :

2) ipset/get_reestr_resolve.sh получает список доменов от rublacklist и дальше их ресолвит в ip адреса
в файл ipset/zapret-ip.txt.gz. В этом списке есть готовые IP адреса, но судя во всему они там в точности в том виде,
что вносит в реестр РосКомПозор. Адреса могут меняться, позор не успевает их обновлять, а провайдеры редко
банят по IP : вместо этого они банят http запросы с "нехорошим" заголовком "Host:" вне зависимости
от IP адреса. Поэтому скрипт ресолвит все сам, хотя это и занимает много времени.
Используется мультипоточный ресолвер mdig (собственная разработка).
Реестр РКН уже настолько огромен, что однопоточный ресолв займет вечность, а многопоточный хоть и тоже много времени,
но хотя бы оно конечно.

3) ipset/get_reestr_ip.txt
взять все IP адреса из реестра и загнать в ipset zapret/zapret6
на роутерах с <128 Mb RAM может стработать только с TMPDIR на внешнем носителе

4) ipset/get_reestr_combined.sh. для провайдеров, которые блокируют по IP https, а остальное по DPI.
IP https и IP без домена заносятся в ipset ipban, остальные в ipset zapret.
на роутерах с <128 Mb RAM может стработать только с TMPDIR на внешнем носителе

Скрипты 3 и 4 убирают из списка мусор. На данный момент мусором считается миллион+ забаненых telegram proxy IP.
Это сокращает размер списка кардинально. Большой объем памяти требуется только для временного хранения скачанного
реестра в /tmp. Потом из списка уберется мусор, он станет значительно легче, поместится в ipset даже на 64 Mb RAM.
Поэтому поможет задание TMPDIR на флэшку.

Cкрипты с названием get_antifilter_* оперируют списками адресов и масок подсетей с сайтов antifilter.network и antifilter.download :

5) ipset/get_antifilter_ip.sh. получает лист https://antifilter.network/download/ip.lst.
лист содержит огромное количество ip (> миллиона).
на роутерах с <128 Mb RAM даже не пытайтесь

7) ipset/get_antifilter_ipsmart.sh. получает лист https://antifilter.network/download/ipsmart.lst.
это умная суммаризация отдельных адресов из ip.lst по маскам от /32 до /22
количество префиксов измеряется всего лишь десятками тысяч, потому это лучшее решение для роутера с 64 Mb RAM

7) ipset/get_antifilter_ipsum.sh. получает лист https://antifilter.network/download/ipsum.lst.
это суммаризация отдельных адресов из ip.lst по маске /24
количество префиксов измеряется всего лишь десятками тысяч, потому можно использовать на роутерах с 64 Mb RAM

Все варианты рассмотренных скриптов автоматически создают и заполняют ipset.
Варианты 2-7 дополнительно вызывают вариант 1.

8) ipset/get_config.sh. этот скрипт вызывает то, что прописано в переменной GETLIST из файла config
Если переменная не определена, то ресолвятся лишь листы для ipset nozapret/nozapret6.

Листы РКН все время изменяются. Возникают новые тенденции. Требования к RAM могут меняться.
Поэтому необходима нечастая, но все же регулярная ревизия что же вообще у вас происходит на роутере.
Или вы можете узнать о проблеме лишь когда у вас начнет постоянно пропадать wifi, и вам придется
его перезагружать каждые 2 часа (метод кувалды).

Листы zapret-ip.txt и zapret-ipban.txt сохраняются в сжатом виде в файлы .gz.
Это позволяет снизить их размер во много раз и сэкономить место на роутере.

На роутерах не рекомендуется вызывать эти скрипты чаще раза за 2 суток, поскольку сохранение идет
либо во внутреннюю флэш память роутера, либо в случае extroot - на флэшку.
В обоих случаях слишком частая запись может убить флэшку, но если это произойдет с внутренней
флэш памятью, то вы просто убьете роутер.

Принудительное обновление ipset выполняет скрипт ipset/create_ipset.sh.
Если передан параметр "no-update", скрипт не обновляет ipset, а только создает его при его отсутствии и заполняет.
Это полезно, когда могут случиться несколько последовательных вызовов скрипта. Нет смысла несколько раз перезаполнять
ipset, это длительная операция на больших листах. Листы можно обновлять раз в несколько суток, и только тогда
вызывать create_ipset без параметра "no-update". Во всех остальных случаях стоит применять "no-update".
Список РКН уже достиг внушительных размеров в сотни тысяч IP адресов. Поэтому для оптимизации ipset
применяется утилита ip2net. Она берет список отдельных IP адресов и пытается интеллектуально создать из него подсети для сокращения
количества адресов. ip2net написан на языке C, поскольку операция ресурсоемкая. Иные способы роутер может не потянуть.
Если ip2net скомпилирован или в каталог ip2net скопирован бинарик, то скрипт create_ipset.sh использует ipset типа hash:net, прогоняя список через ip2net.
В противном случае используется ipset типа hash:ip, список загружается как есть.
Соответственно, если вам не нравится ip2net, просто уберите из каталога ip2net бинарик.

Можно внести список доменов в ipset/zapret-hosts-user-ipban.txt. Их ip адреса будут помещены
в отдельный ipset "ipban". Он может использоваться для принудительного завертывания всех
соединений на прозрачный proxy "redsocks" или на VPN.

IPV6 : если включен ipv6, то дополнительно создаются листы с таким же именем, но с "6" на конце перед расширением.
zapret-ip.txt => zapret-ip6.txt
Создаются ipset-ы zapret6 и ipban6.
Листы с antifilter не содержат список ipv6 адресов.

СИСТЕМА ИСКЛЮЧЕНИЯ IP. Все скрипты ресолвят файл zapret-hosts-user-exclude.txt, создавая zapret-ip-exclude.txt и zapret-ip-exclude6.txt.
Они загоняются в ipset-ы  nozapret и nozapret6. Все правила, создаваемые init скриптами, создаются с учетом этих ipset.
Помещенные в них IP не участвуют в процессе.
zapret-hosts-user-exclude.txt может содержать домены, ipv4 и ipv6 адреса или подсети.

ip2net
------

Утилита ip2net предназначена для преобразования ipv4 или ipv6 списка ip в список подсетей
с целью сокращения размера списка. Входные данные берутся из stdin, выходные выдаются в stdout.
 -4                             ; лист - ipv4 (по умолчанию)
 -6                             ; лист - ipv6
 --prefix-length=min[-max]      ; диапазон рассматриваемых длин префиксов. например : 22-30 (ipv4), 56-64 (ipv6)
 --v4-threshold=mul/div         ; ipv4 : включать подсети, в которых заполнено по крайней мере mul/div адресов. например : 3/4
 --v6-threshold=N               ; ipv6 : минимальное количество ip для создания подсети
В списке могут присутствовать записи вида ip/prefix и ip1-ip2. Такие записи выкидываются в stdout без изменений.
Они принимаются командой ipset. ipset умеет для листов hash:net из ip1-ip2 делать оптимальное покрытие ip/prefix.

Выбирается подсеть, в которой присутствует указанный минимум адресов.
Для ipv4 минимум задается как процент от размера подсети (mul/div. например, 3/4), для ipv6 минимум задается напрямую.

Размер подсети выбирается следующим алгоритмом :
Сначала в указанном диапазоне длин префиксов ищутся подсети, в которых количество адресов - максимально.
Если таких сетей найдено несколько, берется наименьшая сеть (префикс больше).
Например, заданы параметры v6_threshold=2 prefix_length=32-64, имеются следующие ipv6 :
1234:5678:aaaa::5
1234:5678:aaaa::6
1234:5678:aaac::5
Результат будет :
1234:5678:aaa8::/45
Эти адреса так же входят в подсеть /32. Однако, нет смысла проходиться ковровой бомбардировкой,
когда те же самые адреса вполне влезают в /45 и их ровно столько же.
Если изменить v6_threshold=4, то результат будет :
1234:5678:aaaa::5
1234:5678:aaaa::6
1234:5678:aaac::5
То есть ip не объединятся в подсеть, потому что их слишком мало.
Если изменить prefix_length=56-64, результат будет :
1234:5678:aaaa::/64
1234:5678:aaac::5

Требуемое процессорное время для вычислений сильно зависит от ширины диапазона длин префиксов, размера искомых подсетей и длины листа.
Если ip2net думает слишком долго, не используйте слишком большие подсети и уменьшите диапазон длин префиксов.
Учтите, что арфиметика mul/div - целочисленная. При превышении разрядной сетки 32 bit результат непредсказуем.
Не надо делать такое :  5000000/10000000. 1/2 - гораздо лучше.

Фильтрация по именам доменов
----------------------------

Альтернативой ipset является использование tpws со списком доменов.
tpws может читать только один hostlist.

Поддерживаются 2 варианта :
1) Внесите домены для дурения в ipset/zapret-hosts-users.txt. Удалите ipset/zapret-hosts.txt.gz.
Тогда init скрипт будет запускать tpws с листом zapret-hosts-users.txt.

2) Список доменов РКН может быть получен скриптом ipset/get_reestr_hostlist.sh - кладется в ipset/zapret-hosts.txt.gz.
Этот скрипт автоматически добавляет к списку РКН домены из zapret-hosts-user.txt.
init скрипт будет запускать tpws с листом zapret-hosts.txt.gz.

При фильтрации по именам доменов tpws должен запускаться без фильтрации по ipset.
Весь трафик http идет через tpws, и он решает нужно ли применять дурение в зависимости от поля Host: в http запросе.
Это создает повышенную нагрузку на систему.
Сам поиск по доменам работает очень быстро, нагрузка связана с прокачиванием объема данных через процесс.
При использовании больших списков, в том числе списка РКН, оцените объем RAM на роутере !
Если после запуска tpws RAM под завязку или случаются oom, значит нужно отказаться от таких больших списков.

Проверка провайдера
-------------------

Перед настройкой нужно провести исследование какую бяку устроил вам ваш провайдер.

Нужно выяснить не подменяет ли он DNS и какой метод обхода DPI работает.
В этом вам поможет скрипт https://github.com/ValdikSS/blockcheck.

Если DNS подменяется, но провайдер не перехватывает обращения к сторонним DNS, поменяйте DNS на публичный.
Например : 8.8.8.8, 8.8.4.4, 1.1.1.1, 1.0.0.1, 9.9.9.9
Если DNS подменяется и провайдер перехватывает обращения к сторонним DNS, настройте dnscrypt.

Проанализируйте какие методы дурения DPI работают, в соответствии с ними настройте /opt/zapret/config.


Выбор параметров
----------------

Файл /opt/zapret/config используется различными компонентами системы и содержит основные настройки.
Его нужно просмотреть и при необходимости отредактировать.
Выберите MODE :

nfqws_ipset - использовать nfqws для модификации трафика на порт 80 только на IP из ipset "zapret"
nfqws_ipset_https - использовать nfqws для модификации трафика на порты 80 и 443 только на IP из ipset "zapret"
nfqws_all - использовать nfqws для модификации трафика на порт 80 для всех IP
nfqws_all_https - использовать nfqws для модификации трафика на порты 80 и 443 для всех IP
nfqws_all_desync - использовать nfqws для атаки десинхронизации DPI на http и https для всех IP
nfqws_ipset_desync - использовать nfqws для атаки десинхронизации DPI на http и https только на IP из ipset "zapret"
nfqws_hostlist_desync - использовать nfqws для атаки десинхронизации DPI на http и https только на хосты из hostlist.
tpws_ipset - использовать tpws для модификации трафика на порт 80 только на IP из ipset "zapret"
tpws_ipset_https - использовать tpws для модификации трафика на порты 80 и 443 только на IP из ipset "zapret"
tpws_all - использовать tpws для модификации трафика на порт 80 для всех IP
tpws_all_https - использовать tpws для модификации трафика на порты 80 и 443 для всех IP
tpws_hostlist - пропускать через tpws весь трафик на порт 80. tpws применяет дурение только к хостам из hostlist.
ipset - только заполнить ipset. ipset может быть применен для заворота трафика на прокси или на VPN
custom - нужно самому запрограммировать запуск демонов в init скрипте и правила iptables

Можно изменить опции дурения, применяемые демонами nfqws и tpws :

NFQWS_OPT="--wsize=3 --hostspell=HOST"
TPWS_OPT_HTTP="--hostspell=HOST --split-http-req=method"
TPWS_OPT_HTTPS="--split-pos=3"

Отдельно настраиваются опции для атаки по десинхронизации DPI :

DESYNC_MARK=0x40000000
NFQWS_OPT_DESYNC="--dpi-desync --dpi-desync-ttl=0 --dpi-desync-fooling=badsum --dpi-desync-fwmark=$DESYNC_MARK"


Параметр GETLIST указывает инсталятору install_easy.sh какой скрипт дергать
для обновления списка заблокированных ip или хостов.
Он же вызывается через get_config.sh из запланированных заданий (crontab или systemd timer).
Поместите сюда название скрипта, который будете использовать для обновления листов.
Если не нужно, то параметр следует закомментировать.

Можно индивидуально отключить ipv4 или ipv6. Если параметр закомментирован или не равен "1",
использование протокола разрешено.
#DISABLE_IPV4=1
DISABLE_IPV6=1

Количество потоков для многопоточного DNS ресолвера mdig (1..100).
Чем их больше, тем быстрее, но не обидится ли на долбежку ваш DNS сервер ?
MDIG_THREADS=30

Место для хранения временных файлов. При скачивании огромных реестров в /tmp места может не хватить.
Если файловая система на нормальном носителе (не встроенная память роутера), то можно
указать место на флэшке или диске.
TMPDIR=/opt/zapret/tmp

Опции для создания ipset-ов
IPSET_OPT="hashsize 262144 maxelem 2097152"
ПРО РУГАНЬ в dmesg по поводу нехватки памяти.
Может так случиться, что памяти в системе достаточно, но при попытке заполнить огромный ipset
ядро начинает громко ругаться, ipset заполняется не полностью.
Вероятная причина в том, что превышается hashsize, заданный при создании ipset (create_ipset.sh).
Происходит переаллокация списка, не находится непрерывных фрагментов памяти нужной длины.
Это лечится увеличением hashsize. Но чем больше hashsize, тем больше занимает ipset в памяти.
Задавать слишком большой hashsize для недостаточно больших списков нецелесообразно.

Опции для вызова ip2net. Отдельно для листов ipv4 и ipv6.
IP2NET_OPT4="--prefix-length=22-30 --v4-threshold=3/4"
IP2NET_OPT6="--prefix-length=56-64 --v6-threshold=5"

Следующие настройки не актуальны для openwrt :

Если ваша система работает как роутер, то нужно вписать названия внутреннего и внешнего интерфейсов :
IFACE_LAN=eth0
IFACE_WAN=eth1
ВАЖНО : настройка маршрутизации , маскарада и т.д. не входит в задачу zapret.
Включаются только режимы, обеспечивающие перехват транзитного трафика.

Параметр INIT_APPLY_FW=1 разрешает init скрипту самостоятельно применять правила iptables.
При иных значениях или если параметр закомментирован, правила применены не будут.
Это полезно, если у вас есть система управления фаерволом, в настройки которой и следует прикрутить правила.

Прикручивание к системе управления фаерволом или своей системе запуска
----------------------------------------------------------------------

Если вы используете какую-то систему управления фаерволом, то она может вступать в конфликт
с имеющимся скриптом запуска. При повторном применении правил она могла бы поломать настройки iptables от zapret.
В этом случае правила для iptables должны быть прикручены к вашему фаерволу отдельно от запуска tpws или nfqws.

Следующие вызовы позволяют применить или убрать правила iptables отдельно :

 /opt/zapret/init.d/sysv/zapret start-fw
 /opt/zapret/init.d/sysv/zapret stop-fw
 
А так можно запустить или остановить демоны отдельно от фаервола :

 /opt/zapret/init.d/sysv/zapret start-daemons
 /opt/zapret/init.d/sysv/zapret stop-daemons
 
Вариант custom
--------------

custom код вынесен в отдельный shell include
/opt/zapret/init.d/sysv/custom
или
/opt/zapret/init.d/openwrt/custom

Нужно свой код вписать в функции :
zapret_custom_daemons
zapret_custom_firewall

В файле custom пишите ваш код, пользуясь хелперами из "functions" или "zapret".
Смотрите как там сделано добавление iptables или запуск демонов.
Используя хелпер функции, вы избавитесь от необходимости учитывать все возможные случаи
типа наличия/отсутствия ipv6, является ли система роутером, имена интерфейсов, ...
Хелперы это учитывают , вам нужно сосредоточиться лишь на фильтрах iptables и
параметрах демонов.

Код для openwrt и sysv немного отличается. В sysv нужно обрабатывать и запуск, и остановку.
Запуск это или остановка передается в параметре $1 (0 или 1).
В openwrt за остановку демонов отвечает procd, а firewall вычищается при "fw3 restart",
потому нет необходимости реализовывать логику останова.

При апгрейде нужно сохранить лишь custom, другие файлы править не надо.

Пример установки на debian-подобную систему
-------------------------------------------

На debian основано большое количество дистрибутивов linux, включая ubuntu.
Здесь рассматриваются прежде всего Debian 8+ и Ubuntu 16+.
Но с большой вероятностью может сработать и на производных от них.
Главное условие - наличие systemd, apt и нескольких стандартных пакетов в репозитории.

Установить пакеты :
 apt-get update
 apt-get install ipset curl dnsutils git

Скопировать директорию zapret в /opt или скачать через git :
 cd /opt
 git clone --depth 1 https://github.com/bol-van/zapret

Запустить автоинсталятор бинариков. Он сам определит рабочую архитектуру и настроит все бинарики.
 /opt/zapret/install_bin.sh
АЛЬТЕРНАТИВА : make -C /opt/zapret. Получите динамические бинарики под вашу ось.
Для сборки требуются dev пакеты : zlib1g-dev libcap-dev libnetfilter-queue-dev

Настроить параметры согласно разделу "Выбор параметров".

Создать ссылку на service unit в systemd :
 ln -fs /opt/zapret/init.d/systemd/zapret.service /lib/systemd/system

Удалить старые листы, если они были созданы ранее :
 /opt/zapret/ipset/clear_lists.sh
По желанию прописать в /opt/zapret/ipset/zapret-hosts-user.txt свои домены.
Выполнить скрипт обновления листа :
 /opt/zapret/ipset/get_config.sh
Настроить таймер systemd для обновления листа :
 ln -fs /opt/zapret/init.d/systemd/zapret-list-update.service /lib/systemd/system
 ln -fs /opt/zapret/init.d/systemd/zapret-list-update.timer /lib/systemd/system

Принять изменения в systemd :
 systemctl daemon-reload

Включить автозапуск службы :
 systemctl enable zapret

Включить таймер обновления листа :
 systemctl enable zapret-list-update.timer

Запустить службу :
 systemctl start zapret

Попробовать зайти куда-нибудь : http://ej.ru, http://kinozal.tv, http://grani.ru.
Если не работает, то остановить службу zapret, добавить правило в iptables вручную,
запустить nfqws или tpws в терминале под рутом с нужными параметрами.
Пытаться подключаться к заблоченым сайтам, смотреть вывод программы.
Если нет никакой реакции, значит скорее всего указаны неверные параметры или ip назначения нет в ipset.
Если реакция есть, но блокировка не обходится, значит параметры обхода подобраны неверно, или это средство
не работает в вашем случае на вашем провайдере.
Никто и не говорил, что это будет работать везде.
Попробуйте снять дамп в wireshark или "tcpdump -vvv -X host <ip>", посмотрите действительно ли первый
сегмент TCP уходит коротким и меняется ли регистр "Host:".

Шпаргалка по управлению службой и таймером :

enable auto start : systemctl enable zapret
disable auto start : systemctl disable zapret
start : sytemctl start zapret
stop : systemctl stop zapret
status, output messages : systemctl status zapret
timer info : systemctl list-timer
delete service : systemctl disable zapret ; rm /lib/systemd/system/zapret.service
delete timer : systemctl disable zapret-list-update.timer ; rm /lib/systemd/system/zapret-list-update.*

Centos 7+, Fedora
-----------------

Centos с 7 версии и более-менее новые федоры построены на systemd.
В качестве пакетного менеджера используется yum.

Установить пакеты :
 yum install -y curl ipset dnsutils git

Далее все аналогично debian.

OpenSUSE
--------

Новые OpenSUSE основаны на systemd и менеджере пакетов zypper.

Установить пакеты :
 zypper --non-interactive install curl ipset

Далее все аналогично debian, кроме расположения systemd.
В opensuse он находится не в /lib/systemd, а в /usr/lib/systemd.
Правильные команды будут :

 ln -fs /opt/zapret/init.d/systemd/zapret.service /usr/lib/systemd/system
 ln -fs /opt/zapret/init.d/systemd/zapret-list-update.service /usr/lib/systemd/system
 ln -fs /opt/zapret/init.d/systemd/zapret-list-update.timer /usr/lib/systemd/system

Arch linux
----------

Построен на базе systemd.

Установить пакеты :
 pacman -Syy
 pacman --noconfirm -S ipset curl

Далее все аналогично debian.

Gentoo
------

Эта система использует OpenRC - улучшенную версию sysvinit.
Установка пакетов производится командой : emerge <package_name>
Пакеты собираются из исходников.

Требуются все те же ipset, curl, git для скачивания с github.
git и curl по умолчанию могут присутствовать, ipset отсутствует.

 emerge ipset

Настроить параметры согласно разделу "Выбор параметров".

Запустить автоинсталятор бинариков. Он сам определит рабочую архитектуру и настроит все бинарики.
 /opt/zapret/install_bin.sh
АЛЬТЕРНАТИВА : make -C /opt/zapret. Получите динамические бинарики под вашу ось.

Удалить старые листы, если они были созданы ранее :
 /opt/zapret/ipset/clear_lists.sh
По желанию прописать в /opt/zapret/ipset/zapret-hosts-user.txt свои домены.
Выполнить скрипт обновления листа :
 /opt/zapret/ipset/get_config.sh
Зашедулить обновление листа :
 crontab -e
 Создать строчку  "0 12 */2 * * /opt/zapret/ipset/get_config.sh"

Подключить init скрипт :

 ln -fs /opt/zapret/init.d/sysv/zapret /etc/init.d
 rc-update add zapret

Запустить службу :

 rc-service zapret start

Шпаргалка по управлению службой :

enable auto start : rc-update add zapret
disable auto start : rc-update del zapret
start : rc-service zapret start
stop : rc-service zapret stop

Простая установка
-----------------

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

# su
<введи пароль рута>
# apt-get update
# apt-get install git
# cd /opt
# git clone --depth 1 https://github.com/bol-van/zapret
# zapret/install_easy.sh

Надоело ?

# /opt/zapret/uninstall_easy.sh
# rm -r /opt/zapret

Это самый необходимый миниум действий.
Если zapret уже куда-то был скачан, то можно запустить install_easy.sh прямо оттуда.
Инсталятор сам запросит рута, скопирует файлы куда надо.
Можно даже запускать инсталятор из "проводника" через функцию "запустить в терминале", если
"проводник" такое позволяет.

Для более гибкой настройки перед запуском инсталятора следует выполнить раздел "Выбор параметров".

Если система на базе systemd, но используется не поддерживаемый инсталятором менеджер пакетов
или названия пакетов не соответствуют прописанным в инсталятор, пакеты нужно установить вручную.
Требуется : ipset curl

ВАЖНО : Хоть инсталятор и спрашивает является ли система роутером,
настройка маршрутизации , маскарада и т.д. не входит в задачу zapret.
Роутер вдруг сам волшебно не поднимется. Предполагается, что роутер вы уже настроили сами.

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

 install_easy.sh make


openwrt/LEDE
------------

Установить дополнительные пакеты :
opkg update
opkg install iptables-mod-extra iptables-mod-nfqueue iptables-mod-filter iptables-mod-ipopt iptables-mod-conntrack-extra ipset curl
(ipv6) opkg install ip6tables-mod-nat
(опционально) opkg install gzip
(опционально) opkg install grep

ЭКОНОМИЯ МЕСТА :

gzip от busybox в разы медленней полноценного варианта. gzip используется скриптами получения листов.
grep от busybox катастрофически медленный с опцией -f. она применяется в get_reestr_combined.sh. если вы не собираетесь
пользоваться этим скриптом, gnu grep можно не устанавливать
iptables-mod-nfqueue можно выкинуть, если не будем пользоваться nfqws
curl можно выкинуть, если для получения ip листа будет использоваться только get_user.sh
ipset можно выкинуть, если не будем пользоваться ipset-тами, а будем, например, использовать tpws
со списком доменов.

Самая главная трудность - скомпилировать программы на C. Это можно сделать на linux x64 при помощи SDK, который
можно скачать с официального сайта openwrt или LEDE. Но процесс кросс компиляции - это всегда сложности.
Недостаточно запустить make как на традиционной linux системе.
Поэтому в binaries имеются готовые статические бинарики для всех самых распространенных архитектур.
Статическая сборка означает, что бинарик не зависит от типа libc (glibc, uclibc или musl) и наличия установленных so.
Его можно использовать сразу. Лишь бы подходил тип CPU. У ARM и MIPS есть несколько версий.
Скорее всего найдется рабочий вариант. Если нет - вам придется собирать самостоятельно.
Для всех поддерживаемых архитектур бинарики запакованы upx. На текущий момент все, кроме mips64.

Скопировать директорию "zapret" в /opt на роутер.

Если места достаточно, самый простой способ :
 opkg update
 opkg install git-http
 mkdir /opt
 cd /opt
 git clone --depth 1 https://github.com/bol-van/zapret

Если места немного :
 opkg update
 opkg install openssh-sftp-server unzip
 ifconfig br-lan
Скачать на комп с github zip архив кнопкой "Clone or download"->Download ZIP
Скопировать средствами sftp zip архив на роутер в /tmp.
 mkdir /opt
 cd /opt
 unzip /tmp/zapret-master.zip
 mv zapret-master zapret
 rm /tmp/zapret-master.zip

Если места совсем мало :
 opkg update
 opkg install netcat
 cd /tmp
 netcat -l -p 1111 >zapret.tar.gz
На linux системе скачать и распаковать zapret. Оставить необходимый минимум файлов.
Запаковать в архив zapret.tar.gz.
 md5sum zapret.tar.gz
 netcat <router_ip> 1111 <zapret.tar.gz
 <ctrl+c>
На роутере
 md5sum zapret.tar.gz
Проверить соответствие hash.

Не стоит работать с распакованной версией zapret на windows. Потеряются ссылки и chmod.

Запустить автоинсталятор бинариков. Он сам определит рабочую архитектуру и настроит все бинарики.
 /opt/zapret/install_bin.sh

Создать ссылку на скрипт запуска :
 ln -fs /opt/zapret/init.d/openwrt/zapret /etc/init.d
Создать ссылку на скрипт события поднятия интерфейса :
 ln -fs /opt/zapret/init.d/openwrt/90-zapret /etc/hotplug.d/iface

Настроить параметры согласно разделу "Выбор параметров".

Удалить старые листы, если они были созданы ранее :
 /opt/zapret/ipset/clear_lists.sh
По желанию прописать в /opt/zapret/ipset/zapret-hosts-user.txt свои домены.
Выполнить скрипт обновления листа :
 /opt/zapret/ipset/get_config.sh
Зашедулить обновление листа :
 crontab -e
 Создать строчку  "0 12 */2 * * /opt/zapret/ipset/get_config.sh"

Включить автозапуск и службы и запустить ее :
 /etc/init.d/zapret enable
 /etc/init.d/zapret start
ПРИМЕЧАНИЕ : на этапе старта системы интерфейсы еще не подняты. Для некоторых демонов это
может быть критично, они не запустятся после перезагрузки.
Cкрипт из /etc/hotplug.d/iface запустит недостающие службы при поднятии интерфейса lan.

Создать ссылку на firewall include :
 ln -fs /opt/zapret/init.d/openwrt/firewall.zapret /etc/firewall.zapret
Проверить была ли создана ранее запись о firewall include :
 uci show firewall | grep firewall.zapret
Если firewall.zapret нет, значит добавить :
 uci add firewall include
 uci set firewall.@include[-1].path="/etc/firewall.zapret"
 uci set firewall.@include[-1].reload="1"
 uci commit firewall
Проверить не включен ли flow offload :
 uci show firewall.@defaults[0]
Если flow_offloading=1 или flow_offloading_hw=1 ,
 uci set firewall.@defaults[0].flow_offloading=0
 uci set firewall.@defaults[0].flow_offloading_hw=0
 uci commit firewall
Перезапустить фаервол :
 fw3 restart

Посмотреть через iptables -nL, ip6tables -nL или через luci вкладку "firewall" появились ли нужные правила.

ЭКОНОМИЯ МЕСТА : если его мало, то можно оставить в директории zapret лишь подкаталог ipset, файл config и init.d/openwrt.
Далее нужно создать подкаталоги с реально используемыми бинариками (ip2net, mdig, tpws, nfq)
и скопировать туда из binaries рабочие executables.
Рекомендуется оставить ip2net и mdig. Из tpws и nfq оставить лишь тот, что был выбран в config.

ЕСЛИ ВСЕ ПЛОХО С МЕСТОМ : откажитесь от работы со списком РКН. используйте только get_user.sh

ЕСЛИ СОВСЕМ ВСЕ УЖАСНО С МЕСТОМ : берете tpws и делаете все своими руками. поднятие iptables, автостарт бинарика.
С некоторых версий скрипты запуска zapret без ipset не работают (он требуется для ip exclude)

СОВЕТ : Покупайте только роутеры с USB. В USB можно воткнуть флэшку и вынести на нее корневую файловую систему
или использовать ее в качестве оверлея. Не надо мучать себя, запихивая незапихиваемое в 8 мб встроенной флэшки.
Для комфортной работы с zapret нужен роутер с 16 Mb встроенной памяти или USB разъемом и 128+ Mb RAM.
На 64 Mb без swap будут проблемы с листами РКН. Если у вас только 64 Mb, и вы хотите листы РКН, подключите swap.
32 Mb для современных версий openwrt - конфигурация на грани живучести. Возможны хаотические падения процессов в oom.
Работа с листами РКН невозможна в принципе.

Простая установка на openwrt
----------------------------

Работает только если у вас на роутере достаточно места.

Копируем zapret на роутер в /tmp.

Запускаем установщик :
 /tmp/zapret_install_easy.sh
Он скопирует в /opt/zapret только необходимый минимум файлов :
 config
 install_easy.sh
 uninstall_easy.sh
 install_bin.sh
 init.d/openwrt/*
 ipset/*
 binaries/<ваша архитектура>/{tpws,nfqws,ip2net,mdig}

После успешной установки можно удалить zapret из tmp для освобождения RAM :
 rm -r /tmp/zapret

Для более гибкой настройки перед запуском инсталятора следует выполнить раздел "Выбор параметров".

Android
-------

Без рута забудьте про nfqws и tpws в режиме transparent proxy. tpws будет работать только в режиме --socks.

Статистики наличия NFQUEUE в стоковых ядрах android у меня нет, но на первом попавшемся устройстве на базе MTK он есть.
Если NFQUEUE есть, то nfqws проверен - он работает.

В стоковых ядрах нет поддержки ipset. В общем случае сложность задачи по поднятию ipset варьируется от
"не просто" до "почти невозможно". Если только вы не найдете готовое собранное ядро под ваш девайс.

tpws будет работать в любом случае, он не требует чего-либо особенного.
В android нет /etc/passwd, потому опция --user не будет работать. Вместо нее можно
пользоваться числовыми user id и опцией --uid.
Рекомендую использовать gid 3003 (AID_INET). Иначе можете получить permission denied на создание сокета.
Например : --uid 1:3003
В iptables укажите : "! --uid-owner 1" вместо "! --uid-owner tpws".
Напишите шелл скрипт с iptables и tpws, запускайте его средствами вашего рут менеджера.
Скрипты автозапуска лежат тут :
magisk  : /data/adb/service.d
supersu : /system/su.d

Я не проверял не прибивают ли новые андроиды iptables по своей прихоти в процессе работы
или при подключении/отключении wifi, mobile data, ...

Кто силен в разработке под андроид, думаю будет несложно написать простую програмулину
с выбором опций tpws, которая сможет выбрать tpws нужной архитектуры, запустить его
и добавить iptables. Чтобы была возможность автозапуска (после нее применяем настройки
и сразу exit). И чтобы были кнопки start/stop.
Если кто готов такую програмулину написать - все скажут спасибо.
Тогда любой желающий с рутом сможет парой кликов настроить себе tpws.

Другие прошивки
---------------

Для статических бинариков не имеет значения на чем они запущены : PC, android, приставка, роутер, любой другой девайс.
Подойдет любая прошивка, дистрибутив linux. Статические бинарики запустятся на всем.
Им нужно только ядро с необходимыми опциями сборки или модулями.
Но кроме бинариков в проекте используются еще и скрипты, в которых задействуются некоторые
стандартные программы.

ЗАМЕЧАНИЕ. Как показала практика, на некоторых ядрах бинарики с upx падают в segfault.
Если это ваш случай, скачайте upx и распакуйте бинарики. Распаковать можно на любой системе и любой архитектуре.

Основные причины почему нельзя просто так взять и установить эту систему на что угодно :
 * отсутствие доступа к девайсу через shell
 * отсутствие рута
 * отсутствие раздела r/w для записи и энергонезависимого хранения файлов
 * отсутствие возможности поставить что-то в автозапуск
 * отсутствие cron
 * недостаток модулей ядра или опций его сборки
 * недостаток модулей iptables (/usr/lib/iptables/lib*.so)
 * недостаток стандартных программ (типа ipset, curl) или их кастрированность (облегченная замена)
 * кастрированный или нестандартный шелл sh

Если в вашей прошивке есть все необходимое, то вы можете адаптировать zapret под ваш девайс в той или иной степени.
Может быть у вас не получится поднять все части системы, однако вы можете хотя бы попытаться
поднять tpws и завернуть на него через -j REDIRECT весь трафик на порт 80.
Если вам есть куда записать tpws, есть возможность выполнять команды при старте, то как минимум
это вы сделать сможете. Скорее всего поддержка REDIRECT в ядре есть. Она точно есть на любом роутере,
на других устройствах под вопросом. NFQUEUE, ipset на большинстве прошивок отсутствуют из-за ненужности.

Пересобрать ядро или модули для него будет скорее всего достаточно трудно.
Для этого вам необходимо будет по крайней мере получить исходники вашей прошивки.
User mode компоненты могут быть привнесены относительно безболезненно, если есть место куда их записать.
Специально для девайсов, имеющих область r/w, существует проект entware.
Некоторые прошивки даже имеют возможность его облегченной установки через веб интерфейс.
entware содержит репозиторий user-mode компонент, которые устанавливаются в /opt.
С их помощью можно компенсировать недостаток ПО основной прошивки, за исключением ядра.

Подробное описание настроек для других прошивок выходит за рамки данного проекта.

Openwrt является одной из немногих относительно полноценных linux систем для embedded devices.
Она характеризуется следующими вещами, которые и послужили основой выбора именно этой прошивки :
 * полный root доступ к девайсу через shell. на заводских прошивках чаще всего отсутствует, на многих альтернативных есть
 * корень r/w. это практически уникальная особенность openwrt. заводские и большинство альтернативных прошивок
   построены на базе squashfs root (r/o), а конфигурация хранится в специально отформатированной области
   встроенной памяти, называемой nvram.  не имеющие r/w корня системы сильно кастрированы. они не имеют
   возможности доустановки ПО из репозитория без специальных вывертов и заточены в основном
   на чуть более продвинутого, чем обычно, пользователя и управление имеющимся функционалом через веб интерфейс,
   но функционал фиксированно ограничен. альтернативные прошивки как правило могут монтировать r/w раздел
   в какую-то область файловой системы, заводские обычно могут монтировать лишь флэшки, подключенные к USB,
   и не факт, что есть поддержка unix файловых системы. может быть поддержка только fat и ntfs.
 * возможность выноса корневой файловой системы на внешний носитель (extroot) или создания на нем оверлея (overlay)
 * наличие менеджера пакетов opkg и репозитория софта
 * в репозитории есть все модули ядра, их можно доустановить через opkg. ядро пересобирать не нужно.
 * в репозитории есть все модули iptables, их можно доустановить через opkg
 * в репозитории есть огромное количество стандартных программ и дополнительного софта
 * наличие SDK, позволяющего собрать недостающее

Обход блокировки https
----------------------

Как правило трюки с DPI не помогают для обхода блокировки https.
Приходится перенаправлять трафик через сторонний хост.
Предлагается использовать прозрачный редирект через socks5 посредством iptables+redsocks, либо iptables+iproute+vpn.
Настройка варианта с redsocks на openwrt описана в https.txt.
Настройка варианта с iproute+wireguard - в wireguard_iproute_openwrt.txt.

ИНОГДА (но нечасто) работает трюк со сплитом tls handshake на 2 части.
Это можно сделать все теми же средствами. nfqws или tpws с параметром --split-pos.
--split-pos - единственный параметр, который работает на не-HTTP трафике, все остальное работать не будет.
Попробуйте, может вам повезет.

ЧАЩЕ на https работает атака DPI desync, но у нее есть свои нюансы настройки.

Почему стоит вложиться в покупку VPS
------------------------------------

VPS - это виртуальный сервер. Существует огромное множество датацентров, предлагающих данную услугу.
На VPS могут выполняться какие угодно задачи. От простого веб сайта до навороченной системы собственной разработки.
Можно использовать VPS и для поднятия собственного vpn или прокси.
Сама широта возможных способов применения , распространенность услуги сводят к минимуму возможности
регуляторов по бану сервисов такого типа. Да, если введут белые списки, то решение загнется, но это будет уже другая
реальность, в которой придется изобретать иные решения.
Пока этого не сделали, никто не будет банить хостинги просто потому , что они предоставляют хостинг услуги.
Вы как индивидуум скорее всего никому не нужны. Подумайте чем вы отличаетесь от известного VPN провайдера.
VPN провайдер предоставляет _простую_ и _доступную_ услугу по обходу блокировок для масс.
Этот факт делает его первоочередной целью блокировки. РКН направит уведомление, после отказа сотрудничать
заблокирует VPN. Предоплаченная сумма пропадет.
У регуляторов нет и никогда не будет ресурсов для тотальной проверки каждого сервера в сети.
Возможен китайский расклад, при котором DPI выявляет vpn протоколы и динамически банит IP серверов,
предоставляющих нелицензированный VPN. Но имея знания, голову, вы всегда можете обфусцировать
vpn трафик или применить другие типы VPN, более устойчивые к анализу на DPI или просто менее широкоизвестные,
а следовательно с меньшей вероятностью обнаруживамые регулятором.
У вас есть свобода делать на вашем VPS все что вы захотите, адаптируясь к новым условиям.
Да, это потребует знаний. Вам выбирать учиться и держать ситуацию под контролем, когда вам ничего запретить
не могут, или покориться системе.

VPS можно прибрести в множестве мест. Существуют специализированные на поиске предложений VPS порталы.
Например, вот этот : https://vps.today/
Для персонального VPN сервера обычно достаточно самой минимальной конфигурации, но с безлимитным трафиком или
с большим лимитом по трафику (терабайты). Важен и тип VPS. Openvz подойдет для openvpn, но
вы не поднимете на нем wireguard, ipsec, то есть все, что требует kernel mode.
Для kernel mode требуется тип виртуализации, предполагающий запуск полноценного экземпляра ОС linux
вместе с ядром. Подойдут kvm, xen, hyper-v, vmware. 

По цене можно найти предложения, которые будут дешевле готовой VPN услуги, но при этом вы сам хозяин в своей лавке
и не рискуете попасть под бан регулятора, разве что "заодно" под ковровую бомбардировку с баном миллионов IP.
Кроме того, если вам совсем все кажется сложным, прочитанное вызывает ступор, и вы точно знаете, что ничего
из описанного сделать не сможете, то вы сможете хотя бы использовать динамическое перенаправление портов ssh
для получения шифрованного socks proxy и прописать его в броузер. Знания linux не нужны совсем.
Это вариант наименее напряжный для чайников, хотя и не самый удобный в использовании.

About

DPI circumvention on Linux, with Huawei Android modifications

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C 89.1%
  • Shell 10.3%
  • Other 0.6%