mirror of
https://github.com/bol-van/zapret.git
synced 2024-11-29 21:40:52 +03:00
2287 lines
222 KiB
Markdown
2287 lines
222 KiB
Markdown
# zapret v.69
|
||
|
||
# ВНИМАНИЕ, остерегайтесь мошенников
|
||
|
||
zapret является свободным и open source.
|
||
Всякий, кто понуждает вас скачивать zapret только с его ресурса, требует удалить ссылки, видео, файлы, обосновывая эти требования авторскими правами, сам нарушает [лицензию](./LICENSE.txt).
|
||
|
||
# Multilanguage README
|
||
|
||
[![en](https://img.shields.io/badge/lang-en-red.svg)](./readme.en.md)
|
||
[![ru](https://img.shields.io/badge/lang-ru-green.svg)](./readme.md)
|
||
|
||
***
|
||
|
||
- [Зачем это нужно](#зачем-это-нужно)
|
||
- [Быстрый старт](#быстрый-старт)
|
||
- [Как это работает](#как-это-работает)
|
||
- [Что сейчас происходит в России](#что-сейчас-происходит-в-россии)
|
||
- [Как это реализовать на практике в системе linux](#как-это-реализовать-на-практике-в-системе-linux)
|
||
- [Когда это работать не будет](#когда-это-работать-не-будет)
|
||
- [nfqws](#nfqws)
|
||
- [АТАКА ДЕСИНХРОНИЗАЦИИ DPI](#атака-десинхронизации-dpi)
|
||
- [ФЕЙКИ](#фейки)
|
||
- [TCP СЕГМЕНТАЦИЯ](#tcp-сегментация)
|
||
- [ПЕРЕКРЫТИЕ SEQUENCE NUMBERS](#перекрытие-sequence-numbers)
|
||
- [СПЕЦИФИЧЕСКИЕ РЕЖИМЫ IPV6](#специфические-режимы-ipv6)
|
||
- [КОМБИНИРОВАНИЕ МЕТОДОВ ДЕСИНХРОНИЗАЦИИ](#комбинирование-методов-десинхронизации)
|
||
- [РЕАКЦИЯ DPI НА ОТВЕТ СЕРВЕРА](#реакция-dpi-на-ответ-сервера)
|
||
- [РЕЖИМ SYNACK](#режим-synack)
|
||
- [РЕЖИМ SYNDATA](#режим-syndata)
|
||
- [ВИРТУАЛЬНЫЕ МАШИНЫ](#виртуальные-машины)
|
||
- [CONNTRACK](#conntrack)
|
||
- [РЕАССЕМБЛИНГ](#реассемблинг)
|
||
- [ПОДДЕРЖКА UDP](#поддержка-udp)
|
||
- [IP ФРАГМЕНТАЦИЯ](#ip-фрагментация)
|
||
- [МНОЖЕСТВЕННЫЕ СТРАТЕГИИ](#множественные-стратегии)
|
||
- [IPTABLES ДЛЯ NFQWS](#iptables-для-nfqws)
|
||
- [NFTABLES ДЛЯ NFQWS](#nftables-для-nfqws)
|
||
- [FLOW OFFLOADING](#flow-offloading)
|
||
- [tpws](#tpws)
|
||
- [TCP СЕГМЕНТАЦИЯ В TPWS](#tcp-сегментация-в-tpws)
|
||
- [TLSREC](#tlsrec)
|
||
- [MSS](#mss)
|
||
- [ДРУГИЕ ПАРАМЕТРЫ ДУРЕНИЯ](#другие-параметры-дурения)
|
||
- [МНОЖЕСТВЕННЫЕ СТРАТЕГИИ](#множественные-стратегии-1)
|
||
- [СЛУЖЕБНЫЕ ПАРАМЕТРЫ](#служебные-параметры)
|
||
- [IPTABLES ДЛЯ TPWS](#iptables-для-tpws)
|
||
- [NFTABLES ДЛЯ TPWS](#nftables-для-tpws)
|
||
- [Способы получения списка заблокированных IP](#способы-получения-списка-заблокированных-ip)
|
||
- [ip2net](#ip2net)
|
||
- [mdig](#mdig)
|
||
- [Фильтрация по именам доменов](#фильтрация-по-именам-доменов)
|
||
- [Режим фильтрации autohostlist](#режим-фильтрации-autohostlist)
|
||
- [Проверка провайдера](#проверка-провайдера)
|
||
- [Выбор параметров](#выбор-параметров)
|
||
- [Прикручивание к системе управления фаерволом или своей системе запуска](#прикручивание-к-системе-управления-фаерволом-или-своей-системе-запуска)
|
||
- [Вариант custom](#вариант-custom)
|
||
- [Простая установка](#простая-установка)
|
||
- [Простая установка на openwrt](#простая-установка-на-openwrt)
|
||
- [Установка на openwrt в режиме острой нехватки места на диске](#установка-на-openwrt-в-режиме-острой-нехватки-места-на-диске)
|
||
- [Android](#android)
|
||
- [Мобильные модемы и роутеры huawei](#мобильные-модемы-и-роутеры-huawei)
|
||
- [FreeBSD, OpenBSD, MacOS](#freebsd-openbsd-macos)
|
||
- [Windows](#windows)
|
||
- [Другие прошивки](#другие-прошивки)
|
||
- [Обход блокировки через сторонний хост](#обход-блокировки-через-сторонний-хост)
|
||
- [Почему стоит вложиться в покупку VPS](#почему-стоит-вложиться-в-покупку-vps)
|
||
- [Поддержать разработчика](#поддержать-разработчика)
|
||
***
|
||
|
||
## Зачем это нужно
|
||
|
||
Автономное средство противодействия DPI, которое не требует подключения каких-либо сторонних серверов. Может помочь
|
||
обойти блокировки или замедление сайтов http(s), сигнатурный анализ tcp и udp протоколов, например с целью блокировки
|
||
VPN.
|
||
|
||
Проект нацелен прежде всего на маломощные embedded устройства - роутеры, работающие под openwrt. Поддерживаются
|
||
традиционные Linux системы, FreeBSD, OpenBSD, частично MacOS. В некоторых случаях возможна самостоятельная прикрутка
|
||
решения к различным прошивкам.
|
||
|
||
Большая часть функционала работает на windows.
|
||
|
||
## Быстрый старт
|
||
|
||
- [Linux/openWrt](./quick_start.md)
|
||
- [Windows](./quick_start_windows.md)
|
||
|
||
## Как это работает
|
||
|
||
В самом простейшем случае вы имеете дело с пассивным DPI. Пассивный DPI может читать трафик из потока, может инжектить
|
||
свои пакеты, но не может блокировать проходящие пакеты. Если запрос "плохой", пассивный DPI инжектит пакет RST,
|
||
опционально дополняя его пакетом http redirect. Если фейк пакет инжектится только для клиента, в этом случае можно
|
||
обойтись командами iptables для дропа RST и/или редиректа на заглушку по определенным условиям, которые нужно подбирать
|
||
для каждого провайдера индивидуально. Так мы обходим последствия срабатывания триггера запрета. Если пассивный DPI
|
||
направляет пакет RST в том числе и серверу, то вы ничего с этим не сможете сделать. Ваша задача - не допустить
|
||
срабатывания триггера запрета. Одними iptables уже не обойдетесь. Этот проект нацелен именно на предотвращение
|
||
срабатывания запрета, а не ликвидацию его последствий.
|
||
|
||
Активный DPI ставится в разрез провода и может дропать пакеты по любым критериям, в том числе распознавать TCP потоки и
|
||
блокировать любые пакеты, принадлежащие потоку.
|
||
|
||
Как не допустить срабатывания триггера запрета ? Послать то, на что DPI не рассчитывает и что ломает ему алгоритм
|
||
распознавания запросов и их блокировки.
|
||
|
||
Некоторые 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.`
|
||
|
||
Существует и более продвинутая магия, направленная на преодоление DPI на пакетном уровне.
|
||
|
||
Подробнее про DPI:\
|
||
https://habr.com/ru/post/335436 или https://web.archive.org/web/20230331233644/https://habr.com/ru/post/335436/ \
|
||
https://geneva.cs.umd.edu/papers/geneva_ccs19.pdf
|
||
|
||
## Что сейчас происходит в России
|
||
|
||
Раньше, до внедрения повсеместных систем ТСПУ, использовался зоопарк различных DPI у провайдеров. Какие-то были
|
||
активными, какие-то пассивными. Сейчас время простых iptables окончательно ушло. Везде активный DPI ТСПУ, но кое-где
|
||
могут оставаться невыключенными дополнительные старые DPI из зоопарка. В этом случае приходится обходить сразу несколько
|
||
DPI. Все больше становится внереестровых блокировок, о которых вы узнаете только по факту недоступности чего-либо, в
|
||
списках этого нет. Применяются блокировки некоторых диапазонов ip адресов (автономный обход невозможен)
|
||
и протоколов (VPN). На некоторых диапазонах IP используется более строгий фильтр, распознающий попытки обмана через
|
||
сегментацию. Должно быть это связано с некоторыми сервисами, которые пытаются таким образом обмануть DPI.
|
||
|
||
## Как это реализовать на практике в системе linux
|
||
|
||
Если кратко, то варианты можно классифицировать по следующей схеме :
|
||
|
||
1) Пассивный DPI, не отправляющий RST серверу. Помогут индивидуально настраиваемые под провайдера команды iptables. На
|
||
rutracker в разделе "обход блокировок - другие способы" по этому вопросу существует отдельная тема. В данном проекте
|
||
не рассматривается. Если вы не допустите срабатывание триггера запрета, то и не придется бороться с его
|
||
последствиями.
|
||
2) Модификация TCP соединения на уровне потока. Реализуется через proxy или transparent proxy.
|
||
3) Модификация TCP соединения на уровне пакетов. Реализуется через обработчик очереди NFQUEUE и raw сокеты.
|
||
|
||
Для вариантов 2 и 3 реализованы программы tpws и nfqws соответственно. Чтобы они работали, необходимо их запустить с
|
||
нужными параметрами и перенаправить на них определенный трафик средствами iptables или nftables.
|
||
|
||
## Когда это работать не будет
|
||
|
||
* Если подменяется DNS. С этой проблемой легко справиться.
|
||
* Если блокировка осуществляется по IP.
|
||
* Если соединение проходит через фильтр, способный реконструировать TCP соединение, и который следует всем стандартам.
|
||
Например, нас заворачивают на squid. Соединение идет через полноценный стек tcpip операционной системы, фрагментация
|
||
отпадает сразу как средство обхода. Squid правильный, он все найдет как надо, обманывать его бесполезно. НО.
|
||
Заворачивать на squid могут позволить себе лишь небольшие провайдеры, поскольку это очень ресурсоемко. Большие
|
||
компании обычно используют DPI, который рассчитан на гораздо большую пропускную способность. Может применяться
|
||
комбинированный подход, когда на DPI заворачивают только IP из "плохого" списка, и дальше уже DPI решает пропускать
|
||
или нет. Так можно снизить нагрузку на DPI в десятки, если не сотни раз, а следовательно не покупать очень дорогие
|
||
решения, обойдясь чем-то существенно более дешевым. Мелкие провайдеры могут покупать услугу фильтрации у вышестоящих,
|
||
чтобы самим не морочиться, и они уже будут применять DPI.
|
||
|
||
## nfqws
|
||
|
||
Эта программа - модификатор пакетов и обработчик очереди NFQUEUE. Для BSD систем существует адаптированный вариант -
|
||
dvtws, собираемый из тех же исходников (см. [документация BSD](./bsd.md)).
|
||
|
||
```
|
||
@<config_file>|$<config_file> ; читать конфигурацию из файла. опция должна быть первой. остальные опции игнорируются.
|
||
|
||
--debug=0|1 ; 1=выводить отладочные сообщения
|
||
--daemon ; демонизировать прогу
|
||
--pidfile=<file> ; сохранить PID в файл
|
||
--user=<username> ; менять uid процесса
|
||
--uid=uid[:gid] ; менять uid процесса
|
||
--qnum=N ; номер очереди N
|
||
--bind-fix4 ; пытаться решить проблему неверного выбора исходящего интерфейса для сгенерированных ipv4 пакетов
|
||
--bind-fix6 ; пытаться решить проблему неверного выбора исходящего интерфейса для сгенерированных ipv6 пакетов
|
||
--wsize=<winsize>[:<scale_factor>] ; менять tcp window size на указанный размер в SYN,ACK. если не задан scale_factor, то он не меняется (устарело !)
|
||
--wssize=<winsize>[:<scale_factor>] ; менять tcp window size на указанный размер в исходящих пакетах. scale_factor по умолчанию 0. (см. conntrack !)
|
||
--wssize-cutoff=[n|d|s]N ; изменять server window size в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N
|
||
--ctrack-timeouts=S:E:F[:U] ; таймауты внутреннего conntrack в состояниях SYN, ESTABLISHED, FIN, таймаут udp. по умолчанию 60:300:60:60
|
||
--hostcase ; менять регистр заголовка "Host:" по умолчанию на "host:".
|
||
--hostnospace ; убрать пробел после "Host:" и переместить его в конец значения "User-Agent:" для сохранения длины пакета
|
||
--hostspell=HoST ; точное написание заголовка Host (можно "HOST" или "HoSt"). автоматом включает --hostcase
|
||
--domcase ; домен после Host: сделать таким : TeSt.cOm
|
||
--dpi-desync=[<mode0>,]<mode>[,<mode2] ; атака по десинхронизации DPI. mode : synack syndata fake fakeknown rst rstack hopbyhop destopt ipfrag1 multisplit multidisorder fakedsplit fakeddisorder ipfrag2 udplen tamper
|
||
--dpi-desync-fwmark=<int|0xHEX> ; бит fwmark для пометки десинхронизирующих пакетов, чтобы они повторно не падали в очередь. default = 0x40000000
|
||
--dpi-desync-ttl=<int> ; установить ttl для десинхронизирующих пакетов
|
||
--dpi-desync-ttl6=<int> ; установить ipv6 hop limit для десинхронизирующих пакетов. если не указано, используется значение ttl
|
||
--dpi-desync-autottl=[<delta>[:<min>[-<max>]]] ; режим auto ttl для ipv4 и ipv6. по умолчанию: 1:3-20. delta=0 отключает функцию.
|
||
--dpi-desync-autottl6=[<delta>[:<min>[-<max>]]] ; переопределение предыдущего параметра для ipv6
|
||
--dpi-desync-fooling=<fooling> ; дополнительные методики как сделать, чтобы фейковый пакет не дошел до сервера. none md5sig badseq badsum datanoack hopbyhop hopbyhop2
|
||
--dpi-desync-repeats=<N> ; посылать каждый генерируемый в nfqws пакет N раз (не влияет на остальные пакеты)
|
||
--dpi-desync-skip-nosni=0|1 ; 1(default)=не применять dpi desync для запросов без hostname в SNI, в частности для ESNI
|
||
--dpi-desync-split-pos=N|-N|marker+N|marker-N ; список через запятую маркеров для tcp сегментации в режимах split и disorder
|
||
--dpi-desync-split-seqovl=N|-N|marker+N|marker-N ; единичный маркер, определяющий величину перекрытия sequence в режимах split и disorder. для split поддерживается только положительное число.
|
||
--dpi-desync-split-seqovl-pattern=<filename>|0xHEX ; чем заполнять фейковую часть overlap
|
||
--dpi-desync-badseq-increment=<int|0xHEX> ; инкремент sequence number для badseq. по умолчанию -10000
|
||
--dpi-desync-badack-increment=<int|0xHEX> ; инкремент ack sequence number для badseq. по умолчанию -66000
|
||
--dpi-desync-any-protocol=0|1 ; 0(default)=работать только по http request и tls clienthello 1=по всем непустым пакетам данных
|
||
--dpi-desync-fake-http=<filename>|0xHEX ; файл, содержащий фейковый http запрос для dpi-desync=fake, на замену стандартному www.iana.org
|
||
--dpi-desync-fake-tls=<filename>|0xHEX ; файл, содержащий фейковый tls clienthello для dpi-desync=fake, на замену стандартному
|
||
--dpi-desync-fake-unknown=<filename>|0xHEX ; файл, содержащий фейковый пейлоад неизвестного протокола для dpi-desync=fake, на замену стандартным нулям 256 байт
|
||
--dpi-desync-fake-syndata=<filename>|0xHEX ; файл, содержащий фейковый пейлоад пакета SYN для режима десинхронизации syndata
|
||
--dpi-desync-fake-quic=<filename>|0xHEX ; файл, содержащий фейковый QUIC Initial
|
||
--dpi-desync-fake-dht=<filename>|0xHEX ; файл, содержащий фейковый пейлоад DHT протокола для dpi-desync=fake, на замену стандартным нулям 64 байт
|
||
--dpi-desync-fake-unknown-udp=<filename>|0xHEX ; файл, содержащий фейковый пейлоад неизвестного udp протокола для dpi-desync=fake, на замену стандартным нулям 64 байт
|
||
--dpi-desync-udplen-increment=<int> ; насколько увеличивать длину udp пейлоада в режиме udplen
|
||
--dpi-desync-udplen-pattern=<filename>|0xHEX ; чем добивать udp пакет в режиме udplen. по умолчанию - нули
|
||
--dpi-desync-start=[n|d|s]N ; применять dpi desync только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру больше или равно N
|
||
--dpi-desync-cutoff=[n|d|s]N ; применять dpi desync только в исходящих пакетах (n), пакетах данных (d), относительных sequence (s) по номеру меньше N
|
||
--hostlist=<filename> ; действовать только над доменами, входящими в список из filename. поддомены автоматически учитываются.
|
||
; в файле должен быть хост на каждой строке.
|
||
; список читается при старте и хранится в памяти в виде иерархической структуры для быстрого поиска.
|
||
; при изменении времени модификации файла он перечитывается автоматически по необходимости
|
||
; список может быть запакован в gzip. формат автоматически распознается и разжимается
|
||
; списков может быть множество. пустой общий лист = его отсутствие
|
||
; хосты извлекаются из Host: хедера обычных http запросов и из SNI в TLS ClientHello.
|
||
--hostlist-exclude=<filename> ; не применять дурение к доменам из листа. может быть множество листов. схема аналогична include листам.
|
||
--hostlist-auto=<filename> ; обнаруживать автоматически блокировки и заполнять автоматический hostlist (требует перенаправления входящего трафика)
|
||
--hostlist-auto-fail-threshold=<int> ; сколько раз нужно обнаружить ситуацию, похожую на блокировку, чтобы добавить хост в лист (по умолчанию: 3)
|
||
--hostlist-auto-fail-time=<int> ; все эти ситуации должны быть в пределах указанного количества секунд (по умолчанию: 60)
|
||
--hostlist-auto-retrans-threshold=<int> ; сколько ретрансмиссий запроса считать блокировкой (по умолчанию: 3)
|
||
--hostlist-auto-debug=<logfile> ; лог положительных решений по autohostlist. позволяет разобраться почему там появляются хосты.
|
||
--new ; начало новой стратегии (новый профиль)
|
||
--filter-l3=ipv4|ipv6 ; фильтр версии ip для текущей стратегии
|
||
--filter-tcp=[~]port1[-port2]|* ; фильтр портов tcp для текущей стратегии. ~ означает инверсию. установка фильтра tcp и неустановка фильтра udp запрещает udp. поддерживается список через запятую.
|
||
--filter-udp=[~]port1[-port2]|* ; фильтр портов udp для текущей стратегии. ~ означает инверсию. установка фильтра udp и неустановка фильтра tcp запрещает tcp. поддерживается список через запятую.
|
||
--filter-l7=[http|tls|quic|wireguard|dht|unknown] ; фильтр протокола L6-L7. поддерживается несколько значений через запятую.
|
||
--ipset=<filename> ; включающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая.
|
||
--ipset-exclude=<filename> ; исключающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая.
|
||
```
|
||
|
||
`--debug` позволяет выводить подробный лог действий на консоль, в syslog или в файл. Может быть важен порядок следования
|
||
опций. `--debug` лучше всего указывать в самом начале. Опции анализируются последовательно. Если ошибка будет при
|
||
проверке опции, а до анализа `--debug` еще дело не дошло, то сообщения не будут выведены в файл или syslog. При
|
||
логировании в файл процесс не держит файл открытым. Ради каждой записи файл открывается и потом закрывается. Так что
|
||
файл можно удалить в любой момент, и он будет создан заново при первом же сообщении в лог. Но имейте в виду, что если вы
|
||
запускаете процесс под root, то будет сменен UID на не-root. В начале на лог файл меняется owner, иначе запись будет
|
||
невозможна. Если вы потом удалите файл, и у процесса не будет прав на создание файла в его директории, лог больше не
|
||
будет вестись. Вместо удаления лучше использовать truncate. В шелле это можно сделать через команду ": >filename"
|
||
|
||
### АТАКА ДЕСИНХРОНИЗАЦИИ DPI
|
||
|
||
Суть ее в следующем. Берется оригинальный запрос, модифицируется, добавляется поддельная информация (фейки)
|
||
таким образом, чтобы ОС сервера передала серверному процессу оригинальный запрос в неизменном виде, а DPI увидел другое.
|
||
То, что он блокировать не станет. Сервер видит одно, DPI - другое. DPI не понимает, что передается запрещенный запрос и не блокирует его.
|
||
|
||
Есть арсенал возможностей, чтобы достичь такого результата.
|
||
Это может быть передача фейк пакетов, чтобы они дошли до DPI, но не дошли до сервера. Может использоваться фрагментация на уровне TCP (сегментация) или на уровне IP.
|
||
Есть атаки, основанные на игре с tcp sequence numbers или с перепутыванием порядка следования tcp сегментов.
|
||
Методы могут сочетаться в различных вариантах.
|
||
|
||
### ФЕЙКИ
|
||
|
||
Фейки - это отдельные сгенерированные nfqws пакеты, несущие ложную информацию для DPI.
|
||
Они либо не должны дойти до сервера, либо могут дойти, но должны быть им отброшены.
|
||
Иначе получается слом tcp соединения или нарушение целостности передаваемого потока, что гарантированно приводит к поломке ресурса.
|
||
Есть ряд методов для решения этой задачи.
|
||
|
||
* `md5sig` добавляет TCP опцию **MD5 signature**. Работает не на всех серверах. Пакеты с md5 обычно отбрасывают только linux.
|
||
* `badsum` портит контрольную сумму TCP. Не сработает, если ваше устройство за NAT, который не пропускает пакеты с инвалидной суммой. Наиболее
|
||
распространенная настройка NAT роутера в Linux их не пропускает. На Linux построено большинство домашних роутеров.
|
||
Непропускание обеспечивается так : настройка ядра sysctl по умолчанию
|
||
`net.netfilter.nf_conntrack_checksum=1` заставляет conntrack проверять tcp и udp чексуммы входящих пакетов и
|
||
выставлять state INVALID для пакетов с инвалидной суммой. Обычно в правилах iptables вставляется правило для дропа
|
||
пакетов с состоянием INVALID в цепочке FORWARD. Совместное сочетание этих факторов приводит к непрохождению badsum
|
||
через такой роутер. В openwrt из коробки `net.netfilter.nf_conntrack_checksum=0`, в других роутерах часто нет, и не
|
||
всегда это можно изменить. Чтобы nfqws мог работать через роутер, нужно на нем выставить указанное значение sysctl в 0.
|
||
nfqws на самом роутере будет работать и без этой настройки, потому что чексумма локально созданных пакетов не
|
||
проверяется никогда. Если роутер за другим NAT, например провайдерским, и он не пропускает invalid packets вы ничего
|
||
не сможете с этим сделать. Но обычно провайдеры все же пропускают badsum. На некоторых адаптерах/свитчах/драйверах
|
||
принудительно включен rx-checksum offload, badsum пакеты отсекаются еще до получения в ОС. В этом случае если что-то и
|
||
можно сделать, то только модифицировать драйвер, что представляется задачей крайне нетривиальной. Установлено, что так
|
||
себя ведут некоторые роутеры на базе mediatek. badsum пакеты уходят с клиентской ОС, но роутером не видятся в br-lan
|
||
через tcpdump. При этом если nfqws выполняется на самом роутере, обход может работать. badsum нормально уходят с
|
||
внешнего интерфейса.
|
||
* `badseq` увеличивает TCP sequence number на определенное значение, выводя его тем самым из TCP window.
|
||
Такие пакеты будут наверняка отброшены принимающим узлом, но так же и DPI, если он ориентируется на sequence
|
||
numbers. По умолчанию смещение seq выбирается -10000. Практика показала, что некоторые DPI не пропускают seq вне
|
||
определенного окна. Однако, такое небольшое смещение может вызвать проблемы при существенной потоковой передаче и
|
||
потере пакетов. Если вы используете `--dpi-desync-any-protocol`, может понадобится установить badseq increment
|
||
0x80000000. Это обеспечит надежную гарантию, что поддельный пакет не вклинится в tcp window на сервере. Так же было
|
||
замечено, что badseq ломает логику некоторых DPI при анализе http, вызывая зависание соединения. Причем на тех же DPI
|
||
TLS с badseq работает нормально.
|
||
* `TTL` казалось бы - лучший вариант, но он требует индивидуальной настройки под каждого провайдера. Если DPI находится
|
||
дальше локальных сайтов провайдера, то вы можете отрезать себе доступ к ним. Ситуация усугубляется наличием ТСПУ на
|
||
магистралах, что вынуждает делать TTL достаточно высоким, увеличивая риск пробоя фейка до сервера. Необходим ip
|
||
exclude list, заполняемый вручную. Вместе с ttl можно применять md5sig. Это ничего не испортит, зато дает неплохой
|
||
шанс работы сайтов, до которых "плохой" пакет дойдет по TTL. Если не удается найти автоматическое решение,
|
||
воспользуйтесь файлом `zapret-hosts-user-exclude.txt`. Некоторые стоковые прошивки роутеров фиксируют исходящий TTL,
|
||
без отключения этой опции через них работать не будет. КАКИМ СТОИТ ВЫБИРАТЬ TTL : найдите минимальное значение, при
|
||
котором обход еще работает. Это и будет номер хопа вашего DPI.
|
||
* `hopbyhop` относится только к ipv6. Добавляется ipv6 extenstion header `hop-by-hop options`. В варианте `hopbyhop2`
|
||
добавляются 2 хедера, что является нарушением стандарта и гарантированно отбрасывается стеком протоколов во всех ОС.
|
||
Один хедер hop-by-hop принимается всеми ОС, однако на некоторых каналах/провайдерах такие пакеты могут фильтроваться и
|
||
не доходить. Расчет идет на то, что DPI проанализирует пакет с hop-by-hop, но он либо не дойдет до адресата всилу
|
||
фильтров провайдера, либо будет отброшен сервером, потому что хедера два.
|
||
* `datanoack` высылает фейки со снятым tcp флагом ACK. Сервера такое не принимают, а DPI может принять. Эта техника
|
||
может ломать NAT и не всегда работает с iptables, если используется masquerade, даже с локальной системы (почти всегда
|
||
на роутерах ipv4). На системах c iptables без masquerade и на nftables работает без ограничений. Экспериментально
|
||
выяснено, что многие провайдерские NAT не отбрасывают эти пакеты, потому работает даже с внутренним провайдерским IP.
|
||
Но linux NAT оно не пройдет, так что за домашним роутером эта техника скорее всего не сработает, но может сработать с него.
|
||
Может сработать и через роутер, если подключение по проводу, и на роутере включено аппаратное ускорение.
|
||
* `autottl`. Суть режима в автоматическом определении TTL, чтобы он почти наверняка прошел DPI и немного не дошел до
|
||
сервера. Берутся базовые значения TTL 64,128,255, смотрится входящий пакет
|
||
(да, требуется направить первый входящий пакет на nfqws !). Вычисляется длина пути, отнимается `delta` (1 по
|
||
умолчанию). Если TTL вне диапазона (min,max - 3,20 по умолчанию), то берутся значения min,max, чтобы вписаться в
|
||
диапазон. Если при этом полученный TTL больше длины пути, то автоматизм не сработал и берутся фиксированные значения
|
||
TTL для атаки. Техника позволяет решить вопрос, когда вся сеть перегорожена шлагбаумами (DPI, ТСПУ) везде где только
|
||
можно, включая магистралов. Но потенциально может давать сбои. Например, при асимметрии входящего и исходящего канала
|
||
до конкретного сервера. На каких-то провайдерах эта техника будет работать неплохо, на других доставит больше проблем,
|
||
чем пользы. Где-то может потребоваться тюнинг параметров. Лучше использовать с дополнительным ограничителем.
|
||
|
||
Режимы дурения могут сочетаться в любых комбинациях. `--dpi-desync-fooling` берет множество значений через запятую.
|
||
|
||
### TCP СЕГМЕНТАЦИЯ
|
||
|
||
* `multisplit`. нарезаем запрос на указанных в `--dpi-desync-split-pos` позициях.
|
||
* `multidisorder`. нарезаем запрос на указанных в `--dpi-desync-split-pos` позициях и отправляем в обратном порядке.
|
||
* `fakedsplit`. нарезаем запрос на 2 части, обрамляя его фейками : фейк 1-й части, 1 часть, фейк 1-й части, 2 часть
|
||
* `fakeddisorder`. нарезаем запрос на 2 части, обрамляя его фейками : 2 часть, фейк 1-й части, 1 часть, фейк 1 части.
|
||
|
||
Для определения позиций нарезки используются маркеры.
|
||
|
||
* **Абсолютный положительный маркер** - числовое смещение внутри пакета или группы пакетов от начала.
|
||
* **Абсолютный отрицательный маркер** - числовое смещение внутри пакета или группы пакетов от следующего за концом байта. -1 указывает на последний байт.
|
||
* **Относительный маркер** - положительное или отрицательное смещение относительно логической позиции внутри пакета или группы пакетов.
|
||
|
||
Относительные позиции :
|
||
|
||
* **method** - начало метода HTTP ('GET', 'POST', 'HEAD', ...). Метод обычно всегда находится на позиции 0, но поддерживается и нахождение метода после дурение методом `--methodeol` от tpws. Тогда позиция может стать 1 или 2.
|
||
* **host** - начало имени хоста в известном протоколе (http, TLS)
|
||
* **endhost** - конец имени хоста
|
||
* **sld** - начало домена 2 уровня в имени хоста
|
||
* **endsld** - конец домена 2 уровня в имени хоста
|
||
* **midsld** - середина домена 2 уровня в имени хоста
|
||
* **sniext** - начало поля данных SNI extension в TLS. Любой extension состоит из 2-байтовых полей type и length, за ними идет поле данных.
|
||
|
||
Пример списка маркеров : `100,midsld,sniext+1,endhost-2,-10`.
|
||
|
||
При разбиении пакета первым делом происходит ресолвинг маркеров - нахождение всех указанных относительных позиций и применение смещений.
|
||
Если относительная позиция отсутствует в текущем протоколе, такие позиции не применяются и отбрасываются.
|
||
Дальше происходит нормализация позиций относительно смещения текущего пакета в группе пакетов (многопакетные запросы TLS с kyber, например).
|
||
Выкидываются все позиции, выходящие за пределы текущего пакета. Оставшиеся сортируются в порядке возрастания и удаляются дубли.
|
||
В вариантах `multisplit` и `multidisorder` если не осталось ни одной позиции, разбиение не происходит.
|
||
|
||
Варианты `fakedsplit` и `fakeddisorder` применяют только одну позицию сплита. Ее поиск среди списка `--dpi-desync-split-pos` осуществляется особым образом.
|
||
Сначала сверяются все относительные маркеры. Если среди них найден подходящий, применяется он. В противном случае сверяются все абсолютные маркеры.
|
||
Если и среди них ничего не найдено, применяется позиция 1.
|
||
|
||
Например, можно написать `--dpi-desync-split-pos=method+2,midsld,5`. Если протокол http, разбиение будет на позиции `method+2`.
|
||
Если протокол TLS - на позиции `midsld`. Если протокол неизвестен и включено `--dpi-desync-any-protocol`, разбиение будет на позиции 5.
|
||
Чтобы все было однозначнее, можно использовать разные профили для разных протоколов и указывать только одну позицию, которая точно есть в этом протоколе.
|
||
|
||
### ПЕРЕКРЫТИЕ SEQUENCE NUMBERS
|
||
|
||
`seqovl` добавляет в начало одного из TCP сегментов `seqovl` байт со смещенным в минус sequence number на величину `seqovl`.
|
||
Для `split` - в начало первого сегмента, для `disorder` - в начало предпоследнего отсылаемого сегмента (второго в оригинальном порядке следования).
|
||
|
||
В случае `split` расчет идет на то, что предыдущий отсыл, если он был, уже попал в сокет серверного приложения, поэтому новая пришедшая часть лишь частично находится в
|
||
пределах текущего окна (in-window). Спереди фейковая часть отбрасывается, а оставшаяся часть содержит оригинал и
|
||
начинается с начала window, поэтому попадает в сокет. Серверное приложение получает все, что реально отсылает клиент,
|
||
отбрасывая фейковую out-of-window часть. Но DPI не может этого понять, поэтому у него происходит sequence десинхронизация.
|
||
Обязательно, чтобы первый сегмент вместе с `seqovl` не превысили длину MTU. Эта ситуация распознается автоматически в Linux, и `seqovl` отменяется.
|
||
В остальных системах ситуация не распознается, и это приведет к поломке соединения. Поэтому выбирайте первую позицию сплита и `seqovl` таким образом, чтобы MTU не был превышен в любом случае.
|
||
Иначе дурение может не работать или работать хаотично.
|
||
|
||
Для `disorder` overlap идет на предпоследнюю отсылаемую часть пакета.
|
||
Для простоты будем считать, что разбиение идет на 2 части, шлются они в порядке "2 1" при оригинальном порядке "1 2".
|
||
Обязательно, чтобы `seqovl` был меньше позиции первого сплита, иначе все отосланное будет передано в сокет сразу же, включая фейк, ломая протокол прикладного уровня.
|
||
Такая ситуация легко обнаруживается программой, и `seqovl` отменяется. Увеличение размера пакета невозможно в принципе.
|
||
При соблюдении условия 2-я часть пакета является полностью in-window, поэтому серверная ОС принимает ее целиком, включая фейк.
|
||
Но поскольку начальная часть данных из 1 пакета еще не принята, то фейк и реальные данные остаются в памяти ядра, не отправляясь в серверное приложение.
|
||
Как только приходит 1-я часть пакета, она переписывает фейковую часть в памяти ядра.
|
||
Ядро получает данные из 1 и 2 части, поэтому далее идет отправка в сокет приложения.
|
||
Таково поведение всех unix ОС, кроме solaris - оставлять последние принятые данные.
|
||
Windows оставляет старые данные, поэтому disorder с seqovl будет приводить к зависаниям соединения
|
||
при работе с Windows серверами. Solaris практически мертв, windows серверов очень немного.
|
||
Можно использовать листы при необходимости.
|
||
Метод позволяет обойтись без fooling и TTL. Фейки перемешаны с реальным данными.
|
||
`fakedsplit/fakeddisorder` по-прежнему добавляют дополнительные отдельные фейки.
|
||
|
||
`seqovl` в варианте `split` может быть только абсолютным положительным значением, поскольку применяется только в первому пакету.
|
||
В варианте `disorder` допустимо применение всех вариантов маркеров.
|
||
Они автоматически нормализуются к текущему пакету в серии. Можно сплитать на `midsld` и делать seqovl на `midsld-1`.
|
||
|
||
### СПЕЦИФИЧЕСКИЕ РЕЖИМЫ IPV6
|
||
|
||
Режимы десинхронизации `hopbyhop`, `destopt` и `ipfrag1` (не путать с fooling !) относятся только к `ipv6` и заключается
|
||
в добавлении хедера `hop-by-hop options`, `destination options` или `fragment` во все пакеты, попадающие под десинхронизацию.
|
||
Здесь надо обязательно понимать, что добавление хедера увеличивает размер пакета, потому не может быть применено
|
||
к пакетам максимального размера. Это имеет место при передаче больших сообщений.
|
||
В случае невозможности отослать пакет дурение будет отменено, пакет будет выслан в оригинале.
|
||
Расчет идет на то, что DPI увидит 0 в поле next header основного заголовка `ipv6` и не будет скакать по
|
||
extension хедерам в поисках транспортного хедера. Таким образом не поймет, что это tcp или udp, и пропустит пакет
|
||
без анализа. Возможно, какие-то DPI на это купятся.
|
||
Может сочетаться с любыми режимами 2-й фазы, кроме варианта `ipfrag1+ipfrag2`.
|
||
Например, `hopbyhop,multisplit` означает разбить tcp пакет на несколько сегментов, в каждый из них добавить hop-by-hop.
|
||
При `hopbyhop,ipfrag2` последовательность хедеров будет : `ipv6,hop-by-hop`,`fragment`,`tcp/udp`.
|
||
Режим `ipfrag1` может срабатывать не всегда без специальной подготовки. См. раздел `IP фрагментация`.
|
||
|
||
### КОМБИНИРОВАНИЕ МЕТОДОВ ДЕСИНХРОНИЗАЦИИ
|
||
|
||
В параметре dpi-desync можно указать до 3 режимов через запятую.
|
||
|
||
* 0 фаза - предполагает работу на этапе установления соединения : `synack`, `syndata` `--wsize`, `--wssize`. На эту фазу не действуют фильтры по [hostlist](((#множественные-стратегии))).
|
||
* 1 фаза - отсылка чего-либо до оригинального пакета данных : `fake`, `rst`, `rstack`.
|
||
* 2 фаза - отсылка в модифицированном виде оригинального пакета данных (например, `fakedsplit` или `ipfrag2`).
|
||
|
||
Режимы требуют указания в порядке возрастания номеров фаз.
|
||
|
||
### РЕАКЦИЯ DPI НА ОТВЕТ СЕРВЕРА
|
||
|
||
Есть DPI, которые анализируют ответы от сервера, в частности сертификат из ServerHello, где прописаны домены.
|
||
Подтверждением доставки ClientHello является ACK пакет от сервера с номером ACK sequence, соответствующим длине ClientHello+1.
|
||
В варианте disorder обычно приходит сперва частичное подтверждение (SACK), потом полный ACK.
|
||
Если вместо ACK или SACK идет RST пакет с минимальной задержкой, то DPI вас отсекает еще на этапе вашего запроса.
|
||
Если RST идет после полного ACK спустя задержку, равную примерно пингу до сервера,
|
||
тогда вероятно DPI реагирует на ответ сервера.
|
||
DPI может отстать от потока, если ClientHello его удовлетворил и не проверять ServerHello.
|
||
Тогда вам повезло. Вариант fake может сработать.
|
||
Если же он не отстает и упорно проверяет ServerHello, то можно попробовать заставить сервер высылать ServerHello частями
|
||
через параметр --wssize (см. conntrack).
|
||
Если и это не помогает, то сделать с этим что-либо вряд ли возможно без помощи со стороны сервера.
|
||
Лучшее решение - включить на сервере поддержку TLS 1.3. В нем сертификат сервера передается в зашифрованном виде.
|
||
Это рекомендация ко всем админам блокируемых сайтов. Включайте TLS 1.3. Так вы дадите больше возможностей преодолеть DPI.
|
||
|
||
### РЕЖИМ SYNACK
|
||
|
||
В документации по geneva это называется "TCB turnaround". Попытка ввести DPI в заблуждение относительно
|
||
ролей клиента и сервера.
|
||
!!! Поскольку режим нарушает работу NAT, техника может сработать только если между атакующим устройством
|
||
и DPI нет NAT. Атака не сработает через NAT роутер, но может сработать с него.
|
||
Для реализации атаки в linux обязательно требуется отключить стандартное правило firewall,
|
||
дропающее инвалидные пакеты в цепочке OUTPUT. Например : `-A OUTPUT -m state --state INVALID -j DROP`
|
||
В openwrt можно отключить drop INVALID в OUTPUT и FORWARD через опцию в /etc/config/firewall:
|
||
|
||
```
|
||
config zone
|
||
option name 'wan'
|
||
.........
|
||
option masq_allow_invalid '1'
|
||
```
|
||
|
||
К сожалению, отключить только в OUTPUT таким образом нельзя. Но можно сделать иначе. Вписать в `/etc/firewall.user`:
|
||
|
||
```
|
||
iptables -D zone_wan_output -m comment --comment '!fw3' -j zone_wan_dest_ACCEPT
|
||
ip6tables -D zone_wan_output -m comment --comment '!fw3' -j zone_wan_dest_ACCEPT
|
||
```
|
||
|
||
Лучше делать так, потому что отсутствие дропа INVALID в FORWARD может привести к нежелательным утечкам пакетов из LAN.
|
||
Если не принять эти меры, отсылка SYN,ACK сегмента вызовет ошибку и операция будет прервана.
|
||
Остальные режимы тоже не сработают. Если поймете, что вам synack не нужен, обязательно верните правило дропа INVALID.
|
||
|
||
### РЕЖИМ SYNDATA
|
||
|
||
Тут все просто. Добавляются данные в пакет SYN. Все ОС их игнорируют, если не используется TCP fast open (TFO),
|
||
а DPI может воспринять, не разобравшись есть там TFO или нет.
|
||
Оригинальные соединения с TFO не трогаются, поскольку это их точно сломает.
|
||
Без уточняющего параметра добавляются 16 нулевых байтов.
|
||
|
||
### ВИРТУАЛЬНЫЕ МАШИНЫ
|
||
|
||
Изнутри VM от virtualbox и vmware в режиме NAT не работают многие техники пакетной магии nfqws.
|
||
Принудительно заменяется ttl, не проходят фейк пакеты. Необходимо настроить сеть в режиме bridge.
|
||
|
||
### CONNTRACK
|
||
|
||
nfqws оснащен ограниченной реализацией слежения за состоянием tcp соединений (conntrack).
|
||
Он включается для реализации некоторых методов противодействия DPI.
|
||
conntrack способен следить за фазой соединения : SYN,ESTABLISHED,FIN, количеством пакетов в каждую сторону,
|
||
sequence numbers. conntrack способен "кормиться" пакетами в обе или только в одну сторону.
|
||
Соединение попадает в таблицу при обнаружении пакетов с выставленными флагами SYN или SYN,ACK.
|
||
Поэтому если необходим conntrack, в правилах перенаправления iptables соединение должно идти на nfqws с самого первого
|
||
пакета, хотя затем может обрываться по фильтру connbytes.
|
||
Для UDP инициатором попадания в таблицу является первый UDP пакет. Он же и определяет направление потока.
|
||
Считается, что первый UDP пакет исходит от клиента к серверу. Далее все пакеты с совпадающими
|
||
`src_ip,src_port,dst_ip,dst_port` считаются принадлежащими этому потоку до истечения времени неактивности.
|
||
conntrack - простенький, он не писался с учетом всевозможных атак на соединение, он не проверяет
|
||
пакеты на валидность sequence numbers или чексумму. Его задача - лишь обслуживание нужд nfqws, он обычно
|
||
кормится только исходящим трафиком, потому нечувствителен к подменам со стороны внешней сети.
|
||
Соединение удаляется из таблицы, как только отпадает нужда в слежении за ним или по таймауту неактивности.
|
||
Существуют отдельные таймауты на каждую фазу соединения. Они могут быть изменены параметром `--ctrack-timeouts`.
|
||
|
||
`--wssize` позволяет изменить с клиента размер tcp window для сервера, чтобы он послал следующие ответы разбитыми на части.
|
||
Чтобы это подействовало на все серверные ОС, необходимо менять window size в каждом исходящем с клиента пакете до отсылки сообщения,
|
||
ответ на который должен быть разбит (например, TLS ClientHello). Именно поэтому и необходим conntrack, чтобы
|
||
знать когда надо остановиться. Если не остановиться и все время устанавливать низкий wssize, скорость упадет катастрофически.
|
||
В linux это может быть купировано через connbytes, но в BSD системах такой возможности нет.
|
||
В случае http(s) останавливаемся сразу после отсылки первого http запроса или TLS ClientHello.
|
||
Если вы имеете дело с не http(s), то вам потребуется параметр `--wssize-cutoff`. Он устанавливает предел, с которого действие
|
||
wssize прекращается. Префикс d перед номером означает учитывать только пакеты с data payload, префикс s - relative sequence number,
|
||
проще говоря количество переданных клиентом байтов + 1.
|
||
Если проскочит пакет с http request или TLS ClientHello, действие wssize прекращается сразу же, не дожидаясь wssize-cutoff.
|
||
Если ваш протокол склонен к долгому бездействию, следует увеличить таймаут фазы ESTABLISHED через параметр `--ctrack-timeouts`.
|
||
Таймаут по умолчанию низкий - всего 5 минут.
|
||
Не забывайте, что nfqws кормится приходящими на него пакетами. Если вы ограничили поступление пакетов через connbytes,
|
||
то в таблице могут остаться повисшие соединения в фазе ESTABLISHED, которые отвалятся только по таймауту.
|
||
Для диагностики состояния conntrack пошлите сигнал SIGUSR1 процессу nfqws : `killall -SIGUSR1 nfqws`.
|
||
Текущая таблица будет выведена nfqws в stdout.
|
||
|
||
Обычно в SYN пакете клиент отсылает кроме window size еще и TCP extension `scaling factor`.
|
||
**scaling factor** представляет из себя степень двойки, на которую умножается window size : 0=>1, 1=>2, 2=>4, ..., 8=>256, ...
|
||
В параметре wssize scaling factor указывается через двоеточие.
|
||
Scaling factor может только снижаться, увеличение заблокировано, чтобы не допустить превышение размера окна со стороны сервера.
|
||
Для принуждения сервера к фрагментации ServerHello, чтобы избежать просекание имени сервера из сертификата сервера на DPI,
|
||
лучше всего использовать `--wssize=1:6`. Основное правило - делать `scale_factor` как можно больше, чтобы после восстановления
|
||
window size итоговый размер окна стал максимально возможным. Если вы сделаете 64:0, будет очень медленно.
|
||
С другой стороны нельзя допустить, чтобы ответ сервера стал достаточно большим, чтобы DPI нашел там искомое.
|
||
|
||
`--wssize` не работает в профилях с хостлистами, поскольку он действует с самого начала соединения, когда еще нельзя
|
||
принять решение о попадании в лист. Однако, профиль с auto hostlist может содержать --wssize.
|
||
`--wssize` может замедлять скорость и/или увеличивать время ответа сайтов, поэтому если есть другие работающие способы
|
||
обхода DPI, лучше применять их.
|
||
|
||
`--dpi-desync-cutoff` позволяет задать предел, при достижении которого прекращается применение dpi-desync.
|
||
Доступны префиксы n,d,s по аналогии с `--wssize-cutoff`.
|
||
Полезно совместно с `--dpi-desync-any-protocol=1`.
|
||
На склонных к бездействию соединениях следует изменить таймауты conntrack.
|
||
Если соединение выпало из conntrack и задана опция `--dpi-desync-cutoff`, `dpi desync` применяться не будет.
|
||
|
||
### РЕАССЕМБЛИНГ
|
||
|
||
nfqws поддерживает реассемблинг некоторых видов запросов.
|
||
На текущий момент это TLS и QUIC ClientHello. Они бывает длинными, если в chrome включить пост-квантовую
|
||
криптографию tls-kyber, и занимают как правило 2 или 3 пакета. kyber включен по умолчанию, начиная с chromium 124.
|
||
chrome рандомизирует фингерпринт TLS. SNI может оказаться как в начале, так и в конце, то есть
|
||
попасть любой пакет. stateful DPI обычно реассемблирует запрос целиком, и только потом
|
||
принимает решение о блокировке.
|
||
В случае получения TLS или QUIC пакета с частичным ClientHello начинается процесс сборки, а пакеты
|
||
задерживаются и не отсылаются до ее окончания. По окончании сборки пакеты проходит через десинхронизацию
|
||
на основании полностью собранного ClientHello.
|
||
При любой ошибке в процессе сборки задержанные пакеты немедленно отсылаются в сеть, а десинхронизация отменяется.
|
||
|
||
Есть специальная поддержка всех вариантов tcp сплита для многосегментного TLS.
|
||
Если указать позицию сплита больше длины первого пакета, то разбивка происходит не обязательно первого пакета, а того,
|
||
на который пришлась итоговая позиция.
|
||
Если, допустим, клиент послал TLS ClientHello длиной 2000, SNI начинается с 1700,
|
||
и заданы опции `fake,multisplit`, то перед первым пакетом идет fake, затем первый пакет в оригинале,
|
||
а последний пакет разбивается на 2 сегмента. В итоге имеем фейк в начале и 3 реальных сегмента.
|
||
|
||
### ПОДДЕРЖКА UDP
|
||
|
||
Атаки на udp более ограничены в возможностях. udp нельзя фрагментировать иначе, чем на уровне ip.
|
||
Для UDP действуют только режимы десинхронизации `fake`, `hopbyhop`, `destopt`, `ipfrag1`, `ipfrag2`, `udplen`, `tamper`.
|
||
Возможно сочетание `fake`, `hopbyhop`, `destopt` с `ipfrag2`, `fake`, `fakeknown` с udplen и tamper.
|
||
`udplen` увеличивает размер udp пакета на указанное в `--dpi-desync-udplen-increment` количество байтов.
|
||
Паддинг заполняется нулями по умолчанию, но можно задать свой паттерн.
|
||
Предназначено для обмана DPI, ориентирующегося на размеры пакетов.
|
||
Может сработать, если пользовательский протокол не привязан жестко к размеру udp пейлоада.
|
||
Режим tamper означает модификацию пакетов известных протоколов особенным для протокола образом.
|
||
На текущий момент работает только с DHT.
|
||
Поддерживается определение пакетов QUIC Initial с расшифровкой содержимого и имени хоста, то есть параметр
|
||
`--hostlist` будет работать.
|
||
Определяются пакеты wireguard handshake initiation и DHT (начинается с 'd1', кончается 'e').
|
||
Для десинхронизации других протоколов обязательно указывать `--dpi-desync-any-protocol`.
|
||
Реализован conntrack для udp. Можно пользоваться --dpi-desync-cutoff. Таймаут conntrack для udp
|
||
можно изменить 4-м параметром в `--ctrack-timeouts`.
|
||
Атака fake полезна только для stateful DPI, она бесполезна для анализа на уровне отдельных пакетов.
|
||
По умолчанию fake наполнение - 64 нуля. Можно указать файл в `--dpi-desync-fake-unknown-udp`.
|
||
|
||
### IP ФРАГМЕНТАЦИЯ
|
||
|
||
Современная сеть практически не пропускает фрагментированные tcp на уровне ip.
|
||
На udp с этим дело получше, поскольку некоторые udp протоколы могут опираться на этот механизм (IKE старых версий).
|
||
Однако, кое-где бывает, что режут и фрагментированный udp.
|
||
Роутеры на базе linux могут самопроизвольно собирать или перефрагментировать пакеты.
|
||
Позиция фрагментации задается отдельно для tcp и udp. По умолчанию 24 и 8 соответственно, должна быть кратна 8.
|
||
Смещение считается с транспортного заголовка.
|
||
|
||
Существует ряд моментов вокруг работы с фрагментами на Linux, без понимания которых может ничего не получиться.
|
||
|
||
ipv4 : Linux дает отсылать ipv4 фрагменты, но стандартные настройки iptables в цепочке OUTPUT могут вызывать ошибки отправки.
|
||
|
||
ipv6 : Нет способа для приложения гарантированно отослать фрагменты без дефрагментации в conntrack.
|
||
На разных системах получается по-разному. Где-то нормально уходят, где-то пакеты дефрагментируются.
|
||
Для ядер <4.16 похоже, что нет иного способа решить эту проблему, кроме как выгрузить модуль `nf_conntrack`,
|
||
который подтягивает зависимость `nf_defrag_ipv6`. Он то как раз и выполняет дефрагментацию.
|
||
Для ядер 4.16+ ситуация чуть лучше. Из дефрагментации исключаются пакеты в состоянии NOTRACK.
|
||
Чтобы не загромождать описание, смотрите пример решения этой проблемы в `blockcheck.sh`.
|
||
|
||
Иногда требуется подгружать модуль `ip6table_raw` с параметром `raw_before_defrag=1`.
|
||
В openwrt параметры модулей указываются через пробел после их названий в файлах `/etc/modules.d`.
|
||
В традиционных системах посмотрите используется ли `iptables-legacy` или `iptables-nft`. Если legacy, то нужно создать файл
|
||
`/etc/modprobe.d/ip6table_raw.conf` с содержимым :
|
||
```
|
||
options ip6table_raw raw_before_defrag=1
|
||
```
|
||
В некоторых традиционных дистрибутивах можно изменить текущий ip6tables через : update-alternatives --config ip6tables
|
||
Если вы хотите оставаться на iptables-nft, вам придется пересобрать патченную версию. Патч совсем небольшой.
|
||
В `nft.c` найдите фрагмент:
|
||
```
|
||
{
|
||
.name = "PREROUTING",
|
||
.type = "filter",
|
||
.prio = -300, /* NF_IP_PRI_RAW */
|
||
.hook = NF_INET_PRE_ROUTING,
|
||
},
|
||
{
|
||
.name = "OUTPUT",
|
||
.type = "filter",
|
||
.prio = -300, /* NF_IP_PRI_RAW */
|
||
.hook = NF_INET_LOCAL_OUT,
|
||
},
|
||
```
|
||
и замените везде -300 на -450.
|
||
|
||
Это нужно сделать вручную, никакой автоматики в `blockcheck.sh` нет.
|
||
|
||
Либо можно раз и навсегда избавиться от этой проблемы, используя `nftables`. Там можно создать `netfilter hook`
|
||
с любым приоритетом. Используйте приоритет -401 и ниже.
|
||
|
||
При использовании iptables и NAT, похоже, что нет способа прицепить обработчик очереди после NAT.
|
||
Пакет попадает в nfqws с source адресом внутренней сети, затем фрагментируется и уже не обрабатывается NAT.
|
||
Так и уходит во внешюю сеть с src ip 192.168.x.x. Следовательно, метод не срабатывает.
|
||
Видимо единственный рабочий метод - отказаться от iptables и использовать nftables.
|
||
Хук должен быть с приоритетом 101 или выше.
|
||
|
||
### МНОЖЕСТВЕННЫЕ СТРАТЕГИИ
|
||
|
||
`nfqws` способен по-разному реагировать на различные запросы и применять разные стратегии дурения.
|
||
Это реализовано посредством поддержки множества профилей дурения.
|
||
Профили разделяются в командной строке параметром `--new`. Первый профиль создается автоматически.
|
||
Для него не нужно `--new`. Каждый профиль имеет фильтр. По умолчанию он пуст, то есть профиль удовлетворяет
|
||
любым условиям.
|
||
Фильтр может содержать жесткие параметры: версия ip протокола, ipset и порты tcp/udp.
|
||
Они всегда однозначно идентифицируются даже на нулевой фазе десинхронизации, когда еще хост и L7 неизвестны.
|
||
В качестве мягкого фильтра могут выступать хост-листы и протокол прикладного уровня (l7).
|
||
L7 протокол становится известен обычно после первого пакета с данными.
|
||
При поступлении запроса идет проверка профилей в порядке от первого до последнего до
|
||
достижения первого совпадения с фильтром.
|
||
Жесткие параметры фильтра сверяются первыми. При несовпадении идет сразу же переход к следующему профилю.
|
||
Если какой-то профиль удовлетворяет жесткому фильтру и L7 фильтру и содержит авто-хостлист, он выбирается сразу.
|
||
Если профиль удовлетворяет жесткому фильтру и L7 фильтру, для него задан хостлист, и у нас еще нет имени хоста,
|
||
идет переход к следующему профилю. В противном случае идет проверка по хостлистам этого профиля.
|
||
Если имя хоста удовлетворяет листам, выбирается этот профиль. Иначе идет переход к следующему.
|
||
Может так случиться, что до получения имени хоста или узнавания L7 протокола соединение идет по одному профилю,
|
||
а при выяснении этих параметров профиль меняется на лету. Это может произойти даже дважды - при выяснении L7
|
||
и имени хоста. Чаще всего это выяснение совмещается в одно действие, поскольку по одному пакету как правило узнается и L7, и хост.
|
||
Поэтому если у вас есть параметры дурения нулевой фазы, тщательно продумывайте что может произойти при переключении стратегии.
|
||
Смотрите debug log, чтобы лучше понять что делает nfqws.
|
||
Нумерация профилей идет с 1 до N. Последним в цепочке создается пустой профиль с номером 0.
|
||
Он используется, когда никакие условия фильтров не совпали.
|
||
|
||
> [!IMPORTANT]
|
||
> Множественные стратегии создавались только для случаев, когда невозможно обьединить
|
||
> имеющиеся стратегии для разных ресурсов. Копирование стратегий из blockcheck для разных сайтов
|
||
> во множество профилей без понимания как они работают приведет к нагромождению параметров, которые все равно
|
||
> не покроют все возможные заблокированные ресурсы. Вы только увязните в этой каше.
|
||
|
||
> [!IMPORTANT]
|
||
> user-mode реализация ipset создавалась не как удобная замена *nix версии, реализованной в ядре.
|
||
> Вариант в ядре работает гораздо эффективнее. Это создавалось для систем без подержки ipset в ядре.
|
||
> Конкретно - Windows и ядра Linux, собранные без nftables и ipset модулей ядра. Например, в android нет ipset.
|
||
|
||
### IPTABLES ДЛЯ NFQWS
|
||
|
||
iptables для задействования атаки на первые пакеты данных в tcp соединении :
|
||
|
||
```
|
||
iptables -t mangle -I POSTROUTING -o <внешний_интерфейс> -p tcp -m multiport --dports 80,443 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:6 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass
|
||
```
|
||
|
||
Этот вариант применяем, когда DPI не следит за всеми запросами http внутри keep-alive сессии.
|
||
Если следит, направляем только первый пакет от https и все пакеты от http :
|
||
|
||
```
|
||
iptables -t mangle -I POSTROUTING -o <внешний_интерфейс> -p tcp --dport 443 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:6 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass
|
||
iptables -t mangle -I POSTROUTING -o <внешний_интерфейс> -p tcp --dport 80 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass
|
||
```
|
||
|
||
mark нужен, чтобы сгенерированный поддельный пакет не попал опять к нам на обработку. nfqws выставляет fwmark при его отсылке.
|
||
хотя nfqws способен самостоятельно различать помеченные пакеты, фильтр в iptables по mark нужен при использовании connbytes,
|
||
чтобы не допустить изменения порядка следования пакетов. Процессинг очереди - процесс отложенный.
|
||
Если ядро имеет пакеты на отсылку вне очереди - оно их отправляет незамедлительно.
|
||
Изменение правильного порядка следования пакетов при десинхронизации ломает всю идею.
|
||
Так же были замечены дедлоки при достаточно большой отсылке пакетов из nfqws и отсутствии mark фильтра.
|
||
Процесс может зависнуть. Поэтому наличие фильтра по mark в ip/nf tables можно считать обязательным.
|
||
|
||
Почему `--connbytes 1:6` :
|
||
* 1 - для работы методов десинхронизации 0-й фазы и корректной работы conntrack
|
||
* 2 - иногда данные идут в 3-м пакете 3-way handshake
|
||
* 3 - стандартная ситуация приема одного пакета запроса
|
||
* 4-6 - на случай ретрансмиссии или запроса длиной в несколько пакетов (TLSClientHello с kyber, например)
|
||
|
||
Для режима autottl необходимо перенаправление входящего `SYN,ACK` пакета или первого пакета соединения (что обычно есть тоже самое).
|
||
Можно построить фильтр на tcp flags и модуле u32 для поиска характерных паттернов http redirect, но проще использовать connbytes.
|
||
|
||
Для режима autohostlist необходимо перенаправление нескольких входящих пакетов, чтобы засечь RST или http redirect.
|
||
Так же стоит увеличить лимит исходящих пакетов в connbytes, чтобы в него вошли все возможные ретрансмиссии, после которых идет реакция по autoostlist.
|
||
|
||
`
|
||
iptables -t mangle -I PREROUTING -i <внешний интерфейс> -p tcp -m multiport --sports 80,443 -m connbytes --connbytes-dir=reply --connbytes-mode=packets --connbytes 1:3 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass
|
||
`
|
||
|
||
Для quic :
|
||
|
||
```
|
||
iptables -t mangle -I POSTROUTING -o <внешний_интерфейс> -p udp --dport 443 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:6 -m mark ! --mark 0x40000000/0x40000000 -j NFQUEUE --queue-num 200 --queue-bypass
|
||
```
|
||
|
||
6 пакетов берется, чтобы покрыть случаи возможных ретрансмиссий quic initial в случае плохой связи или если сервер плохо себя чувствует, а приложение настаивает именно на quic, не переходя на tcp.
|
||
А так же для работы autohostlist по quic. Однако, autohostlist для quic не рекомендуется.
|
||
|
||
### NFTABLES ДЛЯ NFQWS
|
||
|
||
Можно начать с базовой конфигурации.
|
||
|
||
```
|
||
IFACE_WAN=wan
|
||
|
||
nft create table inet ztest
|
||
|
||
nft add chain inet ztest post "{type filter hook postrouting priority mangle;}"
|
||
nft add rule inet ztest post oifname $IFACE_WAN meta mark and 0x40000000 == 0 tcp dport "{80,443}" ct original packets 1-6 queue num 200 bypass
|
||
nft add rule inet ztest post oifname $IFACE_WAN meta mark and 0x40000000 == 0 udp dport 443 ct original packets 1-6 queue num 200 bypass
|
||
|
||
# auto hostlist with avoiding wrong ACK numbers in RST,ACK packets sent by russian DPI
|
||
sysctl net.netfilter.nf_conntrack_tcp_be_liberal=1
|
||
nft add chain inet ztest pre "{type filter hook prerouting priority filter;}"
|
||
nft add rule inet ztest pre iifname $IFACE_WAN tcp sport "{80,443}" ct reply packets 1-3 queue num 200 bypass
|
||
```
|
||
|
||
Для задействования IP фрагментации и `datanoack` на проходящие пакеты требуется особая конфигурация цепочек, перенаправляющая пакеты после NAT.
|
||
В скриптах zapret эта схема называется `POSTNAT`, и она возможна только на nftables.
|
||
Сгенерированные nfqws пакеты требуется на раннем этапе помечать как **notrack**, чтобы они не были испорчены NAT.
|
||
|
||
```
|
||
IFACE_WAN=wan
|
||
|
||
nft create table inet ztest
|
||
|
||
nft add chain inet ztest postnat "{type filter hook postrouting priority srcnat+1;}"
|
||
nft add rule inet ztest postnat oifname $IFACE_WAN meta mark and 0x40000000 == 0 tcp dport "{80,443}" ct original packets 1-6 queue num 200 bypass
|
||
nft add rule inet ztest postnat oifname $IFACE_WAN meta mark and 0x40000000 == 0 udp dport 443 ct original packets 1-6 queue num 200 bypass
|
||
|
||
nft add chain inet ztest predefrag "{type filter hook output priority -401;}"
|
||
nft add rule inet ztest predefrag "mark & 0x40000000 != 0x00000000 notrack"
|
||
```
|
||
|
||
Удаление тестовой таблицы :
|
||
|
||
```
|
||
nft delete table inet ztest
|
||
```
|
||
|
||
### FLOW OFFLOADING
|
||
|
||
Если ваше устройство поддерживает аппаратное ускорение (flow offloading, hardware nat, hardware acceleration), то
|
||
iptables могут не работать. При включенном offloading пакет не проходит по обычному пути netfilter. Необходимо или его
|
||
отключить, или выборочно им управлять.
|
||
|
||
В новых ядрах присутствует software flow offloading (SFO).
|
||
Пакеты, проходящие через SFO, так же проходят мимо большей части механизмов iptables. При включенном SFO работает
|
||
DNAT/REDIRECT (tpws). Эти соединения исключаются из offloading. Однако, остальные соединения идут через SFO, потому
|
||
NFQUEUE будет срабатывать только до помещения соединения в flowtable. Практически это означает, что почти весь функционал nfqws работать не будет.
|
||
Offload включается через специальный target в iptables `FLOWOFFLOAD`. Не обязательно пропускать весь трафик через offload. Можно исключить из
|
||
offload соединения, которые должны попасть на tpws или nfqws. openwrt не предусматривает выборочного управления offload.
|
||
Поэтому скрипты zapret поддерживают свою систему выборочного управления offload в openwrt.
|
||
|
||
iptables target `FLOWOFFLOAD` - это проприетарное изобретение openwrt.
|
||
Управление offload в nftables реализовано в базовом ядре linux без патчей.
|
||
|
||
|
||
## tpws
|
||
|
||
tpws - это transparent proxy.
|
||
```
|
||
@<config_file>|$<config_file> ; читать конфигурацию из файла. опция должна быть первой. остальные опции игнорируются.
|
||
|
||
--debug=0|1|2|syslog|@<filename> ; 0,1,2 = логирование на косоль : 0=тихо, 1(default)=подробно, 2=отладка.
|
||
--debug-level=0|1|2 ; указать уровень логирования для syslog и @<filename>
|
||
--daemon ; демонизировать прогу
|
||
--pidfile=<file> ; сохранить PID в файл
|
||
--user=<username> ; менять uid процесса
|
||
--uid=uid[:gid] ; менять uid процесса
|
||
--bind-addr ; на каком адресе слушать. может быть ipv4 или ipv6 адрес
|
||
; если указан ipv6 link local, то требуется указать с какого он интерфейса : fe80::1%br-lan
|
||
--bind-linklocal=no|unwanted|prefer|force
|
||
; no : биндаться только на global ipv6
|
||
; unwanted (default) : предпочтительно global, если нет - LL
|
||
; prefer : предпочтительно LL, если нет - global
|
||
; force : биндаться только на LL
|
||
--bind-iface4=<iface> ; слушать на первом ipv4 интерфейса iface
|
||
--bind-iface6=<iface> ; слушать на первом ipv6 интерфейса iface
|
||
--bind-wait-ifup=<sec ; ждать до N секунд появления и поднятия интерфейса
|
||
--bind-wait-ip=<sec> ; ждать до N секунд получения IP адреса (если задан --bind-wait-ifup - время идет после поднятия интерфейса)
|
||
--bind-wait-ip-linklocal=<sec>
|
||
; имеет смысл только при задании --bind-wait-ip
|
||
; --bind-linklocal=unwanted : согласиться на LL после N секунд
|
||
; --bind-linklocal=prefer : согласиться на global address после N секунд
|
||
--bind-wait-only ; подождать все бинды и выйти. результат 0 в случае успеха, иначе не 0.
|
||
--connect-bind-addr ; с какого адреса подключаться во внешнюю сеть. может быть ipv4 или ipv6 адрес
|
||
; если указан ipv6 link local, то требуется указать с какого он интерфейса : fe80::1%br-lan
|
||
; опция может повторяться для v4 и v6 адресов
|
||
; опция не отменяет правил маршрутизации ! выбор интерфейса определяется лишь правилами маршрутизации, кроме случая v6 link local.
|
||
--socks ; вместо прозрачного прокси реализовать socks4/5 proxy
|
||
--no-resolve ; запретить ресолвинг имен через socks5
|
||
--resolve-threads ; количество потоков ресолвера
|
||
--port=<port> ; на каком порту слушать
|
||
--maxconn=<max_connections> ; максимальное количество соединений от клиентов к прокси
|
||
--maxfiles=<max_open_files> ; макс количество файловых дескрипторов (setrlimit). мин требование (X*connections+16), где X=6 в tcp proxy mode, X=4 в режиме тамперинга.
|
||
; стоит сделать запас с коэффициентом как минимум 1.5. по умолчанию maxfiles (X*connections)*1.5+16
|
||
--max-orphan-time=<sec> ; если вы запускаете через tpws торрент-клиент с множеством раздач, он пытается установить очень много исходящих соединений,
|
||
; большая часть из которых отваливается по таймауту (юзера сидят за NAT, firewall, ...)
|
||
; установление соединения в linux может длиться очень долго. локальный конец отвалился, перед этим послав блок данных,
|
||
; tpws ждет подключения удаленного конца, чтобы отослать ему этот блок, и зависает надолго.
|
||
; настройка позволяет сбрасывать такие подключения через N секунд, теряя блок данных. по умолчанию 5 сек. 0 означает отключить функцию
|
||
; эта функция не действует на успешно подключенные ранее соединения
|
||
|
||
--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
|
||
--nosplice ; не использовать splice на linux системах
|
||
--skip-nodelay ; не устанавливать в исходящих соединения TCP_NODELAY. несовместимо со split.
|
||
--local-tcp-user-timeout=<seconds> ; таймаут соединений client-proxy (по умолчанию : 10 сек, 0 = оставить системное значение)
|
||
--remote-tcp-user-timeout=<seconds> ; таймаут соединений proxy-target (по умолчанию : 20 сек, 0 = оставить системное значение)
|
||
|
||
--split-pos=N|-N|marker+N|marker-N ; список через запятую маркеров для tcp сегментации
|
||
--split-any-protocol ; применять сегментацию к любым пакетам. по умолчанию - только к известным протоколам (http, TLS)
|
||
--disorder[=http|tls] ; путем манипуляций с сокетом вынуждает отправлять первым второй сегмент разделенного запроса
|
||
--oob[=http|tls] ; отправить байт out-of-band data (OOB) в конце первой части сплита
|
||
--oob-data=<char>|0xHEX ; переопределить байт OOB. по умолчанию 0x00.
|
||
--hostcase ; менять регистр заголовка "Host:". по умолчанию на "host:".
|
||
--hostspell=HoST ; точное написание заголовка Host (можно "HOST" или "HoSt"). автоматом включает --hostcase
|
||
--hostdot ; добавление точки после имени хоста : "Host: kinozal.tv."
|
||
--hosttab ; добавление табуляции после имени хоста : "Host: kinozal.tv\t"
|
||
--hostnospace ; убрать пробел после "Host:"
|
||
--hostpad=<bytes> ; добавить паддинг-хедеров общей длиной <bytes> перед Host:
|
||
--domcase ; домен после Host: сделать таким : TeSt.cOm
|
||
--methodspace ; добавить пробел после метода : "GET /" => "GET /"
|
||
--methodeol ; добавить перевод строки перед методом : "GET /" => "\r\nGET /"
|
||
--unixeol ; конвертировать 0D0A в 0A и использовать везде 0A
|
||
--tlsrec=N|-N|marker+N|marker-N ; разбивка TLS ClientHello на 2 TLS records на указанной позиции. Минимальное смещение - 6.
|
||
--mss=<int> ; установить MSS для клиента. может заставить сервер разбивать ответы, но существенно снижает скорость
|
||
--tamper-start=[n]<pos> ; начинать дурение только с указанной байтовой позиции или номера блока исходяшего потока (считается позиция начала принятого блока)
|
||
--tamper-cutoff=[n]<pos> ; закончить дурение на указанной байтовой позиции или номере блока исходящего потока (считается позиция начала принятого блока)
|
||
--hostlist=<filename> ; действовать только над доменами, входящими в список из filename. поддомены автоматически учитываются.
|
||
; в файле должен быть хост на каждой строке.
|
||
; список читается при старте и хранится в памяти в виде иерархической структуры для быстрого поиска.
|
||
; при изменении времени модификации файла он перечитывается автоматически по необходимости
|
||
; список может быть запакован в gzip. формат автоматически распознается и разжимается
|
||
; списков может быть множество. пустой общий лист = его отсутствие
|
||
; хосты извлекаются из Host: хедера обычных http запросов и из SNI в TLS ClientHello.
|
||
--hostlist-exclude=<filename> ; не применять дурение к доменам из листа. может быть множество листов. схема аналогична include листам.
|
||
--hostlist-auto=<filename> ; обнаруживать автоматически блокировки и заполнять автоматический hostlist (требует перенаправления входящего трафика)
|
||
--hostlist-auto-fail-threshold=<int> ; сколько раз нужно обнаружить ситуацию, похожую на блокировку, чтобы добавить хост в лист (по умолчанию: 3)
|
||
--hostlist-auto-fail-time=<int> ; все эти ситуации должны быть в пределах указанного количества секунд (по умолчанию: 60)
|
||
--hostlist-auto-debug=<logfile> ; лог положительных решений по autohostlist. позволяет разобраться почему там появляются хосты.
|
||
--new ; начало новой стратегии (новый профиль)
|
||
--filter-l3=ipv4|ipv6 ; фильтр версии ip для текущей стратегии
|
||
--filter-tcp=[~]port1[-port2]|* ; фильтр портов tcp для текущей стратегии. ~ означает инверсию. поддерживается список через запятую.
|
||
--filter-l7=[http|tls|quic|wireguard|dht|unknown] ; фильтр протокола L6-L7. поддерживается несколько значений через запятую.
|
||
--ipset=<filename> ; включающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая.
|
||
--ipset-exclude=<filename> ; исключающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая.
|
||
```
|
||
|
||
### TCP СЕГМЕНТАЦИЯ В TPWS
|
||
|
||
tpws, как и nfqws, поддерживает множественную сегментацию запросов. Сплит позиции задаются в `--split-pos`.
|
||
Указываются маркеры через запятую. Описание маркеров см в разделе [nfqws](#tcp-сегментация).
|
||
|
||
На прикладном уровне в общем случае нет гарантированного средства заставить ядро выплюнуть
|
||
блок данных, порезанным в определенном месте. ОС держит буфер отсылки (SNDBUF) у каждого сокета.
|
||
Если у сокета включена опция TCP_NODELAY и буфер пуст, то каждый send приводит к отсылке
|
||
отдельного ip пакета или группы пакетов, если блок не вмещается в один ip пакет.
|
||
Однако, если в момент send уже имеется неотосланный буфер, то ОС присоединит данные к нему,
|
||
никакой отсылки отдельным пакетом не будет. Но в этом случае и так нет никакой гарантии,
|
||
что какой-то блок сообщения пойдет в начале пакета, на что собственно и заточены DPI.
|
||
Разбиение будет производится согласно MSS, который зависит от MTU исходящего интерфейса.
|
||
Таким образом DPI, смотрящие в начало поля данных TCP пакета, будут поломаны в любом случае.
|
||
Протокол http относится к запрос-ответным протоколам. Новое сообщение посылается только тогда,
|
||
когда сервер получил запрос и полностью вернул ответ. Значит запрос фактически был не только отослан,
|
||
но и принят другой стороной, а следовательно буфер отсылки пуст, и следующие 2 send приведут
|
||
к отсылке сегментов данных разными ip пакетами.
|
||
|
||
Таким образом tpws обеспечивает сплит только за счет раздельных вызовов send, и это обычно работает надежно,
|
||
если разбивать не на слишком много частей и не на слишком мелкие подряд следующие части.
|
||
В последнем случае Linux все же может обьединить некоторые части, что приведет к несоответствию реальной сегментации
|
||
указанным сплит позициям. Другие ОС в этом вопросе ведут себя более предсказуемо. Спонтанного обьединения замечено не было.
|
||
Поэтому не стоит злоупотреблять сплитами и в особенности мелкими соседними пакетами.
|
||
|
||
tpws работает на уровне сокетов, поэтому длинный запрос, не вмещающийся в 1 пакет (TLS с kyber), он получает целым блоком.
|
||
На каждую сплит часть он делает отдельный вызов `send()`. Но ОС не сможет отослать данные в одном пакете, если размер превысит MTU.
|
||
В случае слишком большого сегмента ОС дополнительно его порежет на более мелкие. Результат должен быть аналогичен nfqws.
|
||
|
||
`--disorder` заставляет слать каждый 2-й пакет с TTL=1, начиная с первого.
|
||
К серверу приходят все четные пакеты сразу. На остальные ОС делает ретрансмиссию, и они приходят потом.
|
||
Это само по себе создает дополнительную задержку (200 мс в linux для первой ретрансмиссии).
|
||
Иным способом сделать disorder в сокет варианте не представляется возможным.
|
||
Итоговый порядок для 6 сегментов получается `2 4 6 1 3 5`.
|
||
|
||
`--oob` высылает 1 байт out-of-band data после первого сплит сегмента. `oob` в каждом сегменте сплита показал себя ненадежным.
|
||
Сервер получает oob в сокет.
|
||
|
||
Сочетание `oob` и `disorder` возможно только в Linux. Остальные ОС не умеют с таким справляться. Флаг URG теряется при ретрансмиссиях.
|
||
Сервер получает oob в сокет. Сочетание этих параметров в ос, кроме Linux, вызывает ошибку на этапе запуска.
|
||
|
||
### TLSREC
|
||
|
||
`--tlsrec` позволяют внутри одного tcp сегмента разрезать TLS ClientHello на 2 TLS records. Можно использовать стандартный
|
||
механизм маркеров для задания относительных позиций.
|
||
|
||
`--tlsrec` ломает значительное количество сайтов. Криптобиблиотеки (openssl, ...) на оконечных http серверах
|
||
без проблем принимают разделенные tls сегменты, но мидлбоксы - не всегда. К мидлбоксам можно отнести CDN
|
||
или системы ddos-защиты. Поэтому применение `--tlsrec` без ограничителей вряд ли целесообразно.
|
||
В РФ `--tlsrec` обычно не работает с TLS 1.2, потому что цензор парсит сертификат сервера из ServerHello.
|
||
Работает только с TLS 1.3, поскольку там эта информация шифруется.
|
||
Впрочем, сейчас сайтов, не поддерживающих TLS 1.3, осталось немного.
|
||
|
||
### MSS
|
||
|
||
`--mss` устанавливает опцию сокета TCP_MAXSEG. Клиент выдает это значение в tcp опциях SYN пакета.
|
||
Сервер в ответ в SYN,ACK выдает свой MSS. На практике сервера обычно снижают размеры отсылаемых ими пакетов, но они
|
||
все равно не вписываются в низкий MSS, указанный клиентом. Обычно чем больше указал клиент, тем больше
|
||
шлет сервер. На TLS 1.2 если сервер разбил заброс так, чтобы домен из сертификата не попал в первый пакет,
|
||
это может обмануть DPI, секущий ответ сервера.
|
||
Схема может значительно снизить скорость и сработать не на всех сайтах.
|
||
С фильтром по hostlist совместимо только в режиме socks при включенном удаленном ресолвинге хостов.
|
||
(firefox network.proxy.socks_remote_dns). Это единственный вариант, когда tpws может узнать имя хоста
|
||
еще на этапе установления соединения.
|
||
Применяя данную опцию к сайтам TLS1.3, если броузер тоже поддерживает TLS1.3, то вы делаете только хуже.
|
||
Но нет способа автоматически узнать когда надо применять, когда нет, поскольку MSS идет только в
|
||
3-way handshake еще до обмена данными, а версию TLS можно узнать только по ответу сервера, который
|
||
может привести к реакции DPI.
|
||
Использовать только когда нет ничего лучше или для отдельных ресурсов.
|
||
Для http использовать смысла нет, поэтому заводите отдельный desync profile с фильтром по порту 443.
|
||
Работает только на Linux, не работает на BSD и MacOS.
|
||
|
||
### ДРУГИЕ ПАРАМЕТРЫ ДУРЕНИЯ
|
||
|
||
Параметр `--hostpad=<bytes>` добавляет паддинг-хедеров перед `Host:` на указанное количество байтов.
|
||
Если размер `<bytes>` слишком большой, то идет разбивка на разные хедеры по 2K.
|
||
Общий буфер приема http запроса - 64K, больший паддинг не поддерживается, да и http сервера
|
||
такое уже не принимают.
|
||
Полезно против DPI, выполняющих реассемблинг TCP с ограниченным буфером.
|
||
Если техника работает, то после некоторого количества bytes http запрос начнет проходить до сайта.
|
||
Если при этом критический размер padding около MTU, значит скорее всего DPI не выполняет реассемблинг пакетов, и лучше будет использовать обычные опции TCP сегментации.
|
||
Если все же реассемблинг выполняется, то критический размер будет около размера буфера DPI. Он может быть 4K или 8K, возможны и другие значения.
|
||
|
||
### МНОЖЕСТВЕННЫЕ СТРАТЕГИИ
|
||
|
||
Работают аналогично `nfqws`, кроме некоторых моментов.
|
||
Нет параметра `--filter-udp`, поскольку `tpws` udp не поддерживает.
|
||
Методы нулевой фазы (`--mss`) могут работать по хостлисту в одном единственном случае:
|
||
если используется режим socks и удаленный ресолвинг хостов через прокси.
|
||
То есть работоспособность вашей настройки в одном и том же режиме может зависеть от того,
|
||
применяет ли клиент удаленный ресолвинг. Это может быть неочевидно.
|
||
В одной программе работает, в другой - нет.
|
||
Если вы используете профиль с хостлистом , и вам нужен mss, укажите mss в профиле с хостлистом,
|
||
создайте еще один профиль без хостлиста, если его еще нет, и в нем еще раз укажите mss.
|
||
Тогда при любом раскладе будет выполняться mss.
|
||
Используйте `curl --socks5` и `curl --socks5-hostname` для проверки вашей стратегии.
|
||
Смотрите вывод `--debug`, чтобы убедиться в правильности настроек.
|
||
|
||
### СЛУЖЕБНЫЕ ПАРАМЕТРЫ
|
||
|
||
`--debug` позволяет выводить подробный лог действий на консоль, в syslog или в файл.
|
||
Может быть важен порядок следования опций. `--debug` лучше всего указывать в самом начале.
|
||
Опции анализируются последовательно. Если ошибка будет при проверке опции, а до анализа `--debug` еще дело не дошло,
|
||
то сообщения не будут выведены в файл или syslog.
|
||
`--debug=0|1|2` позволяют сразу в одном параметре включить логирование на консоль и указать уровень.
|
||
Сохранено для совместимости с более старыми версиями. Для выбора уровня в режиме syslog или file используйте
|
||
отдельный параметр `--debug-level`. Если в этих режимах `--debug` не указывать уровень через `--debug-level`, то
|
||
автоматически назначается уровень 1.
|
||
При логировании в файл процесс не держит файл открытым. Ради каждой записи файл открывается и потом закрывается.
|
||
Так что файл можно удалить в любой момент, и он будет создан заново при первом же сообщении в лог.
|
||
Но имейте в виду, что если вы запускаете процесс под root, то будет сменен UID на не-root.
|
||
В начале на лог файл меняется owner, иначе запись будет невозможна. Если вы потом удалите файл,
|
||
и у процесса не будет прав на создание файла в его директории, лог больше не будет вестись.
|
||
Вместо удаления лучше использовать truncate.
|
||
В шелле это можно сделать через команду ": >filename"
|
||
|
||
tpws может биндаться на множество интерфейсов и IP адресов (до 32 шт).
|
||
Порт всегда только один.
|
||
Параметры `--bind-iface*` и `--bind-addr` создают новый бинд.
|
||
Остальные параметры `--bind-*` относятся к последнему бинду.
|
||
Для бинда на все ipv4 укажите `--bind-addr "0.0.0.0"`, на все ipv6 - `"::"`. `--bind-addr=""` - биндаемся на все ipv4 и ipv6.
|
||
Выбор режима использования link local ipv6 адресов (`fe80::/8`) :
|
||
```
|
||
--bind-iface6 --bind-linklocal=no : сначала приватный адрес fc00::/7, затем глобальный адрес
|
||
--bind-iface6 --bind-linklocal=unwanted : сначала приватный адрес fc00::/7, затем глобальный адрес, затем link local.
|
||
--bind-iface6 --bind-linklocal=prefer : сначала link local, затем приватный адрес fc00::/7, затем глобальный адрес.
|
||
--bind-iface6 --bind-linklocal=force : только link local
|
||
```
|
||
Если не указано ни одного бинда, то создается бинд по умолчанию на все адреса всех интерфейсов.
|
||
Для бинда на конкретный link-local address делаем так : `--bind-iface6=fe80::aaaa:bbbb:cccc:dddd%iface-name`
|
||
Параметры `--bind-wait*` могут помочь в ситуациях, когда нужно взять IP с интерфейса, но его еще нет, он не поднят
|
||
или не сконфигурирован.
|
||
В разных системах события ifup ловятся по-разному и не гарантируют, что интерфейс уже получил IP адрес определенного типа.
|
||
В общем случае не существует единого механизма повеситься на событие типа "на интерфейсе X появился link local address".
|
||
Для бинда на известный ip, когда еще интерфейс не сконфигурирован, нужно делать так: `--bind-addr=192.168.5.3 --bind-wait-ip=20`
|
||
В режиме transparent бинд возможен на любой несуществующий адрес, в режиме socks - только на существующий.
|
||
|
||
Параметры rcvbuf и sndbuf позволяют установить setsockopt SO_RCVBUF SO_SNDBUF для локального и удаленного соединения.
|
||
|
||
`--skip-nodelay` может быть полезен, когда tpws используется без дурения, чтобы привести MTU к MTU системы, на которой работает tpws.
|
||
Это может быть полезно для скрытия факта использования VPN. Пониженный MTU - 1 из способов обнаружения
|
||
подозрительного подключения. С tcp proxy ваши соединения неотличимы от тех, что сделал бы сам шлюз.
|
||
|
||
`--local-tcp-user-timeout` и `--remote-tcp-user-timeout` устанавливают значение таймаута в секундах
|
||
для соединений клиент-прокси и прокси-сервер. Этот таймаут соответствует опции сокета linux
|
||
TCP_USER_TIMEOUT. Под таймаутом подразумевается время, в течение которого буферизированные данные
|
||
не переданы или на переданные данные не получено подтверждение (ACK) от другой стороны.
|
||
Этот таймаут никак не касается времени отсутствия какой-либо передачи через сокет лишь потому,
|
||
что данных для передачи нет. Полезно для сокращения время закрытия подвисших соединений.
|
||
Поддерживается только на Linux и MacOS.
|
||
|
||
Режим `--socks` не требует повышенных привилегий (кроме бинда на привилегированные порты 1..1023).
|
||
Поддерживаются версии socks 4 и 5 без авторизации. Версия протокола распознается автоматически.
|
||
Подключения к IP того же устройства, на котором работает tpws, включая localhost, запрещены.
|
||
socks5 позволяет удаленно ресолвить хосты (curl : --socks5-hostname firefox : socks_remote_dns=true).
|
||
tpws поддерживает эту возможность асинхронно, не блокируя процессинг других соединений, используя
|
||
многопоточный пул ресолверов. Количество потоков определяется автоматически в зависимости от `--maxconn`,
|
||
но можно задать и вручную через параметр `--resolver-threads`.
|
||
Запрос к socks выставляется на паузу, пока домен не будет преобразован в ip адрес в одном из потоков
|
||
ресолвера. Ожидание может быть более длинным, если все потоки заняты.
|
||
Если задан параметр `--no-resolve`, то подключения по именам хостов запрещаются, а пул ресолверов не создается.
|
||
Тем самым экономятся ресурсы.
|
||
|
||
### IPTABLES ДЛЯ TPWS
|
||
|
||
Для перенаправления tcp соединения на transparent proxy используются команды следующего вида :
|
||
|
||
```
|
||
iptables -t nat -I OUTPUT -o <внешний_интерфейс> -p tcp --dport 80 -m owner ! --uid-owner tpws -j DNAT --to 127.0.0.127:988
|
||
iptables -t nat -I PREROUTING -i <внутренний_интерфейс> -p tcp --dport 80 -j DNAT --to 127.0.0.127:988
|
||
```
|
||
|
||
Первая команда для соединений с самой системы, вторая - для проходящих через роутер соединений.
|
||
|
||
DNAT на localhost работает в цепочке OUTPUT, но не работает в цепочке PREROUTING без включения параметра
|
||
route_localnet :
|
||
|
||
`sysctl -w net.ipv4.conf.<внутренний_интерфейс>.route_localnet=1`
|
||
|
||
Можно использовать `-j REDIRECT --to-port 988` вместо DNAT, однако в этом случае процесс transparent proxy должен
|
||
слушать на ip адресе входящего интерфейса или на всех адресах. Слушать на всех - не есть хорошо с точки зрения
|
||
безопасности. Слушать на одном (локальном) можно, но в случае автоматизированного скрипта придется его узнавать, потом
|
||
динамически вписывать в команду. В любом случае требуются дополнительные усилия. Использование route_localnet тоже имеет
|
||
потенциальные проблемы с безопасностью. Вы делаете доступным все, что висит на `127.0.0.0/8` для локальной подсети <
|
||
внутренний_интерфейс>. Службы обычно привязываются к `127.0.0.1`, поэтому можно средствами iptables запретить входящие
|
||
на `127.0.0.1` не с интерфейса lo, либо повесить tpws на любой другой IP из из `127.0.0.0/8`, например на `127.0.0.127`,
|
||
и разрешить входящие не с lo только на этот IP.
|
||
|
||
```
|
||
iptables -A INPUT ! -i lo -d 127.0.0.127 -j ACCEPT
|
||
iptables -A INPUT ! -i lo -d 127.0.0.0/8 -j DROP
|
||
```
|
||
|
||
Фильтр по owner необходим для исключения рекурсивного перенаправления соединений от самого tpws. tpws запускается под
|
||
пользователем `tpws`, для него задается исключающее правило.
|
||
|
||
ip6tables работают почти точно так же, как и ipv4, но есть ряд важных нюансов. В DNAT следует брать адрес --to в
|
||
квадратные скобки. Например :
|
||
|
||
`ip6tables -t nat -I OUTPUT -o <внешний_интерфейс> -p tcp --dport 80 -m owner ! --uid-owner tpws -j DNAT --to [::1]:988`
|
||
|
||
Параметра route_localnet не существует для ipv6. DNAT на localhost (::1) возможен только в цепочке OUTPUT. В цепочке
|
||
PREROUTING DNAT возможен на любой global address или на link local address того же интерфейса, откуда пришел пакет.
|
||
NFQUEUE работает без изменений.
|
||
|
||
### NFTABLES ДЛЯ TPWS
|
||
|
||
Базовая конфигурация :
|
||
|
||
```
|
||
IFACE_WAN=wan
|
||
IFACE_LAN=br-lan
|
||
|
||
sysctl -w net.ipv4.conf.$IFACE_LAN.route_localnet=1
|
||
|
||
nft create table inet ztest
|
||
|
||
nft create chain inet ztest localnet_protect
|
||
nft add rule inet ztest localnet_protect ip daddr 127.0.0.127 return
|
||
nft add rule inet ztest localnet_protect ip daddr 127.0.0.0/8 drop
|
||
nft create chain inet ztest input "{type filter hook input priority filter - 1;}"
|
||
nft add rule inet ztest input iif != "lo" jump localnet_protect
|
||
|
||
nft create chain inet ztest dnat_output "{type nat hook output priority dstnat;}"
|
||
nft add rule inet ztest dnat_output meta skuid != tpws oifname $IFACE_WAN tcp dport { 80, 443 } dnat ip to 127.0.0.127:988
|
||
nft create chain inet ztest dnat_pre "{type nat hook prerouting priority dstnat;}"
|
||
nft add rule inet ztest dnat_pre meta iifname $IFACE_LAN tcp dport { 80, 443 } dnat ip to 127.0.0.127:988
|
||
```
|
||
|
||
Удаление таблицы :
|
||
```
|
||
nft delete table inet ztest
|
||
```
|
||
|
||
|
||
## Способы получения списка заблокированных IP
|
||
|
||
!!! nftables не могут работать с ipset-ами. Собственный аналогичный механизм требует огромного количество RAM
|
||
!!! для загрузки больших листов. Например, для загона 100K записей в nfset не хватает даже 256 Mb.
|
||
!!! Если вам нужны большие листы на домашних роутерах, откатывайтесь на iptables+ipset.
|
||
|
||
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_preresolved.sh`. то же самое, что и 2), только берется уже заресолвленый список
|
||
со стороннего ресурса.
|
||
|
||
4) `ipset/get_reestr_preresolved_smart.sh`. то же самое, что и 3), с добавлением всего диапазона некоторых
|
||
автономных систем (прыгающие IP адреса из cloudflare, facebook, ...) и некоторых поддоменов блокируемых сайтов
|
||
|
||
Cкрипты с названием `get_antifilter_*` оперируют списками адресов и масок подсетей с сайтов antifilter.network и antifilter.download :
|
||
|
||
5) `ipset/get_antifilter_ip.sh`. получает лист https://antifilter.download/list/ip.lst.
|
||
|
||
6) `ipset/get_antifilter_ipsmart.sh`. получает лист https://antifilter.network/download/ipsmart.lst.
|
||
умная суммаризация отдельных адресов из ip.lst по маскам от /32 до /22
|
||
|
||
7) `ipset/get_antifilter_ipsum.sh`. получает лист https://antifilter.download/list/ipsum.lst.
|
||
суммаризация отдельных адресов из ip.lst по маске /24
|
||
|
||
8) `ipset/get_antifilter_ipresolve.sh`. получает лист https://antifilter.download/list/ipresolve.lst.
|
||
пре-ресолвленный список, аналогичный получаемый при помощи get_reestr_resolve. только ipv4.
|
||
|
||
9) `ipset/get_antifilter_allyouneed.sh`. получает лист https://antifilter.download/list/allyouneed.lst.
|
||
Суммарный список префиксов, созданный из ipsum.lst и subnet.lst.
|
||
|
||
10) `ipset/get_refilter_ipsum.sh`.
|
||
Список берется отсюда : https://github.com/1andrevich/Re-filter-lists
|
||
|
||
Все варианты рассмотренных скриптов автоматически создают и заполняют ipset.
|
||
Варианты 2-10 дополнительно вызывают вариант 1.
|
||
|
||
11) `ipset/get_config.sh`. этот скрипт вызывает то, что прописано в переменной GETLIST из файла config
|
||
Если переменная не определена, то ресолвятся лишь листы для ipset nozapret/nozapret6.
|
||
|
||
Листы РКН все время изменяются. Возникают новые тенденции. Требования к RAM могут меняться.
|
||
Поэтому необходима нечастая, но все же регулярная ревизия что же вообще у вас происходит на роутере.
|
||
Или вы можете узнать о проблеме лишь когда у вас начнет постоянно пропадать wifi, и вам придется
|
||
его перезагружать каждые 2 часа (метод кувалды).
|
||
|
||
Самые щадящие варианты по RAM - `get_antifilter_allyouneed.sh`, `get_antifilter_ipsum.sh`, `get_refilter_*.sh`.
|
||
|
||
Листы `zapret-ip.txt` и `zapret-ipban.txt` сохраняются в сжатом виде в файлы .gz.
|
||
Это позволяет снизить их размер во много раз и сэкономить место на роутере.
|
||
Отключить сжатие листов можно параметром конфига GZIP_LISTS=0.
|
||
|
||
На роутерах не рекомендуется вызывать эти скрипты чаще раза за 2 суток, поскольку сохранение идет
|
||
либо во внутреннюю флэш память роутера, либо в случае extroot - на флэшку.
|
||
В обоих случаях слишком частая запись может убить флэшку, но если это произойдет с внутренней
|
||
флэш памятью, то вы просто убьете роутер.
|
||
|
||
Принудительное обновление `ipset` выполняет скрипт `ipset/create_ipset.sh`.
|
||
Если передан параметр `no-update`, скрипт не обновляет `ipset`, а только создает его при его отсутствии и заполняет.
|
||
Это полезно, когда могут случиться несколько последовательных вызовов скрипта. Нет смысла несколько раз перезаполнять
|
||
`ipset`, это длительная операция на больших листах. Листы можно обновлять раз в несколько суток, и только тогда
|
||
вызывать `create_ipset` без параметра `no-update`. Во всех остальных случаях стоит применять `no-update`.
|
||
|
||
Список РКН уже достиг внушительных размеров в сотни тысяч IP адресов. Поэтому для оптимизации `ipset`
|
||
применяется утилита `ip2net`. Она берет список отдельных IP адресов и пытается интеллектуально создать из него подсети для сокращения
|
||
количества адресов. `ip2net` отсекает неправильные записи в листах, гарантируя отсутствие ошибок при их загрузке.
|
||
`ip2net` написан на языке C, поскольку операция ресурсоемкая. Иные способы роутер может не потянуть.
|
||
|
||
Можно внести список доменов в `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 адреса или подсети.
|
||
|
||
**FreeBSD**. Скрипты ipset/*.sh работают так же на FreeBSD. Вместо ipset они создают lookup таблицы ipfw с аналогичными именами.
|
||
ipfw таблицы в отличие от ipset могут содержать как ipv4, так и ipv6 адреса и подсети в одной таблице, поэтому разделения нет.
|
||
|
||
Параметр конфига LISTS_RELOAD задает произвольную команду для перезагрузки листов.
|
||
Это особенно полезно на BSD системах с PF.
|
||
LISTS_RELOAD=- отключает перезагрузку листов.
|
||
|
||
## 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.
|
||
ipfw из FreeBSD понимает ip/prefix, но не понимает ip1-ip2.
|
||
ip2net фильтрует входные данные, выкидывая неправильные IP адреса.
|
||
|
||
Выбирается подсеть, в которой присутствует указанный минимум адресов.
|
||
Для 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 - гораздо лучше.
|
||
|
||
## mdig
|
||
|
||
Программа предназначена для многопоточного ресолвинга больших листов через системный DNS.
|
||
Она берет из stdin список доменов и выводит в stdout результат ресолвинга. Ошибки выводятся в stderr.
|
||
|
||
```
|
||
--threads=<threads_number> ; количество потоков. по умолчанию 1.
|
||
--family=<4|6|46> ; выбор семейства IP адресов : ipv4, ipv6, ipv4+ipv6
|
||
--verbose ; дебаг-лог на консоль
|
||
--stats=N ; выводить статистику каждые N доменов
|
||
--log-resolved=<file> ; сохранять успешно отресолвленные домены в файл
|
||
--log-failed=<file> ; сохранять неудачно отресолвленные домены в файл
|
||
--dns-make-query=<domain> ; вывести в stdout бинарный DNS запрос по домену. если --family=6, запрос будет AAAA, иначе A.
|
||
--dns-parse-query ; распарсить бинарный DNS ответ и выдать все ivp4 и ipv6 адреса из него в stdout
|
||
```
|
||
|
||
Параметры `--dns-make-query` и `--dns-parse-query` позволяют провести ресолвинг одного домена через произвольный канал.
|
||
Например, следующим образом можно выполнить DoH запрос, используя лишь mdig и curl :
|
||
```
|
||
mdig --family=6 --dns-make-query=rutracker.org | curl --data-binary @- -H "Content-Type: application/dns-message" https://cloudflare-dns.com/dns-query | mdig --dns-parse-query
|
||
```
|
||
|
||
## Фильтрация по именам доменов
|
||
|
||
Альтернативой ipset является использование tpws или nfqws со списком доменов.
|
||
Оба демона принимают неограниченное количество листов include (`--hostlist`) и exclude (`--hostlist-exclude`).
|
||
Прежде всего проверяются exclude листы. При вхождении в них происходит отказ от дурения.
|
||
Далее при наличии include листов проверяется домен на вхождение в них. При невхождении в список отказ от дурения.
|
||
Если все include листы пустые, это приравнивается к отсутствию include листов. Ограничение перестает работать.
|
||
В иных случаях происходит дурение.
|
||
Нет ни одного списка - дурение всегда.
|
||
Есть только exclude список - дурение всех, кроме.
|
||
Есть только include список - дурение только их.
|
||
Есть оба - дурение только include, кроме exclude.
|
||
|
||
В системе запуска это обыграно следующим образом.
|
||
Присутствуют 2 include списка :
|
||
`ipset/zapret-hosts-users.txt.gz` или `ipset/zapret-hosts-users.txt`,
|
||
`ipset/zapret-hosts.txt.gz` или `ipset/zapret-hosts.txt`
|
||
и 1 exclude список
|
||
`ipset/zapret-hosts-users-exclude.txt.gz` или `ipset/zapret-hosts-users-exclude.txt`
|
||
|
||
При режимах фильтрации `MODE_FILTER=hostlist` или `MODE_FILTER=autohostlist` система запуска передает `nfqws` или `tpws` все листы, файлы которых присутствуют.
|
||
Передача происходит через замену маркеров `<HOSTLIST>` и `<HOSTLIST_NOAUTO>` на реальные параметры `--hostlist`, `--hostlist-exclude`, `--hostlist-auto`.
|
||
Если вдруг листы include присутствуют, но все они пустые, то работа аналогична отсутствию include листа.
|
||
Файл есть, но не смотря на это дурится все, кроме exclude.
|
||
Если вам нужен именно такой режим - не обязательно удалять `zapret-hosts-users.txt`. Достаточно сделать его пустым.
|
||
|
||
Поддомены учитываются автоматически. Например, строчка "ru" вносит в список "*.ru". Строчка "*.ru" в списке не сработает.
|
||
|
||
Список доменов РКН может быть получен скриптами
|
||
```
|
||
ipset/get_reestr_hostlist.sh
|
||
ipset/get_antizapret_domains.sh
|
||
ipset/get_reestr_resolvable_domains.sh
|
||
ipset/get_refilter_domains.sh
|
||
```
|
||
Он кладется в `ipset/zapret-hosts.txt.gz`.
|
||
|
||
При изменении времени модификации файлов списки перечитываются автоматически.
|
||
|
||
При фильтрации по именам доменов демон должен запускаться без фильтрации по ipset.
|
||
tpws и nfqws решают нужно ли применять дурение в зависимости от хоста, полученного из протокола прикладного уровня (http, tls, quic).
|
||
При использовании больших списков, в том числе списка РКН, оцените объем RAM на роутере !
|
||
Если после запуска демона RAM под завязку или случаются oom, значит нужно отказаться от таких больших списков.
|
||
|
||
## Режим фильтрации autohostlist
|
||
|
||
Этот режим позволяет проанализировать как запросы со стороны клиента, так и ответы от сервера.
|
||
Если хост еще не находится ни в каких листах и обнаруживается ситуация, похожая на блокировку,
|
||
происходит автоматическое добавление хоста в список `autohostlist` как в памяти, так и в файле.
|
||
`nfqws` или `tpws` сами ведут этот файл.
|
||
Чтобы какой-то хост не смог попась в `autohostlist` используйте `hostlist-exclude`.
|
||
Если он все-же туда попал - удалите запись из файла вручную. Процессы автоматически перечитают файл.
|
||
`tpws`/`nfqws` сами назначают владельцем файла юзера, под которым они работают после сброса привилегий,
|
||
чтобы иметь возможность обновлять лист.
|
||
|
||
В случае `nfqws` данный режим требует перенаправления в том числе и входящего трафика.
|
||
Крайне рекомендовано использовать ограничитель `connbytes`, чтобы `nfqws` не обрабатывал гигабайты.
|
||
По этой же причине не рекомендуется использование режима на BSD системах. Там нет фильтра `connbytes`.
|
||
|
||
На linux системах при использовании nfqws и фильтра connbytes может понадобится :
|
||
`sysctl net.netfilter.nf_conntrack_tcp_be_liberal=1`
|
||
Было замечено, что некоторые DPI в России возвращают RST с неверным ACK. Это принимается tcp/ip стеком
|
||
linux, но через раз приобретает статус INVALID в conntrack. Поэтому правила с `connbytes` срабатывают
|
||
через раз, не пересылая RST пакет `nfqws`.
|
||
|
||
Как вообще могут вести себя DPI, получив "плохой запрос" и приняв решение о блокировке:
|
||
|
||
1) Зависание: просто отмораживается, блокируя прохождение пакетов по TCP каналу.
|
||
2) RST: отправляет RST клиенту и/или серверу
|
||
3) Редирект: (только для http) отправляет редирект на сайт-заглушку
|
||
4) Подмена сертификата: (только для https) полный перехват TLS сеанса с попыткой всунуть что-то
|
||
свое клиенту. Применяется нечасто, поскольку броузеры на такое ругаются.
|
||
|
||
`nfqws` и `tpws` могут сечь варианты 1-3, 4 они не распознают.
|
||
Всилу специфики работы с отдельными пакетами или с TCP каналом tpws и nfqws распознают эти ситуации
|
||
по-разному.
|
||
Что считается ситуацией, похожей на блокировку :
|
||
1) **nfqws** Несколько ретрансмиссий первого запроса в TCP сеансе, в котором имеется host.
|
||
2) **nfqws,tpws** RST, пришедший в ответ на первый запрос с хостом.
|
||
3) **nfqws,tpws** HTTP редирект, пришедший в ответ на первый запрос с хостом, на глобальный адрес
|
||
с доменом 2 уровня, не совпадающим с доменом 2 уровня оригинального запроса.
|
||
4) **tpws** закрытие соединения клиентом после отправки первого запроса с хостом, если не было на него
|
||
ответа со стороны сервера. Это обычно случается по таймауту, когда нет ответа (случай "зависание").
|
||
|
||
Чтобы снизить вероятность ложных срабатываний, имеется счетчик ситуаций, похожих на блокировку.
|
||
Если за определенное время произойдет более определенного их количества, хост считается заблокированным
|
||
и заносится в `autohostlist`. По нему сразу же начинает работать стратегия по обходу блокировки.
|
||
Если в процессе счета вебсайт отвечает без признаков блокировки, счетчик сбрасывается.
|
||
Вероятно, это был временный сбой сайта.
|
||
|
||
На практике работа с данным режимом выглядит так.
|
||
Первый раз пользователь заходит на сайт и получает заглушку, сброс соединения или броузер подвисает,
|
||
вываливаясь по таймауту с сообщением о невозможности загрузить страницу.
|
||
Надо долбить F5, принуждая броузер повторять попытки. После некоторой попытки сайт
|
||
начинает работать, и дальше он будет работать всегда.
|
||
|
||
С этим режимом можно использовать техники обхода, ломающие значительное количество сайтов.
|
||
Если сайт не ведет себя как заблокированный, значит обход применен не будет.
|
||
В противном случае терять все равно нечего.
|
||
Однако, могут быть временные сбои сервера, приводящие к ситуации, аналогичной блокировке.
|
||
Могут происходит ложные срабатывания. Если такое произошло, стратегия может начать ломать
|
||
незаблокированный сайт. Эту ситуацию, увы, придется вам контролировать вручную.
|
||
Заносите такие домены в `ipset/zapret-hosts-user-exclude.txt`, чтобы избежать повторения.
|
||
Чтобы впоследствии разобраться почему домен был занесен в лист, можно включить `autohostlist debug log`.
|
||
Он полезен тем, что работает без постоянного просмотра вывода `nfqws` в режиме debug.
|
||
В лог заносятся только основные события, ведущие к занесению хоста в лист.
|
||
По логу можно понять как избежать ложных срабатываний и подходит ли вообще вам этот режим.
|
||
|
||
Можно использовать один `autohostlist` с множеством процессов. Все процессы проверяют время модификации файла.
|
||
Если файл был изменен в другом процессе, происходит его перечитывание.
|
||
Все процессы должны работать под одним uid, чтобы были права доступа на файл.
|
||
|
||
Скрипты `zapret` ведут `autohostlist` в `ipset/zapret-hosts-auto.txt`.
|
||
`install_easy.sh` при апгрейде `zapret` сохраняет этот файл.
|
||
Режим `autohostlist` включает в себя режим `hostlist`.
|
||
Можно вести `ipset/zapret-hosts-user.txt`, `ipset/zapret-hosts-user-exclude.txt`.
|
||
|
||
## Проверка провайдера
|
||
|
||
Перед настройкой нужно провести исследование какую бяку устроил вам ваш провайдер.
|
||
|
||
Нужно выяснить не подменяет ли он DNS и какой метод обхода DPI работает.
|
||
В этом вам поможет скрипт `blockcheck.sh`.
|
||
|
||
Если 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`.
|
||
Еще один эффективный вариант - использовать ресолвер от yandex 77.88.8.88 на нестандартном порту 1253.
|
||
Многие провайдеры не анализируют обращения к DNS на нестандартных портах.
|
||
`blockcheck` если видит подмену DNS автоматически переключается на DoH сервера.
|
||
|
||
Следует прогнать `blockcheck` по нескольким заблокированным сайтам и выявить общий характер блокировок.
|
||
Разные сайты могут быть заблокированы по-разному, нужно искать такую технику, которая работает на большинстве.
|
||
Чтобы записать вывод `blockcheck.sh` в файл, выполните: `./blockcheck.sh | tee /tmp/blockcheck.txt`.
|
||
|
||
Проанализируйте какие методы дурения DPI работают, в соответствии с ними настройте `/opt/zapret/config`.
|
||
|
||
Имейте в виду, что у провайдеров может быть несколько DPI или запросы могут идти через разные каналы
|
||
по методу балансировки нагрузки. Балансировка может означать, что на разных ветках разные DPI или
|
||
они находятся на разных хопах. Такая ситуация может выражаться в нестабильности работы обхода.
|
||
Дернули несколько раз curl. То работает, то connection reset или редирект. `blockcheck.sh` выдает
|
||
странноватые результаты. То split работает на 2-м. хопе, то на 4-м. Достоверность результата вызывает сомнения.
|
||
В этом случае задайте несколько повторов одного и того же теста. Тест будет считаться успешным только,
|
||
если все попытки пройдут успешно.
|
||
|
||
При использовании `autottl` следует протестировать как можно больше разных доменов. Эта техника
|
||
может на одних провайдерах работать стабильно, на других потребуется выяснить при каких параметрах
|
||
она стабильна, на третьих полный хаос, и проще отказаться.
|
||
|
||
`Blockcheck` имеет 3 уровня сканирования.
|
||
* `quick` - максимально быстро найти хоть что-то работающее.
|
||
* `standard` дает возможность провести исследование как и на что реагирует DPI в плане методов обхода.
|
||
* `force` дает максимум проверок даже в случаях, когда ресурс работает без обхода или с более простыми стратегиями.
|
||
|
||
Есть ряд других параметров, которые не будут спрашиваться в диалоге, но которые можно переопределить через
|
||
переменные.
|
||
|
||
```
|
||
CURL - замена программы curl
|
||
CURL_MAX_TIME - время таймаута curl в секундах
|
||
CURL_MAX_TIME_QUIC - время таймаута curl для quic. если не задано, используется значение CURL_MAX_TIME
|
||
CURL_CMD=1 - показывать команды curl
|
||
CURL_OPT - дополнительные параметры curl. `-k` - игнор сертификатов. `-v` - подробный вывод протокола
|
||
DOMAINS - список тестируемых доменов через пробел
|
||
HTTP_PORT, HTTPS_PORT, QUIC_PORT - номера портов для соответствующих протоколов
|
||
SKIP_DNSCHECK=1 - отказ от проверки DNS
|
||
SKIP_TPWS=1 - отказ от тестов tpws
|
||
SKIP_PKTWS=1 - отказ от тестов nfqws/dvtws/winws
|
||
PKTWS_EXTRA, TPWS_EXTRA - дополнительные параметры nfqws/dvtws/winws и tpws
|
||
PKTWS_EXTRA_1 .. PKTWS_EXTRA_9, TPWS_EXTRA_1 .. TPWS_EXTRA_9 - отдельно дополнительные параметры, содержащие пробелы
|
||
SECURE_DNS=0|1 - принудительно выключить или включить DoH
|
||
DOH_SERVERS - список URL DoH через пробел для автоматического выбора работающего сервера
|
||
DOH_SERVER - конкретный DoH URL, отказ от поиска
|
||
```
|
||
|
||
Пример запуска с переменными:\
|
||
`SECURE_DNS=1 SKIP_TPWS=1 CURL_MAX_TIME=1 CURL=/tmp/curl ./blockcheck.sh`
|
||
|
||
**СКАН ПОРТОВ**\
|
||
Если в системе присутствует совместимый `netcat` (ncat от nmap или openbsd ncat. в openwrt по умолчанию нет),
|
||
то выполняется сканирование портов http или https всех IP адресов домена.
|
||
Если ни один IP не отвечает, то результат очевиден. Можно останавливать сканирование.
|
||
Автоматически оно не остановится, потому что netcat-ы недостаточно подробно информируют о причинах ошибки.
|
||
Если доступна только часть IP, то можно ожидать хаотичных сбоев, т.к. подключение идет к случайному адресу
|
||
из списка.
|
||
|
||
**ПРОВЕРКА НА ЧАСТИЧНЫЙ IP block**\
|
||
Под частичным блоком подразумевается ситуация, когда коннект на порты есть, но по определенному транспортному
|
||
или прикладному протоколу всегда идет реакция DPI вне зависимости от запрашиваемого домена.
|
||
Эта проверка так же не выдаст автоматического вердикта/решения, потому что может быть очень много вариаций.
|
||
Вместо этого анализ происходящего возложен на самого пользователя или тех, кто будет читать лог.
|
||
Суть этой проверки в попытке дернуть неблокированный IP с блокированным доменом и наоборот, анализируя
|
||
при этом реакцию DPI. Реакция DPI обычно проявляется в виде таймаута (зависание запроса), connection reset
|
||
или http redirect на заглушку. Любой другой вариант скорее всего говорит об отсутствии реакции DPI.
|
||
В частности, любые http коды, кроме редиректа, ведущего именно на заглушку, а не куда-то еще.
|
||
На TLS - ошибки handshake без задержек.
|
||
Ошибка сертификата может говорить как о реакции DPI с MiTM атакой (подмена сертификата), так и
|
||
о том, что принимающий сервер неблокированного домена все равно принимает ваш TLS `handshake` с чужим доменом,
|
||
пытаясь при этом выдать сертификат без запрошенного домена. Требуется дополнительный анализ.
|
||
Если на заблокированный домен есть реакция на всех IP адресах, значит есть блокировка по домену.
|
||
Если на неблокированный домен есть реакция на IP адресах блокированного домена, значит имеет место блок по IP.
|
||
Соответственно, если есть и то, и другое, значит есть и блок по IP, и блок по домену.
|
||
Неблокированный домен первым делом проверяется на доступность на оригинальном адресе.
|
||
При недоступности тест отменяется, поскольку он будет неинформативен.
|
||
|
||
Если выяснено, что есть частичный блок по IP на DPI, то скорее всего все остальные тесты будут провалены
|
||
вне зависимости от стратегий обхода. Но бывают и некоторые исключения. Например, пробитие через `ipv6
|
||
option headers`. Или сделать так, чтобы он не мог распознать протокол прикладного уровня.
|
||
Дальнейшие тесты могут быть не лишены смысла.
|
||
|
||
**ПРИМЕРЫ БЛОКИРОВКИ ТОЛЬКО ПО ДОМЕНУ БЕЗ БЛОКА ПО IP**
|
||
|
||
```
|
||
> testing iana.org on it's original
|
||
!!!!! AVAILABLE !!!!!
|
||
> testing rutracker.org on 192.0.43.8 (iana.org)
|
||
curl: (28) Operation timed out after 1002 milliseconds with 0 bytes received
|
||
> testing iana.org on 172.67.182.196 (rutracker.org)
|
||
HTTP/1.1 409 Conflict
|
||
> testing iana.org on 104.21.32.39 (rutracker.org)
|
||
HTTP/1.1 409 Conflict
|
||
|
||
> testing iana.org on it's original ip
|
||
!!!!! AVAILABLE !!!!!
|
||
> testing rutracker.org on 192.0.43.8 (iana.org)
|
||
curl: (28) Connection timed out after 1001 milliseconds
|
||
> testing iana.org on 172.67.182.196 (rutracker.org)
|
||
curl: (35) OpenSSL/3.2.1: error:0A000410:SSL routines::ssl/tls alert handshake failure
|
||
> testing iana.org on 104.21.32.39 (rutracker.org)
|
||
curl: (35) OpenSSL/3.2.1: error:0A000410:SSL routines::ssl/tls alert handshake failure
|
||
|
||
> testing iana.org on it's original ip
|
||
!!!!! AVAILABLE !!!!!
|
||
> testing rutracker.org on 192.0.43.8 (iana.org)
|
||
HTTP/1.1 307 Temporary Redirect
|
||
Location: https://www.gblnet.net/blocked.php
|
||
> testing iana.org on 172.67.182.196 (rutracker.org)
|
||
HTTP/1.1 409 Conflict
|
||
> testing iana.org on 104.21.32.39 (rutracker.org)
|
||
HTTP/1.1 409 Conflict
|
||
|
||
> testing iana.org on it's original ip
|
||
!!!!! AVAILABLE !!!!!
|
||
> testing rutracker.org on 192.0.43.8 (iana.org)
|
||
curl: (35) Recv failure: Connection reset by peer
|
||
> testing iana.org on 172.67.182.196 (rutracker.org)
|
||
curl: (35) OpenSSL/3.2.1: error:0A000410:SSL routines::ssl/tls alert handshake failure
|
||
> testing iana.org on 104.21.32.39 (rutracker.org)
|
||
curl: (35) OpenSSL/3.2.1: error:0A000410:SSL routines::ssl/tls alert handshake failure
|
||
```
|
||
|
||
|
||
**ПРИМЕР ПОЛНОГО IP БЛОКА ИЛИ БЛОКА TCP ПОРТА ПРИ ОТСУТСТВИИ БЛОКА ПО ДОМЕНУ**
|
||
|
||
```
|
||
* port block tests ipv4 startmail.com:80
|
||
ncat -z -w 1 145.131.90.136 80
|
||
145.131.90.136 does not connect. netcat code 1
|
||
ncat -z -w 1 145.131.90.152 80
|
||
145.131.90.152 does not connect. netcat code 1
|
||
|
||
* curl_test_http ipv4 startmail.com
|
||
- checking without DPI bypass
|
||
curl: (28) Connection timed out after 2002 milliseconds
|
||
UNAVAILABLE code=28
|
||
|
||
- IP block tests (requires manual interpretation)
|
||
|
||
> testing iana.org on it's original ip
|
||
!!!!! AVAILABLE !!!!!
|
||
> testing startmail.com on 192.0.43.8 (iana.org)
|
||
HTTP/1.1 302 Found
|
||
Location: https://www.iana.org/
|
||
> testing iana.org on 145.131.90.136 (startmail.com)
|
||
curl: (28) Connection timed out after 2002 milliseconds
|
||
> testing iana.org on 145.131.90.152 (startmail.com)
|
||
curl: (28) Connection timed out after 2002 milliseconds
|
||
```
|
||
|
||
## Выбор параметров
|
||
|
||
Файл `/opt/zapret/config` используется различными компонентами системы и содержит основные настройки.
|
||
Его нужно просмотреть и при необходимости отредактировать.
|
||
|
||
На linux системах можно выбрать использовать `iptables` или `nftables`.
|
||
По умолчанию на традиционных linux выбирается `nftables`, если установлен nft.
|
||
На openwrt по умолчанию выбирается `nftables` на новых версиях с firewall4.
|
||
|
||
`FWTYPE=iptables`
|
||
|
||
На `nftables` можно отключить стандартную схему перехвата трафика после NAT и перейти на перехват до NAT.
|
||
Это сделает невозможным применение некоторых методов дурения на проходящем трафике как в случае с `iptables`.
|
||
nfqws начнет получать адреса пакетов из локальной сети и отображать их в логах.
|
||
|
||
`POSTNAT=0`
|
||
|
||
Существует 3 стандартных опции запуска, настраиваемых раздельно и независимо: `tpws-socks`, `tpws`, `nfqws`.
|
||
Их можно использовать как по отдельности, так и вместе. Например, вам надо сделать комбинацию
|
||
из методов, доступных только в `tpws` и только в `nfqws`. Их можно задействовать вместе.
|
||
`tpws` будет прозрачно локализовывать трафик на системе и применять свое дурение, `nfqws` будет дурить трафик,
|
||
исходящий с самой системы после обработки на `tpws`.
|
||
А можно на эту же систему повесить без параметров socks proxy, чтобы получать доступ к обходу блокировок через прокси.
|
||
Таким образом, все 3 режима вполне могут задействоваться вместе.
|
||
Так же безусловно и независимо, в добавок к стандартным опциям, применяются все custom скрипты в `init.d/{sysv,openwrt,macos}/custom.d`.
|
||
|
||
Однако, при комбинировании tpws и nfqws с пересечением по L3/L4 протоколам не все так просто , как может показаться на первый взгляд.
|
||
Первым всегда работает tpws, за ним - nfqws. На nfqws попадает уже "задуренный" трафик от tpws.
|
||
Получается, что дурилка дурит дурилку, и дурилка не срабатывает, потому что ее задурили.
|
||
Вот такой веселый момент. nfqws перестает распознавать протоколы и применять методы.
|
||
Некоторые методы дурения от tpws nfqws в состоянии распознать и отработать корректно, но большинство - нет.
|
||
Решение - использование `--dpi-desync-any-protocol` в nfqws и работа как с неизвестным протоколом.
|
||
Комбинирование tpws и nfqws является продвинутым вариантом, требующим глубокого понимания происходящего.
|
||
Очень желательно проанализировать действия nfqws по `--debug` логу. Все ли так, как вы задумали.
|
||
|
||
Одновременное использование tpws и nfqws без пересечения по L3/L4 (то есть nfqws - udp, tpws - tcp или nfqws - port 443, tpws - port 80 или nfqws - ipv4, tpws - ipv6) проблем не представляет.
|
||
|
||
`tpws-socks` требует настройки параметров `tpws`, но не требует перехвата трафика.
|
||
Остальные опции требуют раздельно настройки перехвата трафика и опции самих демонов.
|
||
Каждая опция предполагает запуск одного инстанса соответствующего демона. Все различия методов дурения
|
||
для `http`, `https`, `quic` и т.д. должны быть отражены через схему мультистратегий.
|
||
В этом смысле настройка похожа на вариант `winws` на Windows, а перенос конфигов не должен представлять больших сложностей.
|
||
Основное правило настройки перехвата - перехватывайте только необходимый минимум.
|
||
Любой перехват лишнего - это бессмысленная нагрузка на вашу систему.
|
||
Опции демонов `--ipset` использовать запрещено. Это сделано намеренно и искусственно, чтобы не поощрять простой и
|
||
работающий, но неэффективный метод на *nix системах. Используйте `ipset`-ы режима ядра.
|
||
При необходимости пишите и задействуйте `custom scripts`.
|
||
Настройки демонов можно для удобства писать на нескольких строках, используя двойные или одинарные кавычки.
|
||
Чтобы задействовать стандартные обновляемые хост-листы из `ipset`, используйте маркер <HOSTLIST>.
|
||
Он будет заменен на параметры, соответствующие режиму MODE_FILTER, и будут подставлены реально существующие файлы.
|
||
Если MODE_FILTER не предполагает стандартного хостлиста, <HOSTLIST> будет заменен на пустую строку.
|
||
Стандартные хостлисты следует вставлять в финальных стратегиях (стратегиях по умолчанию), закрывающих цепочки по
|
||
группе параметров фильтра. Таких мест может быть несколько.
|
||
Не нужно использовать <HOSTLIST> в узких специализациях и в тех профилях, по которым точно не будет проходить
|
||
трафик с известными протоколами, откуда поддерживается извлечение имени хоста (`http`, `tls`, `quic`).
|
||
<HOSTLIST_NOAUTO> - это вариация, при которой стандартный автолист используется как обычный.
|
||
То есть на этом профиле не происходит автоматическое добавление заблокированных доменов.
|
||
Но если на другом профиле что-то будет добавлено, то этот профиль примет изменения автоматически.
|
||
|
||
***Включение стандартной опции tpws в режиме socks***\
|
||
`TPWS_SOCKS_ENABLE=0`
|
||
|
||
***На каком порту будет слушать tpws socks. прослушивается только localhost и LAN***\
|
||
`TPPORT_SOCKS=987`
|
||
|
||
***Параметры tpws для режима socks***
|
||
```
|
||
TPWS_SOCKS_OPT="
|
||
--filter-tcp=80 --methodeol <HOSTLIST> --new
|
||
--filter-tcp=443 --split-pos=1,midsld --disorder <HOSTLIST>"
|
||
```
|
||
|
||
***Включение стандартной опции tpws в прозрачном режиме***\
|
||
`TPWS_ENABLE=0`
|
||
|
||
***Какие tcp порты следует перенаправлять на tpws***\
|
||
`TPWS_PORTS=80,443`
|
||
|
||
***Параметры tpws для прозрачного режима***
|
||
```
|
||
TPWS_OPT="
|
||
--filter-tcp=80 --methodeol <HOSTLIST> --new
|
||
--filter-tcp=443 --split-pos=1,midsld --disorder <HOSTLIST>"
|
||
```
|
||
|
||
***Включение стандартной опции nfqws***\
|
||
`NFQWS_ENABLE=0`
|
||
|
||
***Какие tcp и udp порты следует перенаправлять на nfqws с использованием connbytes ограничителя***
|
||
|
||
connbytes позволяет из каждого соединения перенаправить только заданное количество начальных пакетов по каждому направлению - на вход и на выход.
|
||
Это более эффективная kernel-mode замена параметра nfqws `--dpi-desync-cutoff=nX`.
|
||
```
|
||
NFQWS_PORTS_TCP=80,443
|
||
NFQWS_PORTS_UDP=443
|
||
```
|
||
|
||
***Сколько начальных входящих и исходящих пакетов нужно перенаправлять на nfqws по каждому направлению***
|
||
```
|
||
NFQWS_TCP_PKT_OUT=$((6+$AUTOHOSTLIST_RETRANS_THRESHOLD))
|
||
NFQWS_TCP_PKT_IN=3
|
||
NFQWS_UDP_PKT_OUT=$((6+$AUTOHOSTLIST_RETRANS_THRESHOLD))
|
||
NFQWS_UDP_PKT_IN=0
|
||
```
|
||
|
||
***Задать порты для перенаправления на nfqws без connbytes ограничителя***\
|
||
Есть трафик, исходящий сеанс для которого необходимо перенаправлять весь без ограничителей.
|
||
Типичное применение - поддержка http keepalives на stateless DPI.
|
||
Это существенно нагружает процессор. Использовать только если понимаете зачем. Чаще всего это не нужно.
|
||
Входящий трафик ограничивается по connbytes через параметры PKT_IN.
|
||
Если указываете здесь какие-то порты, желательно их убрать из версии с connbytes ограничителем
|
||
```
|
||
NFQWS_PORTS_TCP_KEEPALIVE=80
|
||
NFQWS_PORTS_UDP_KEEPALIVE=
|
||
```
|
||
|
||
***Параметры nfqws***
|
||
```
|
||
NFQWS_OPT="
|
||
--filter-tcp=80 --dpi-desync=fake,multisplit --dpi-desync-split-pos=method+2 --dpi-desync-fooling=md5sig <HOSTLIST> --new
|
||
--filter-tcp=443 --dpi-desync=fake,multidisorder --dpi-desync-split-pos=1,midsld --dpi-desync-fooling=badseq,md5sig <HOSTLIST> --new
|
||
--filter-udp=443 --dpi-desync=fake --dpi-desync-repeats=6 <HOSTLIST_NOAUTO>
|
||
```
|
||
|
||
***Режим фильтрации хостов:***
|
||
```
|
||
none - применять дурение ко всем хостам
|
||
ipset - ограничить дурение ipset-ом zapret/zapret6
|
||
hostlist - ограничить дурение списком хостов из файла
|
||
autohostlist - режим hostlist + распознавание блокировок и ведение автоматического листа
|
||
```
|
||
`MODE_FILTER=none`
|
||
|
||
***Настройка системы управления выборочным traffic offload (только если поддерживается)***
|
||
```
|
||
donttouch: выборочное управление отключено, используется системная настройка, простой инсталлятор выключает системную настройку, если она не совместима с выбранным режимом
|
||
none: выборочное управление отключено, простой инсталлятор выключает системную настройку
|
||
software: выборочное управление включено в режиме software, простой инсталлятор выключает системную настройку
|
||
hardware: выборочное управление включено в режиме hardware, простой инсталлятор выключает системную настройку
|
||
```
|
||
`FLOWOFFLOAD=donttouch`
|
||
|
||
Параметр 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-ов и nfset-ов***
|
||
|
||
```
|
||
SET_MAXELEM=262144
|
||
IPSET_OPT="hashsize 262144 maxelem 2097152"
|
||
```
|
||
|
||
Хук, позволяющий внести ip адреса динамически. $1 = имя таблицы\
|
||
Адреса выводятся в stdout. В случае nfset автоматически решается проблема возможного пересечения интервалов.\
|
||
`IPSET_HOOK="/etc/zapret.ipset.hook"`
|
||
|
||
***ПРО РУГАНЬ в 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"
|
||
```
|
||
|
||
***Настройка режима autohostlist.***
|
||
|
||
При увеличении AUTOHOSTLIST_RETRANS_THRESHOLD и использовании nfqws следует пересмотреть значения параметров
|
||
NFQWS_TCP_PKT_OUT и NFQWS_UDP_PKT_OUT. Все ретрансмиссии должны быть получены nfqws, иначе триггер "зависание запроса" не сработает.
|
||
|
||
```
|
||
AUTOHOSTLIST_RETRANS_THRESHOLD=3
|
||
AUTOHOSTLIST_FAIL_THRESHOLD=3
|
||
AUTOHOSTLIST_FAIL_TIME=60
|
||
AUTOHOSTLIST_DEBUG=0
|
||
```
|
||
|
||
***Включить или выключить сжатие больших листов в скриптах ipset/\*.sh.***
|
||
|
||
`GZIP_LISTS=1`
|
||
|
||
***Команда для перезагрузки ip таблиц фаервола.***
|
||
|
||
Если не указано или пустое, выбирается автоматически ipset или ipfw при их наличии.
|
||
На BSD системах с PF нет автоматической загрузки. Там нужно указать команду явно: `pfctl -f /etc/pf.conf`
|
||
На более новых pfctl (есть в новых FreeBSD, нет в OpenBSD 6.8) можно дать команду загрузки только таблиц: `pfctl -Tl -f /etc/pf.conf`
|
||
"-" означает отключение загрузки листов даже при наличии поддерживаемого backend.
|
||
```
|
||
LISTS_RELOAD="pfctl -f /etc/pf.conf"
|
||
LISTS_RELOAD=-
|
||
```
|
||
|
||
В openwrt существует сеть по умолчанию 'lan'. Только трафик с этой сети будет перенаправлен на tpws.
|
||
Но возможно задать другие сети или список сетей:\
|
||
`OPENWRT_LAN="lan lan2 lan3"`
|
||
|
||
В openwrt в качестве wan берутся интерфейсы, имеющие default route. Отдельно для ipv4 и ipv6.
|
||
Это можно переопределить:
|
||
```
|
||
OPENWRT_WAN4="wan4 vpn"
|
||
OPENWRT_WAN6="wan6 vpn6"
|
||
```
|
||
|
||
Параметр INIT_APPLY_FW=1 разрешает init скрипту самостоятельно применять правила iptables.\
|
||
При иных значениях или если параметр закомментирован, правила применены не будут.\
|
||
Это полезно, если у вас есть система управления фаерволом, в настройки которой и следует прикрутить правила.\
|
||
На openwrt неприменимо при использовании firewall3+iptables.
|
||
|
||
***Следующие настройки не актуальны для openwrt:***
|
||
|
||
Если ваша система работает как роутер, то нужно вписать названия внутренних и внешних интерфейсов:
|
||
```
|
||
IFACE_LAN=eth0
|
||
IFACE_WAN=eth1
|
||
IFACE_WAN6="henet ipsec0"
|
||
```
|
||
Несколько интерфейсов могут быть вписаны через пробел.
|
||
Если IFACE_WAN6 не задан, то берется значение IFACE_WAN.
|
||
|
||
> [!IMPORTANT]
|
||
> Настройка маршрутизации, маскарада и т.д. не входит в задачу zapret.
|
||
> Включаются только режимы, обеспечивающие перехват транзитного трафика.
|
||
> Возможно определить несколько интерфейсов следующим образом:
|
||
|
||
`IFACE_LAN="eth0 eth1 eth2"`
|
||
|
||
## Прикручивание к системе управления фаерволом или своей системе запуска
|
||
|
||
Если вы используете какую-то систему управления фаерволом, то она может вступать в конфликт
|
||
с имеющимся скриптом запуска. При повторном применении правил она могла бы поломать настройки 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 restart_fw
|
||
```
|
||
|
||
_А так можно запустить или остановить демоны отдельно от фаервола:_
|
||
|
||
```
|
||
/opt/zapret/init.d/sysv/zapret start_daemons
|
||
/opt/zapret/init.d/sysv/zapret stop_daemons
|
||
/opt/zapret/init.d/sysv/zapret restart_daemons
|
||
```
|
||
|
||
`nftables` сводят практически на нет конфликты между разными системами управления, поскольку позволяют
|
||
использовать независимые таблицы и хуки. Используется отдельная nf-таблица "zapret".
|
||
Если ваша система ее не будет трогать, скорее всего все будет нормально.
|
||
|
||
_Для `nftables` предусмотрено несколько дополнительных вызовов:_
|
||
|
||
Посмотреть set-ы интерфейсов, относящихся к lan, wan и wan6. По ним идет завертывание трафика.
|
||
А так же таблицу flow table с именами интерфейсов ingress hook.\
|
||
`/opt/zapret/init.d/sysv/zapret list_ifsets`
|
||
|
||
Обновить set-ы интерфейсов, относящихся к lan, wan и wan6.
|
||
Для традиционных linux список интерфейсов берется из переменных конфига IFACE_LAN, IFACE_WAN.
|
||
Для openwrt определяется автоматически. Множество lanif может быть расширено параметром OPENWRT_LAN.
|
||
Все интерфейсы lan и wan так же добавляются в ingress hook от flow table.\
|
||
`/opt/zapret/init.d/sysv/zapret reload_ifsets`
|
||
|
||
Просмотр таблицы без содержимого set-ов. Вызывает `nft -t list table inet zapret`\
|
||
`/opt/zapret/init.d/sysv/zapret list_table`
|
||
|
||
_Так же возможно прицепиться своим скриптом к любой стадии применения и снятия фаервола со стороны zapret скриптов:_
|
||
```
|
||
INIT_FW_PRE_UP_HOOK="/etc/firewall.zapret.hook.pre_up"
|
||
INIT_FW_POST_UP_HOOK="/etc/firewall.zapret.hook.post_up"
|
||
INIT_FW_PRE_DOWN_HOOK="/etc/firewall.zapret.hook.pre_down"
|
||
INIT_FW_POST_DOWN_HOOK="/etc/firewall.zapret.hook.post_down"
|
||
```
|
||
|
||
Эти настройки доступны в config.
|
||
Может быть полезно, если вам нужно использовать nftables set-ы, например `ipban`/`ipban6`.
|
||
nfset-ы принадлежат только одной таблице, следовательно вам придется писать правила для таблицы zapret,
|
||
а значит нужно синхронизироваться с применением/снятием правил со стороны zapret скриптов.
|
||
|
||
## Вариант custom
|
||
|
||
custom скрипты - это маленькие shell программы, управляющие нестандартными режимами применения zapret
|
||
или частными случаями, которые не могут быть интегрированы в основную часть без загромождения и замусоривания кода.
|
||
Для применеия custom следует помещать файлы в следующие директории в зависимости от вашей системы:
|
||
```
|
||
/opt/zapret/init.d/sysv/custom.d
|
||
/opt/zapret/init.d/openwrt/custom.d
|
||
/opt/zapret/init.d/macos/custom.d
|
||
```
|
||
Директория будет просканирована в алфавитном порядке, и каждый скрипт будет применен.
|
||
Рядом имеется `custom.d.examples`. Это готовые скрипты, которые можно копировать в `custom.d`.
|
||
Их можно взять за основу для написания собственных.
|
||
|
||
***Для linux пишется код в функции***
|
||
```
|
||
zapret_custom_daemons
|
||
zapret_custom_firewall
|
||
zapret_custom_firewall_nft
|
||
zapret_custom_firewall_nft_flush
|
||
```
|
||
|
||
***Для macos***
|
||
```
|
||
zapret_custom_daemons
|
||
zapret_custom_firewall_v4
|
||
zapret_custom_firewall_v6
|
||
```
|
||
|
||
zapret_custom_daemons поднимает демоны `nfqws`/`tpws` в нужном вам количестве и с нужными вам параметрами.
|
||
Для систем традиционного linux (sysv) и MacOS в первом параметре передается код операции: 1 = запуск, 0 = останов.
|
||
Для openwrt логика останова отсутствует за ненадобностью.
|
||
Схема запуска демонов в openwrt отличается - используется procd.
|
||
|
||
zapret_custom_firewall поднимает и убирает правила `iptables`.
|
||
В первом параметре передается код операции: 1 = запуск, 0 = останов.
|
||
|
||
zapret_custom_firewall_nft поднимает правила nftables.
|
||
Логика останова отсутствует за ненадобностью. Стандартные цепочки zapret удаляются автоматически.
|
||
Однако, sets и правила из ваших собственных цепочек не удаляются.
|
||
Их нужно подчистить в zapret_custom_firewall_nft_flush.
|
||
Если set-ов и собственных цепочек у вас нет, функцию можно не определять или оставить пустой.
|
||
|
||
Если вам не нужны iptables или nftables - можете не писать соответствующую функцию.
|
||
|
||
В linux можно использовать локальные переменные `FW_EXTRA_PRE` и `FW_EXTRA_POST`.\
|
||
`FW_EXTRA_PRE` добавляет код к правилам ip/nf tables до кода, генерируемого функциями-хелперами.\
|
||
`FW_EXTRA_POST` добавляет код после.
|
||
|
||
В linux функции-хелперы добавляют правило в начало цепочек, то есть перед уже имеющимися.
|
||
Поэтому специализации должны идти после более общих вариантов.
|
||
Для macos правило обратное. Там правила добавляются в конец.
|
||
По этой же причине фаервол в Linux сначала применяется в стандартном режиме, потом custom,
|
||
а в MacOS сначала custom, потом стандартный режим.
|
||
|
||
В macos firewall-функции ничего сами никуда не заносят. Их задача - лишь выдать текст в stdout,
|
||
содержащий правила для pf-якоря. Остальное сделает обертка.
|
||
|
||
Особо обратите внимание на номер демона в функциях `run_daemon` и `do_daemon`, номера портов `tpws`
|
||
и очередей `nfqueue`.
|
||
Они должны быть уникальными во всех скриптах. При накладке будет ошибка.
|
||
Поэтому используйте функции динамического получения этих значений из пула.
|
||
|
||
`custom` скрипты могут использовать переменные из `config`. Можно помещать в `config` свои переменные
|
||
и задействовать их в скриптах.
|
||
Можно использовать функции-хелперы. Они являются частью общего пространства функций shell.
|
||
Полезные функции можно взять из примеров скриптов. Так же смотрите `common/*.sh`.
|
||
Используя хелпер функции, вы избавитесь от необходимости учитывать все возможные случаи
|
||
типа наличия/отсутствия ipv6, является ли система роутером, имена интерфейсов, ...Хелперы это учитывают. Вам нужно сосредоточиться лишь на фильтрах `{ip,nf}tables` и параметрах демонов.
|
||
|
||
## Простая установка
|
||
|
||
`install_easy.sh` автоматизирует ручные варианты процедур установки.
|
||
Он поддерживает OpenWRT, linux системы на базе systemd или openrc и MacOS.
|
||
|
||
Для более гибкой настройки перед запуском инсталлятора следует выполнить раздел "Выбор параметров".
|
||
|
||
Если система запуска поддерживается, но используется не поддерживаемый инсталлятором менеджер пакетов
|
||
или названия пакетов не соответствуют прописанным в инсталлятор, пакеты нужно установить вручную.
|
||
Всегда требуется curl. `ipset` - только для режима `iptables`, для `nftables` - не нужен.
|
||
|
||
Для совсем обрезанных дистрибутивов (alpine) требуется отдельно установить `iptables` и `ip6tables`, либо `nftables`.
|
||
|
||
В комплекте идут статические бинарники для большинства архитектур. Какой-то из них подойдет
|
||
с вероятностью 99%. Но если у вас экзотическая система, инсталлятор попробует собрать бинарники сам
|
||
через make. Для этого нужны gcc, make и необходимые **-dev** пакеты. Можно форсировать режим
|
||
компиляции следующим вызовом:
|
||
|
||
`install_easy.sh make`
|
||
|
||
Под openwrt все уже сразу готово для использования системы в качестве роутера.
|
||
Имена интерфейсов WAN и LAN известны из настроек системы.
|
||
Под другими системами роутер вы настраиваете самостоятельно. Инсталлятор в это не вмешивается.
|
||
инсталлятор в зависимости от выбранного режима может спросить LAN и WAN интерфейсы.
|
||
Нужно понимать, что заворот проходящего трафика на `tpws` в прозрачном режиме происходит до выполнения маршрутизации,
|
||
следовательно возможна фильтрация по LAN и невозможна по WAN.
|
||
Решение о завороте на `tpws` локального исходящего трафика принимается после выполнения маршрутизации,
|
||
следовательно ситуация обратная: LAN не имеет смысла, фильтрация по WAN возможна.
|
||
Заворот на `nfqws` происходит всегда после маршрутизации, поэтому к нему применима только фильтрация по WAN.
|
||
Возможность прохождения трафика в том или ином направлении настраивается вами в процессе конфигурации роутера.
|
||
|
||
Деинсталляция выполняется через `uninstall_easy.sh`. После выполнения деинсталляции можно удалить каталог `/opt/zapret`.
|
||
|
||
|
||
## Простая установка на openwrt
|
||
|
||
Работает только если у вас на роутере достаточно места.
|
||
|
||
Копируем zapret на роутер в `/tmp`.
|
||
|
||
Запускаем установщик:\
|
||
`sh /tmp/zapret/install_easy.sh`
|
||
|
||
Он скопирует в `/opt/zapret` только необходимый минимум файлов.
|
||
|
||
После успешной установки можно удалить zapret из tmp для освобождения RAM:\
|
||
`rm -r /tmp/zapret`
|
||
|
||
Для более гибкой настройки перед запуском инсталлятора следует выполнить раздел "Выбор параметров".
|
||
|
||
Система простой инсталяции заточена на любое умышленное или неумышленное изменение прав доступа на файлы.
|
||
Устойчива к репаку под windows. После копирования в `/opt` права будут принудительно восстановлены.
|
||
|
||
|
||
## Установка на openwrt в режиме острой нехватки места на диске
|
||
|
||
Требуется около 120-200 кб на диске. Придется отказаться от всего, кроме `tpws`.
|
||
|
||
**Инструкция для openwrt 22 и выше с nftables**
|
||
|
||
Никаких зависимостей устанавливать не нужно.
|
||
|
||
***Установка:***
|
||
|
||
1) Скопируйте все из `init.d/openwrt-minimal/tpws/*` в корень openwrt.
|
||
2) Скопируйте бинарник `tpws` подходящей архитектуры в `/usr/bin/tpws`.
|
||
3) Установите права на файлы: `chmod 755 /etc/init.d/tpws /usr/bin/tpws`
|
||
4) Отредактируйте `/etc/config/tpws`
|
||
* Если не нужен ipv6, отредактируйте `/etc/nftables.d/90-tpws.nft` и закомментируйте строки с редиректом ipv6.
|
||
5) `/etc/init.d/tpws enable`
|
||
6) `/etc/init.d/tpws start`
|
||
7) `fw4 restart`
|
||
|
||
***Полное удаление:***
|
||
|
||
1) `/etc/init.d/tpws disable`
|
||
2) `/etc/init.d/tpws stop`
|
||
3) `rm -f /etc/nftables.d/90-tpws.nft /etc/firewall.user /etc/init.d/tpws /usr/bin/tpws`
|
||
4) `fw4 restart`
|
||
|
||
**Инструкция для openwrt 21 и ниже с iptables**
|
||
|
||
***Установите зависимости:***
|
||
1) `opkg update`
|
||
2) `opkg install iptables-mod-extra`
|
||
* только для IPV6: `opkg install ip6tables-mod-nat`
|
||
|
||
Убедитесь, что в `/etc/firewall.user` нет ничего значимого.
|
||
Если есть - не следуйте слепо инструкции. Объедините код или создайте свой `firewall include` в `/etc/config/firewall`.
|
||
|
||
***Установка:***
|
||
|
||
1) Скопируйте все из `init.d/openwrt-minimal/tpws/*` в корень openwrt.
|
||
2) Скопируйте бинарник `tpws` подходящей архитектуры в `/usr/bin/tpws`.
|
||
3) Установите права на файлы: `chmod 755 /etc/init.d/tpws /usr/bin/tpws`
|
||
4) Отредактируйте `/etc/config/tpws`
|
||
* Если не нужен ipv6, отредактируйте /etc/firewall.user и установите там DISABLE_IPV6=1.
|
||
5) `/etc/init.d/tpws enable`
|
||
6) `/etc/init.d/tpws start`
|
||
7) `fw3 restart`
|
||
|
||
***Полное удаление:***
|
||
|
||
1) `/etc/init.d/tpws disable`
|
||
2) `/etc/init.d/tpws stop`
|
||
3) `rm -f /etc/nftables.d/90-tpws.nft /etc/firewall.user /etc/init.d/tpws`
|
||
4) `touch /etc/firewall.user`
|
||
5) `fw3 restart`
|
||
|
||
|
||
## Android
|
||
|
||
Без рута забудьте про nfqws и tpws в режиме transparent proxy. tpws будет работать только в режиме `--socks`.
|
||
|
||
Ядра Android имеют поддержку NFQUEUE. nfqws работает.
|
||
|
||
В стоковых ядрах нет поддержки ipset. В общем случае сложность задачи по поднятию ipset варьируется от
|
||
"не просто" до "почти невозможно". Если только вы не найдете готовое собранное ядро под ваш девайс.
|
||
|
||
tpws будет работать в любом случае, он не требует чего-либо особенного.
|
||
|
||
Хотя linux варианты под Android работают, рекомендуется использовать специально собранные под bionic бинарники.
|
||
У них не будет проблем с DNS, с локальным временем и именами юзеров и групп.\
|
||
Рекомендую использовать 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
|
||
|
||
`nfqws` может иметь такой глюк. При запуске с uid по умолчанию (0x7FFFFFFF) при условии работы на сотовом интерфейсе
|
||
и отключенном кабеле внешнего питания система может частично виснуть. Перестает работать тач и кнопки,
|
||
но анимация на экране может продолжаться. Если экран был погашен, то включить его кнопкой power невозможно.
|
||
Изменение UID на низкий (--uid 1 подойдет) позволяет решить эту проблему.
|
||
Глюк был замечен на android 8.1 на девайсе, основанном на платформе mediatek.
|
||
|
||
Ответ на вопрос куда поместить tpws на android без рута, чтобы потом его запускать из приложений.
|
||
Файл заливаем через adb shell в /data/local/tmp/, лучше всего в субфолдер.
|
||
```
|
||
mkdir /data/local/tmp/zapret
|
||
adb push tpws /data/local/tmp/zapret
|
||
chmod 755 /data/local/tmp/zapret /data/local/tmp/zapret/tpws
|
||
chcon u:object_r:system_file:s0 /data/local/tmp/zapret/tpws
|
||
```
|
||
Как найти стратегию обхода сотового оператора: проще всего раздать инет на комп с linux.
|
||
Можно записать live image linux на флэшку и загрузиться с нее или запустить виртуалку с linux
|
||
и пробросить в нее usb устройство от режима модема с телефона.
|
||
На компе с linux прогнать стандартную процедуру blockcheck. При переносе правил на телефон уменьшить TTL на 1,
|
||
если правила с TTL присутствуют в стратегии.
|
||
Можно развернуть rootfs какого-нибудь дистрибутива linux прямо на телефоне, имея рута.
|
||
Это лучше всего делать с компа через adb shell.
|
||
Если компа нет, то это единственный вариант, хотя и неудобный.
|
||
Подойдет что-то легковесное, например, alpine или даже openwrt.
|
||
Если это не эмулятор android, то универсальная архитектура - arm (любой вариант).
|
||
Если вы точно знаете, что ОС у вас 64-разрядная, то лучше вместо arm - aarch64.
|
||
|
||
```
|
||
mount --bind /dev /data/linux/dev
|
||
mount --bind /proc /data/linux/proc
|
||
mount --bind /sys /data/linux/sys
|
||
chroot /data/linux
|
||
```
|
||
|
||
Первым делом вам нужно будет один раз настроить DNS. Сам он не заведется.
|
||
|
||
`echo nameserver 1.1.1.1 >/etc/resolv.conf`
|
||
|
||
Далее нужно средствами пакетного менеджера установить iptables-legacy. Обязательно **НЕ** iptables-nft,
|
||
который, как правило, присутствует по умолчанию. В ядре android нет nftables.\
|
||
`ls -la $(which iptables)`\
|
||
Линк должен указывать на legacy вариант.
|
||
Если нет, значит устанавливайте нужные пакеты вашего дистрибутива, и убеждайтесь в правильности ссылок.\
|
||
`iptables -S`\
|
||
Так можно проверить, что ваш `iptables` увидел то, что туда насовал android. `iptables-nft` выдаст ошибку.
|
||
Далее качаем zapret в `/opt/zapret`. Обычные действия с `install_prereq.sh`, `install_bin.sh`, `blockcheck.sh`.
|
||
|
||
Учтите, что стратегии обхода сотового оператора и домашнего wifi вероятно будут разные.
|
||
Выделить сотового оператора легко через параметр iptables `-o <имя интерфейса>`. Имя может быть, например, `ccmni0`.
|
||
Его легко увидеть через `ifconfig`.
|
||
Wifi сеть - обычно `wlan0`.
|
||
|
||
Переключать blockcheck между оператором и wifi можно вместе со всем инетом - включив или выключив wifi.
|
||
Если найдете стратегию для wifi и впишите ее в автостарт, то при подключении к другому wifi
|
||
она может не сработать или вовсе что-то поломать, потому подумайте стоит ли.
|
||
Может быть лучше сделать скрипты типа "запустить обход домашнего wifi", "снять обход домашнего wifi",
|
||
и пользоваться ими по необходимости из терминала.
|
||
Но домашний wifi лучше все-же обходить на роутере.
|
||
|
||
|
||
## Мобильные модемы и роутеры huawei
|
||
|
||
Устройства типа E3372, E8372, E5770 разделяют общую идеологию построения системы.
|
||
Имеются 2 вычислительных ядра. Одно ядро выполняет vxworks, другое - linux.
|
||
На 4pda имеются модифицированные прошивки с telnet и adb. Их и нужно использовать.
|
||
|
||
Дальнейшие утверждения проверены на E8372. На других может быть аналогично или похоже.
|
||
Присутствуют дополнительные аппаратные блоки для offload-а сетевых функций.
|
||
Не весь трафик идет через linux. Исходящий трафик с самого модема проходит
|
||
цепочку OUTPUT нормально, на FORWARD =>wan часть пакетов выпадает из tcpdump.
|
||
|
||
tpws работает обычным образом.
|
||
|
||
`nfqueue` поломан, можно собрать фиксящий модуль https://github.com/im-0/unfuck-nfqueue-on-e3372h,
|
||
используя исходники с huawei open source. Исходники содержат тулчейн и полусобирающееся,
|
||
неактуальное ядро. Конфиг можно взять с рабочего модема из `/proc/config.gz`.
|
||
С помощью этих исходников умельцы могут собрать модуль `unfuck_nfqueue.ko`.
|
||
После его применения NFQUEUE и nfqws для arm работают нормально.
|
||
|
||
Чтобы избежать проблемы с offload-ом при использовании nfqws, следует комбинировать tpws в режиме tcp proxy и nfqws.
|
||
Правила NFQUEUE пишутся для цепочки OUTPUT.
|
||
connbytes придется опускать, поскольку модуля в ядре нет. Но это не смертельно.
|
||
|
||
Скрипт автозапуска - `/system/etc/autorun.sh`. Создайте свой скрипт настройки zapret,
|
||
запускайте из конца autorun.sh через "&". Скрипт должен в начале делать sleep 5, чтобы дождаться
|
||
поднятия сети и iptables от huawei.
|
||
|
||
> [!WARNING]
|
||
> На этом модеме происходят хаотические сбросы соединений tcp по непонятным причинам.
|
||
> Выглядит это так, если запускать curl с самого модема:
|
||
```
|
||
curl www.ru
|
||
curl: (7) Failed to connect to www.ru port 80: Host is unreachable
|
||
```
|
||
Возникает ошибка сокета EHOSTUNREACH (errno -113). То же самое видно в tpws.
|
||
В броузере не подгружаются части веб страниц, картинки, стили.
|
||
В tcpdump на внешнем интерфейсе eth_x виден только единственный и безответный SYN пакет, без сообщений ICMP.
|
||
ОС каким-то образом узнает о невозможности установить TCP соединение и выдает ошибку.
|
||
Если выполнять подключение с клиента, то SYN пропадают, соединение не устанавливается.
|
||
ОС клиента проводит ретрансмиссию, и с какого-то раза подключение удается.
|
||
Поэтому без tcp проксирования в этой ситуации сайты тупят, но загружаются, а с проксированием
|
||
подключение выполняется, но вскоре сбрасывается без каких-либо данных, и броузеры не пытаются установить
|
||
его заново. Поэтому качество броузинга с tpws может быть хуже, но дело не в tpws.
|
||
Частота сбросов заметно возрастает, если запущен торент клиент, имеется много tcp соединений.
|
||
Однако, причина не в переполнении таблицы conntrack. Увеличение лимитов и очистка conntrack не помогают.
|
||
Предположительно эта особенность связана с обработкой пакетов сброса соединения в hardware offload.
|
||
Точного ответа на вопрос у меня нет. Если вы знаете - поделитесь, пожалуйста.
|
||
Чтобы не ухудшать качество броузинга, можно фильтровать заворот на tpws по ip фильтру.
|
||
Поддержка ipset отсутствует. Значит, все, что можно сделать - создать индивидуальные правила
|
||
на небольшое количество хостов.
|
||
|
||
Некоторые наброски скриптов присутствуют в [files/huawei](./../files/huawei/). _Не готовое решение!_ Смотрите, изучайте, приспосабливайте.\
|
||
Здесь можно скачать готовые полезные статические бинарники для arm, включая curl : https://github.com/bol-van/bins
|
||
|
||
|
||
## FreeBSD, OpenBSD, MacOS
|
||
|
||
Описано в [документации BSD](./bsd.md)
|
||
|
||
## Windows
|
||
|
||
Описано в [документации Windows](./windows.md)
|
||
|
||
|
||
## Другие прошивки
|
||
|
||
Для статических бинариков не имеет значения на чем они запущены: PC, android, приставка, роутер, любой другой девайс.
|
||
Подойдет любая прошивка, дистрибутив linux. Статические бинарники запустятся на всем.
|
||
Им нужно только ядро с необходимыми опциями сборки или модулями.
|
||
Но кроме бинариков в проекте используются еще и скрипты, в которых задействуются некоторые
|
||
стандартные программы.
|
||
|
||
Основные причины почему нельзя просто так взять и установить эту систему на что угодно:
|
||
* отсутствие доступа к девайсу через shell
|
||
* отсутствие рута
|
||
* отсутствие раздела r/w для записи и энергонезависимого хранения файлов
|
||
* отсутствие возможности поставить что-то в автозапуск
|
||
* отсутствие cron
|
||
* неотключаемый flow offload или другая проприетарщина в netfilter
|
||
* недостаток модулей ядра или опций его сборки
|
||
* недостаток модулей 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.
|
||
С их помощью можно компенсировать недостаток ПО основной прошивки, за исключением ядра.
|
||
|
||
Можно попытаться использовать sysv init script таким образом, как это описано в разделе
|
||
"Прикручивание к системе управления фаерволом или своей системе запуска".
|
||
В случае ругани на отсутствие каких-то базовых программ, их следует восполнить посредством entware.
|
||
Перед запуском скрипта путь к дополнительным программам должен быть помещен в PATH.
|
||
|
||
_Подробное описание настроек для других прошивок выходит за рамки данного проекта._
|
||
|
||
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 и репозитория софта
|
||
* flow offload предсказуемо, стандартно и выборочно управляем, а так же отключаем
|
||
* в репозитории есть все модули ядра, их можно доустановить через opkg. ядро пересобирать не нужно.
|
||
* в репозитории есть все модули iptables, их можно доустановить через opkg
|
||
* в репозитории есть огромное количество стандартных программ и дополнительного софта
|
||
* наличие SDK, позволяющего собрать недостающее
|
||
|
||
|
||
## Обход блокировки через сторонний хост
|
||
|
||
Если не работает автономный обход, приходится перенаправлять трафик через сторонний хост.
|
||
Предлагается использовать прозрачный редирект через socks5 посредством `iptables+redsocks`, либо `iptables+iproute+vpn`.
|
||
Настройка варианта с redsocks на openwrt описана в [redsocks.txt](./redsocks.txt).
|
||
Настройка варианта с `iproute+wireguard` - в [wireguard_iproute_openwrt.txt](./wireguard_iproute_openwrt.txt).
|
||
|
||
|
||
## Почему стоит вложиться в покупку 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 не нужны совсем.
|
||
Это вариант наименее напряжный для чайников, хотя и не самый удобный в использовании.
|
||
|
||
## Поддержать разработчика
|
||
|
||
<img src=https://cdn-icons-png.flaticon.com/16/14446/14446252.png alt="USDT" style="vertical-align: middle;"/> USDT
|
||
```
|
||
0x3d52Ce15B7Be734c53fc9526ECbAB8267b63d66E
|
||
```
|
||
|
||
<img src=https://cdn-icons-png.flaticon.com/16/5968/5968260.png alt="USDT" style="vertical-align: middle;"/> BTC
|
||
```
|
||
bc1qhqew3mrvp47uk2vevt5sctp7p2x9m7m5kkchve
|
||
```
|