mirror of https://github.com/bol-van/zapret/
4 changed files with 364 additions and 338 deletions
@ -1,33 +1,33 @@ |
|||
For window size changing : |
|||
|
|||
iptables -t raw -I PREROUTING -p tcp --sport 80 --tcp-flags SYN,ACK SYN,ACK -j NFQUEUE --queue-num 200 --queue-bypass |
|||
iptables -t raw -I PREROUTING -p tcp --sport 80 --tcp-flags SYN,ACK SYN,ACK -m set --match-set zapret src -j NFQUEUE --queue-num 200 --queue-bypass |
|||
|
|||
For outgoing data manipulation ("Host:" case changing) : |
|||
|
|||
iptables -t mangle -I POSTROUTING -p tcp --dport 80 -j NFQUEUE --queue-num 200 --queue-bypass |
|||
iptables -t mangle -I POSTROUTING -p tcp --dport 80 -m set --match-set zapret dst -j NFQUEUE --queue-num 200 --queue-bypass |
|||
iptables -t mangle -I POSTROUTING -p tcp --dport 80 -m set --match-set zapret dst -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:5 -j NFQUEUE --queue-num 200 --queue-bypass |
|||
|
|||
|
|||
For TPROXY : |
|||
|
|||
sysctl -w net.ipv4.ip_forward=1 |
|||
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE |
|||
|
|||
ip -f inet rule add fwmark 1 lookup 100 |
|||
ip -f inet route add local default dev lo table 100 |
|||
# prevent loop |
|||
iptables -t filter -I INPUT -p tcp --dport 1188 -j REJECT |
|||
iptables -t mangle -A PREROUTING -i eth1 -p tcp --dport 80 -j MARK --set-mark 1 |
|||
iptables -t mangle -A PREROUTING -i eth1 -p tcp --dport 80 -j TPROXY --tproxy-mark 0x1/0x1 --on-port 1188 |
|||
|
|||
iptables -t mangle -A PREROUTING -i eth1 -p tcp --dport 80 -m set --match-set zapret dst -j MARK --set-mark 1 |
|||
iptables -t mangle -A PREROUTING -i eth1 -p tcp --dport 80 -m mark --mark 0x1/0x1 -j TPROXY --tproxy-mark 0x1/0x1 --on-port 1188 |
|||
|
|||
For DNAT : |
|||
|
|||
# run tpws as user "tpws". its required to avoid loops. |
|||
sysctl -w net.ipv4.conf.eth1.route_localnet=1 |
|||
iptables -t nat -I PREROUTING -p tcp --dport 80 -j DNAT --to 127.0.0.1:1188 |
|||
iptables -t nat -I OUTPUT -p tcp --dport 80 -m owner ! --uid-owner tpws -j DNAT --to 127.0.0.1:1188 |
|||
For window size changing : |
|||
|
|||
iptables -t raw -I PREROUTING -p tcp --sport 80 --tcp-flags SYN,ACK SYN,ACK -j NFQUEUE --queue-num 200 --queue-bypass |
|||
iptables -t raw -I PREROUTING -p tcp --sport 80 --tcp-flags SYN,ACK SYN,ACK -m set --match-set zapret src -j NFQUEUE --queue-num 200 --queue-bypass |
|||
|
|||
For outgoing data manipulation ("Host:" case changing) : |
|||
|
|||
iptables -t mangle -I POSTROUTING -p tcp --dport 80 -j NFQUEUE --queue-num 200 --queue-bypass |
|||
iptables -t mangle -I POSTROUTING -p tcp --dport 80 -m set --match-set zapret dst -j NFQUEUE --queue-num 200 --queue-bypass |
|||
iptables -t mangle -I POSTROUTING -p tcp --dport 80 -m set --match-set zapret dst -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:5 -j NFQUEUE --queue-num 200 --queue-bypass |
|||
|
|||
|
|||
For TPROXY : |
|||
|
|||
sysctl -w net.ipv4.ip_forward=1 |
|||
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE |
|||
|
|||
ip -f inet rule add fwmark 1 lookup 100 |
|||
ip -f inet route add local default dev lo table 100 |
|||
# prevent loop |
|||
iptables -t filter -I INPUT -p tcp --dport 1188 -j REJECT |
|||
iptables -t mangle -A PREROUTING -i eth1 -p tcp --dport 80 -j MARK --set-mark 1 |
|||
iptables -t mangle -A PREROUTING -i eth1 -p tcp --dport 80 -j TPROXY --tproxy-mark 0x1/0x1 --on-port 1188 |
|||
|
|||
iptables -t mangle -A PREROUTING -i eth1 -p tcp --dport 80 -m set --match-set zapret dst -j MARK --set-mark 1 |
|||
iptables -t mangle -A PREROUTING -i eth1 -p tcp --dport 80 -m mark --mark 0x1/0x1 -j TPROXY --tproxy-mark 0x1/0x1 --on-port 1188 |
|||
|
|||
For DNAT : |
|||
|
|||
# run tpws as user "tpws". its required to avoid loops. |
|||
sysctl -w net.ipv4.conf.eth1.route_localnet=1 |
|||
iptables -t nat -I PREROUTING -p tcp --dport 80 -j DNAT --to 127.0.0.1:1188 |
|||
iptables -t nat -I OUTPUT -p tcp --dport 80 -m owner ! --uid-owner tpws -j DNAT --to 127.0.0.1:1188 |
|||
|
@ -1,255 +1,259 @@ |
|||
zapret v.6 |
|||
|
|||
Для чего это надо |
|||
----------------- |
|||
|
|||
Обойти блокировки веб сайтов http. |
|||
|
|||
Как это работает |
|||
---------------- |
|||
|
|||
У провайдеров в DPI бывают бреши. Они случаются от того, что правила DPI пишут для |
|||
обычных пользовательских программ, опуская все возможные случаи, допустимые по стандартам. |
|||
Это делается для простоты и скорости. Нет смысла ловить хакеров, которых 0.01%, |
|||
ведь все равно эти блокировки обходятся довольно просто даже обычными пользователями. |
|||
|
|||
Некоторые DPI не могут распознать http запрос, если он разделен на TCP сегменты. |
|||
Например, запрос вида "GET / HTTP/1.1\r\nHost: kinozal.tv......" |
|||
мы посылаем 2 частями : сначала идет "GET ", затем "/ HTTP/1.1\r\nHost: kinozal.tv.....". |
|||
Другие DPI спотыкаются, когда заголовок "Host:" пишется в другом регистре : например, "host:". |
|||
Кое-где работает добавление дополнительного пробела после метода : "GET /" => "GET /". |
|||
|
|||
Как это реализовать на практике в системе linux |
|||
----------------------------------------------- |
|||
|
|||
Как заставить систему разбивать запрос на части ? Можно прогнать всю TCP сессию |
|||
через transparent proxy, а можно подменить поле tcp window size на первом входящем TCP пакете с SYN,ACK. |
|||
Тогда клиент подумает, что сервер установил для него маленький window size и первый сегмент с данными |
|||
отошлет не более указанной длины. В последующих пакетах мы не будем менять ничего. |
|||
Дальнейшее поведение системы по выбору размера отсылаемых пакетов зависит от реализованного |
|||
в ней алгоритма. Опыт показывает, что linux первый пакет всегда отсылает не более указанной |
|||
в window size длины, остальные пакеты до некоторых пор шлет не более max(36,указанный_размер). |
|||
После некоторого количества пакетов срабатывает механизм window scaling и начинает |
|||
учитываться фактор скалинга, размер пакетов становится не более max(36,указанный_рамер << scale_factor). |
|||
Не слишком изящное поведение, но поскольку на размеры входящик пакетов мы не влияем, |
|||
а объем принимаемых по http данных обычно гораздо выше объема отсылаемых, то визуально |
|||
появятся лишь небольшие задержки. |
|||
Windows ведет себя в аналогичном случае гораздо более предсказуемо. Первый сегмент |
|||
уходит указанной длины, дальше window size меняется в зависимости от значения, |
|||
присылаемого в новых tcp пакетах. То есть скорость почти сразу же восстанавливается |
|||
до возможного максимума. |
|||
|
|||
Перехватить пакет с SYN,ACK не представляет никакой сложности средствами iptables. |
|||
Однако, возможности редактирования пакетов в iptables сильно ограничены. |
|||
Просто так поменять window size стандартными модулями нельзя. |
|||
Для этого мы воспользуемся средством NFQUEUE. Это средство позволяет |
|||
передавать пакеты на обработку процессам, работающим в user mode. |
|||
Процесс, приняв пакет, может его изменить, что нам и нужно. |
|||
|
|||
iptables -t raw -I PREROUTING -p tcp --sport 80 --tcp-flags SYN,ACK SYN,ACK -j NFQUEUE --queue-num 200 --queue-bypass |
|||
|
|||
Будет отдавать нужные нам пакеты процессу, слушающему на очереди с номером 200. |
|||
Он подменит window size. PREROUTING поймает как пакеты, адресованные самому хосту, |
|||
так и маршрутизируемые пакеты. То есть решение одинаково работает как на клиенте, |
|||
так и на роутере. На роутере на базе PC или на базе OpenWRT. |
|||
В принципе этого достаточно. |
|||
Однако, при таком воздействии на TCP будет небольшая задержка. |
|||
Чтобы не трогать хосты, которые не блокируются провайдером, можно сделать такой ход. |
|||
Создать список заблоченых доменов или скачать его с rublacklist. |
|||
Заресолвить все домены в ipv4 адреса. Загнать их в ipset с именем "zapret". |
|||
Добавить в правило : |
|||
|
|||
iptables -t raw -I PREROUTING -p tcp --sport 80 --tcp-flags SYN,ACK SYN,ACK -m set --match-set zapret src -j NFQUEUE --queue-num 200 --queue-bypass |
|||
|
|||
Такии образом воздействие будет производиться только на ip адреса, относящиеся к заблокированным сайтам. |
|||
Список можно обновлять через cron раз в несколько дней. |
|||
Если обновлять через rublacklist, то это займет довольно долго. Более часа. Но ресурсов |
|||
этот процесс не отнимает, так что никаких проблем это не вызовет, особенно, если система |
|||
работает постоянно. |
|||
|
|||
Если DPI не обходится через разделение запроса на сегменты, то иногда срабатывает изменение |
|||
"Host:" на "host:". В этом случае нам может не понадобится замена window size, поэтому цепочка |
|||
PREROUTING нам не нужна. Вместо нее вешаемся на исходящие пакеты в цепочке POSTROUTING : |
|||
|
|||
iptables -t mangle -I POSTROUTING -p tcp --dport 80 -m set --match-set zapret dst -j NFQUEUE --queue-num 200 --queue-bypass |
|||
|
|||
В этом случае так же возможны дополнительные моменты. DPI может ловить только первый http запрос, игнорируя |
|||
последующие запросы в keep-alive сессии. Тогда можем уменьшить нагрузку на проц, отказавшись от процессинга ненужных пакетов. |
|||
|
|||
iptables -t mangle -I POSTROUTING -p tcp --dport 80 -m set --match-set zapret dst -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:5 -j NFQUEUE --queue-num 200 --queue-bypass |
|||
|
|||
Случается так, что провайдер мониторит всю HTTP сессию с keep-alive запросами. В этом случае |
|||
недостаточно ограничивать TCP window при установлении соединения. Необходимо посылать отдельными |
|||
TCP сегментами каждый новый запрос. Эта задача решается через полное проксирование трафика через |
|||
transparent proxy (TPROXY или DNAT). TPROXY не работает с соединениями, исходящими с локальной системы, |
|||
так что это решение применимо только на роутере. DNAT работает и с локальными соединениеми, |
|||
но имеется опасность входа в бесконечную рекурсию, поэтому демон запускается под отдельным пользователем, |
|||
и для этого пользователя отключается DNAT через "-m owner". Полное проксирование требует больше ресурсов |
|||
процессора, чем манипуляция с исходящими пакетами без реконструкции TCP соединения. |
|||
|
|||
iptables -t nat -I PREROUTING -p tcp --dport 80 -j DNAT --to 127.0.0.1:1188 |
|||
iptables -t nat -I OUTPUT -p tcp --dport 80 -m owner ! --uid-owner tpws -j DNAT --to 127.0.0.1:1188 |
|||
|
|||
nfqws |
|||
----- |
|||
|
|||
Эта программа - модификатор пакетов и обработчик очереди NFQUEUE. |
|||
Она берет следующие параметры : |
|||
--qnum=200 ; номер очереди |
|||
--wsize=4 ; менять tcp window size на указанный размер |
|||
--hostcase ; менять регистр заголовка "Host:" |
|||
--daemon ; демонизировать прогу |
|||
|
|||
tpws |
|||
----- |
|||
|
|||
tpws - это transparent proxy. |
|||
--bind-addr ; на каком адресе слушать. может быть ipv4 или ipv6 адрес. если не указано, то слушает на всех адресах ipv4 и ipv6 |
|||
--port=<port> ; на каком порту слушать |
|||
--split-http-req=method|host ; способ разделения http запросов на сегменты : около метода (GET,POST) или около заголовка Host |
|||
--hostcase ; замена "Host:" => "host:" |
|||
--methodspace ; добавить пробел после метода : "GET /" => "GET /" |
|||
--daemon ; демонизировать прогу |
|||
--user=<username> ; менять uid процесса |
|||
|
|||
Провайдеры |
|||
---------- |
|||
|
|||
mns.ru : нужна замена window size на 4 |
|||
beeline (corbina) : нужна замена регистра "Host:" на протяжении всей http сессии |
|||
dom.ru : нужно проксирование HTTP сессий через tpws с заменой регистра "Host:" и разделение TCP сегментов на хедере "Host:". |
|||
Ахтунг ! Домру блокирует все поддомены заблоченого домена. IP адреса всевозможных поддоменов узнать невозможно из реестра |
|||
блокировок, поэтому если вдруг на каком-то сайте вылезает блокировочный баннер, то идите в консоль firefox, вкладка network. |
|||
Загружайте сайт и смотрите куда идет редирект. Потом вносите домен в zapret-hosts-user.txt. Например, на kinozal.tv имеются |
|||
2 запрашиваемых поддомена : s.kinozal.tv и st.kinozal.tv с разными IP адресами. |
|||
sknt.ru : проверена работа с tpws с параметром "--split-http-req=method". возможно, будет работать nfqueue, пока возможности |
|||
проверить нет |
|||
tkt : помогает разделение http запроса на сегменты, настройки mns.ru подходят |
|||
ТКТ был куплен ростелекомом, используется фильтрация ростелекома. |
|||
Поскольку DPI не отбрасывает входящую сессию, а только всовывает свой пакет, который приходит раньше ответа от настоящего сервера, |
|||
блокировки так же обходятся без применения "тяжелой артиллерии" следующим правилом : |
|||
iptables -t raw -I PREROUTING -p tcp --sport 80 -m string --hex-string "|0D0A|Location: http://95.167.13.50" --algo bm -j DROP --from 40 --to 200 |
|||
Ростелеком : см tkt |
|||
|
|||
Способы получения списка заблокированных IP |
|||
------------------------------------------- |
|||
|
|||
1) Внесите заблокирванные домены в ipset/zapret-hosts-user.txt и запустите ipset/get_user.sh |
|||
На выходе получите ipset/zapret-ip-user.txt с IP адресами. |
|||
|
|||
2) ipset/get_reestr.sh получает список доменов от rublacklist и дальше их ресолвит в ip адреса |
|||
в файл ipset/zapret-ip.txt. В этом списке есть готовые IP адреса, но судя во всему они там в точности в том виде, |
|||
что вносит в реестр РосКомПозор. Адреса могут меняться, позор не успевает их обновлять, а провайдеры редко |
|||
банят по IP : вместо этого они банят http запросы с "нехорошим" заголовком "Host:" вне зависимости |
|||
от IP адреса. Поэтому скрипт ресолвит все сам, хотя это и занимает много времени. |
|||
Дополнительное требование - объем памяти в /tmp для сохранения туда скачанного файла, размер которого |
|||
несколько Мб и продолжает расти. На роутерах openwrt /tmp представляет собой tmpfs , то есть ramdisk. |
|||
В случае роутера с 32 мб памяти ее может не хватить, и будут проблемы. В этом случае используйте |
|||
следующий скрипт. |
|||
Скрипт автоматически вызывает ipset/get_user.sh и обновляет ipset |
|||
|
|||
3) ipset/get_anizapret.sh. быстро и без нагрузки на роутер получает лист с http://antizapret.prostovpn.org. |
|||
Скрипт автоматически вызывает ipset/get_user.sh и обновляет ipset |
|||
|
|||
На роутерах не рекомендуется вызывать эти скрипты чаще раза за 2 суток, поскольку сохранение идет |
|||
либо во внутреннюю флэш память роутера, либо в случае extroot - на флэшку. |
|||
В обоих случаях слишком частая запись может убить флэшку, но если это произойдет с внутренней |
|||
флэш памятью, то вы просто убьете роутер. |
|||
|
|||
Обновление ipset выполняет скрипт ipset/create_ipset.sh |
|||
|
|||
Пример установки на debian 7 |
|||
---------------------------- |
|||
Debian 7 изначально содержит ядро 3.2. Оно не умеет делать DNAT на localhost. |
|||
Конечно, можно не привязывать tpws к 127.0.0.1 и заменить в правилах iptables "DNAT 127.0.0.1" на "REDIRECT", |
|||
но лучше установить более свежее ядро. Оно есть в стабильном репозитории : |
|||
apt-get update |
|||
apt-get install linux-image-3.16 |
|||
Установить пакеты : |
|||
apt-get update |
|||
apt-get install libnetfilter-queue-dev ipset curl |
|||
Скопировать директорию "zapret" в /opt. |
|||
Собрать nfqws : |
|||
cd /opt/zapret/nfq |
|||
make |
|||
Собрать tpws : |
|||
cd /opt/zapret/tpws |
|||
make |
|||
Скопировать /opt/zapret/init.d/debian7/zapret в /etc/init.d. |
|||
В /etc/init.d/zapret выбрать пераметр "ISP". В зависимости от него будут применены нужные правила. |
|||
Там же выбрать параметр SLAVE_ETH, соответствующий названию внутреннего сетевого интерфейса. |
|||
Включить автостарт : chkconfig zapret on |
|||
(опционально) Вручную первый раз получить новый список ip адресов : /opt/zapret/ipset/get_antizapret.sh |
|||
Зашедулить задание обновления листа : |
|||
crontab -e |
|||
Создать строчку "0 12 * * */2 /opt/zapret/ipset/get_antizapret.sh". Это значит в 12:00 каждые 2 дня обновлять список. |
|||
Запустить службу : service zapret start |
|||
Попробовать зайти куда-нибудь : http://ej.ru, http://kinozal.tv, http://grani.ru. |
|||
Если не работает, то остановить службу zapret, добавить правило в iptables вручную, |
|||
запустить nfqws в терминале под рутом с нужными параметрами. |
|||
Пытаться подключаться к заблоченым сайтам, смотреть вывод программы. |
|||
Если нет никакой реакции, значит скорее всего указан неверный номер очереди или ip назначения нет в ipset. |
|||
Если реакция есть, но блокировка не обходится, значит параметры обхода подобраные неверно, или это средство |
|||
не работает в вашем случае на вашем провайдере. |
|||
Никто и не говорил, что это будет работать везде. |
|||
Попробуйте снять дамп в wireshark или "tcpdump -vvv -X host <ip>", посмотрите действительно ли первый |
|||
сегмент TCP уходит коротким и меняется ли регистр "Host:". |
|||
|
|||
ubuntu 12,14 |
|||
------------ |
|||
|
|||
Имеется готовый конфиг для upstart : zapret.conf. Его нужно скопировать в /etc/init и настроить по аналогии с debian. |
|||
Запуск службы : "start zapret" |
|||
Останов службы : "stop zapret" |
|||
|
|||
Другие linux системы |
|||
-------------------- |
|||
|
|||
Существует несколько основных систем запуска служб : sysvinit, upstart, systemd. |
|||
Настройка зависит от системы, используемой в вашем дистрибутиве. |
|||
Типичная стратегия - найти скрипт или конфигурацию запуска других служб и написать свой по аналогии, |
|||
при необходимости почитывая документацию по системе запуска. |
|||
Нужные команды можно взять из предложенных скриптов. |
|||
|
|||
Фаерволлы |
|||
--------- |
|||
|
|||
Если вы используете какую-то систему управления фаерволом, то она может вступать в конфликт |
|||
с имеющимся скриптом запуска. В этом случае правила для iptables должны быть прикручены |
|||
к вашему фаерволу отдельно от скрипта запуска tpws или nfqws. |
|||
Именно так решается вопрос в случае с openwrt, поскольку там своя система управления фаерволом. |
|||
При повторном применении правил она могла бы поломать настройки iptables, сделанные скриптом из init.d. |
|||
|
|||
Что делать с openwrt |
|||
-------------------- |
|||
|
|||
Установить дополнительные пакеты : |
|||
opkg update |
|||
opkg install iptables-mod-extra iptables-mod-nfqueue iptables-mod-filter iptables-mod-ipopt ipset curl bind-tools |
|||
|
|||
Самая главная трудность - скомпилировать программы на C. |
|||
Это можно сделать средствами кросс-компиляции на любой традиционной linux системе. |
|||
Читайте compile/build_howto_openwrt.txt. |
|||
Ваша задача - получить ipk файлы для tpws и nfqws. |
|||
Скопировать директорию "zapret" в /opt на роутер. |
|||
Установить ipk. Для этого сначала копируем на роутер ipk в /tmp, потом opkg install /tmp/*.ipk. |
|||
Смотрим, что появились исполняемые файлы /opt/zapret/tpws/tpws, /opt/zapret/nfq/nfqws. |
|||
Скопировать /opt/zapret/init.d/zapret в /etc/init.d. |
|||
В /etc/init.d/zapret выбрать пераметр "ISP". В зависимости от него будут применены нужные правила. |
|||
/etc/init.d/zapret enable |
|||
/etc/init.d/zapret start |
|||
В зависимости от вашего провайдера либо внести нужные записи в /etc/firewall.user, либо |
|||
скопировать 99-zapret в /etc/hotplug.d/firewall (сначала нужно mkdir /etc/hotplug.d/firewall). |
|||
В /etc/hotplug.d/firewall/99-zapret выбрать нужного провайдера. |
|||
/etc/init.d/firewall restart |
|||
Посмотреть через iptables -L или через luci вкладку "firewall" появились ли нужные правила. |
|||
Зашедулить задание обновления листа : |
|||
crontab -e |
|||
Создать строчку "0 12 * * */2 /opt/zapret/ipset/get_antizapret.sh". Это значит в 12:00 каждые 2 дня обновлять список. |
|||
|
|||
Если у вас linux x64, то вместо компиляции toolchain можно использовать пре-компилированный SDK от разработчиков openwrt. |
|||
https://downloads.openwrt.org/ |
|||
Найдите вашу версию openwrt, найдите вашу архитектуру, скачайте файл "OpenWrt-SDK-*". |
|||
Фактически это тот же buildroot, только в нем уже подготовлен toolchain для нужной версии openwrt, |
|||
нужной target архитектуры и хост-системы linux x64. |
|||
|
|||
zapret v.7 |
|||
|
|||
Для чего это надо |
|||
----------------- |
|||
|
|||
Обойти блокировки веб сайтов http. |
|||
|
|||
Как это работает |
|||
---------------- |
|||
|
|||
У провайдеров в DPI бывают бреши. Они случаются от того, что правила DPI пишут для |
|||
обычных пользовательских программ, опуская все возможные случаи, допустимые по стандартам. |
|||
Это делается для простоты и скорости. Нет смысла ловить хакеров, которых 0.01%, |
|||
ведь все равно эти блокировки обходятся довольно просто даже обычными пользователями. |
|||
|
|||
Некоторые DPI не могут распознать http запрос, если он разделен на TCP сегменты. |
|||
Например, запрос вида "GET / HTTP/1.1\r\nHost: kinozal.tv......" |
|||
мы посылаем 2 частями : сначала идет "GET ", затем "/ HTTP/1.1\r\nHost: kinozal.tv.....". |
|||
Другие DPI спотыкаются, когда заголовок "Host:" пишется в другом регистре : например, "host:". |
|||
Кое-где работает добавление дополнительного пробела после метода : "GET /" => "GET /" |
|||
или добавление точки в конце имени хоста : "Host: kinozal.tv." |
|||
|
|||
Как это реализовать на практике в системе linux |
|||
----------------------------------------------- |
|||
|
|||
Как заставить систему разбивать запрос на части ? Можно прогнать всю TCP сессию |
|||
через transparent proxy, а можно подменить поле tcp window size на первом входящем TCP пакете с SYN,ACK. |
|||
Тогда клиент подумает, что сервер установил для него маленький window size и первый сегмент с данными |
|||
отошлет не более указанной длины. В последующих пакетах мы не будем менять ничего. |
|||
Дальнейшее поведение системы по выбору размера отсылаемых пакетов зависит от реализованного |
|||
в ней алгоритма. Опыт показывает, что linux первый пакет всегда отсылает не более указанной |
|||
в window size длины, остальные пакеты до некоторых пор шлет не более max(36,указанный_размер). |
|||
После некоторого количества пакетов срабатывает механизм window scaling и начинает |
|||
учитываться фактор скалинга, размер пакетов становится не более max(36,указанный_рамер << scale_factor). |
|||
Не слишком изящное поведение, но поскольку на размеры входящик пакетов мы не влияем, |
|||
а объем принимаемых по http данных обычно гораздо выше объема отсылаемых, то визуально |
|||
появятся лишь небольшие задержки. |
|||
Windows ведет себя в аналогичном случае гораздо более предсказуемо. Первый сегмент |
|||
уходит указанной длины, дальше window size меняется в зависимости от значения, |
|||
присылаемого в новых tcp пакетах. То есть скорость почти сразу же восстанавливается |
|||
до возможного максимума. |
|||
|
|||
Перехватить пакет с SYN,ACK не представляет никакой сложности средствами iptables. |
|||
Однако, возможности редактирования пакетов в iptables сильно ограничены. |
|||
Просто так поменять window size стандартными модулями нельзя. |
|||
Для этого мы воспользуемся средством NFQUEUE. Это средство позволяет |
|||
передавать пакеты на обработку процессам, работающим в user mode. |
|||
Процесс, приняв пакет, может его изменить, что нам и нужно. |
|||
|
|||
iptables -t raw -I PREROUTING -p tcp --sport 80 --tcp-flags SYN,ACK SYN,ACK -j NFQUEUE --queue-num 200 --queue-bypass |
|||
|
|||
Будет отдавать нужные нам пакеты процессу, слушающему на очереди с номером 200. |
|||
Он подменит window size. PREROUTING поймает как пакеты, адресованные самому хосту, |
|||
так и маршрутизируемые пакеты. То есть решение одинаково работает как на клиенте, |
|||
так и на роутере. На роутере на базе PC или на базе OpenWRT. |
|||
В принципе этого достаточно. |
|||
Однако, при таком воздействии на TCP будет небольшая задержка. |
|||
Чтобы не трогать хосты, которые не блокируются провайдером, можно сделать такой ход. |
|||
Создать список заблоченых доменов или скачать его с rublacklist. |
|||
Заресолвить все домены в ipv4 адреса. Загнать их в ipset с именем "zapret". |
|||
Добавить в правило : |
|||
|
|||
iptables -t raw -I PREROUTING -p tcp --sport 80 --tcp-flags SYN,ACK SYN,ACK -m set --match-set zapret src -j NFQUEUE --queue-num 200 --queue-bypass |
|||
|
|||
Такии образом воздействие будет производиться только на ip адреса, относящиеся к заблокированным сайтам. |
|||
Список можно обновлять через cron раз в несколько дней. |
|||
Если обновлять через rublacklist, то это займет довольно долго. Более часа. Но ресурсов |
|||
этот процесс не отнимает, так что никаких проблем это не вызовет, особенно, если система |
|||
работает постоянно. |
|||
|
|||
Если DPI не обходится через разделение запроса на сегменты, то иногда срабатывает изменение |
|||
"Host:" на "host:". В этом случае нам может не понадобится замена window size, поэтому цепочка |
|||
PREROUTING нам не нужна. Вместо нее вешаемся на исходящие пакеты в цепочке POSTROUTING : |
|||
|
|||
iptables -t mangle -I POSTROUTING -p tcp --dport 80 -m set --match-set zapret dst -j NFQUEUE --queue-num 200 --queue-bypass |
|||
|
|||
В этом случае так же возможны дополнительные моменты. DPI может ловить только первый http запрос, игнорируя |
|||
последующие запросы в keep-alive сессии. Тогда можем уменьшить нагрузку на проц, отказавшись от процессинга ненужных пакетов. |
|||
|
|||
iptables -t mangle -I POSTROUTING -p tcp --dport 80 -m set --match-set zapret dst -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:5 -j NFQUEUE --queue-num 200 --queue-bypass |
|||
|
|||
Случается так, что провайдер мониторит всю HTTP сессию с keep-alive запросами. В этом случае |
|||
недостаточно ограничивать TCP window при установлении соединения. Необходимо посылать отдельными |
|||
TCP сегментами каждый новый запрос. Эта задача решается через полное проксирование трафика через |
|||
transparent proxy (TPROXY или DNAT). TPROXY не работает с соединениями, исходящими с локальной системы, |
|||
так что это решение применимо только на роутере. DNAT работает и с локальными соединениеми, |
|||
но имеется опасность входа в бесконечную рекурсию, поэтому демон запускается под отдельным пользователем, |
|||
и для этого пользователя отключается DNAT через "-m owner". Полное проксирование требует больше ресурсов |
|||
процессора, чем манипуляция с исходящими пакетами без реконструкции TCP соединения. |
|||
|
|||
iptables -t nat -I PREROUTING -p tcp --dport 80 -j DNAT --to 127.0.0.1:1188 |
|||
iptables -t nat -I OUTPUT -p tcp --dport 80 -m owner ! --uid-owner tpws -j DNAT --to 127.0.0.1:1188 |
|||
|
|||
nfqws |
|||
----- |
|||
|
|||
Эта программа - модификатор пакетов и обработчик очереди NFQUEUE. |
|||
Она берет следующие параметры : |
|||
--daemon ; демонизировать прогу |
|||
--qnum=200 ; номер очереди |
|||
--wsize=4 ; менять tcp window size на указанный размер |
|||
--hostcase ; менять регистр заголовка "Host:" |
|||
Параметры манипуляции могут сочетаться в любых комбинациях. |
|||
|
|||
tpws |
|||
----- |
|||
|
|||
tpws - это transparent proxy. |
|||
--bind-addr ; на каком адресе слушать. может быть ipv4 или ipv6 адрес. если не указано, то слушает на всех адресах ipv4 и ipv6 |
|||
--port=<port> ; на каком порту слушать |
|||
--daemon ; демонизировать прогу |
|||
--user=<username> ; менять uid процесса |
|||
--split-http-req=method|host ; способ разделения http запросов на сегменты : около метода (GET,POST) или около заголовка Host |
|||
--hostcase ; замена "Host:" => "host:" |
|||
--hostdot ; добавление точки после имени хоста : "Host: kinozal.tv." |
|||
--methodspace ; добавить пробел после метода : "GET /" => "GET /" |
|||
Параметры манипуляции могут сочетаться в любых комбинациях. |
|||
|
|||
Провайдеры |
|||
---------- |
|||
|
|||
mns.ru : нужна замена window size на 4 |
|||
beeline (corbina) : нужна замена регистра "Host:" на протяжении всей http сессии |
|||
dom.ru : нужно проксирование HTTP сессий через tpws с заменой регистра "Host:" и разделение TCP сегментов на хедере "Host:". |
|||
Ахтунг ! Домру блокирует все поддомены заблоченого домена. IP адреса всевозможных поддоменов узнать невозможно из реестра |
|||
блокировок, поэтому если вдруг на каком-то сайте вылезает блокировочный баннер, то идите в консоль firefox, вкладка network. |
|||
Загружайте сайт и смотрите куда идет редирект. Потом вносите домен в zapret-hosts-user.txt. Например, на kinozal.tv имеются |
|||
2 запрашиваемых поддомена : s.kinozal.tv и st.kinozal.tv с разными IP адресами. |
|||
sknt.ru : проверена работа с tpws с параметром "--split-http-req=method". возможно, будет работать nfqueue, пока возможности |
|||
проверить нет |
|||
tkt : помогает разделение http запроса на сегменты, настройки mns.ru подходят |
|||
ТКТ был куплен ростелекомом, используется фильтрация ростелекома. |
|||
Поскольку DPI не отбрасывает входящую сессию, а только всовывает свой пакет, который приходит раньше ответа от настоящего сервера, |
|||
блокировки так же обходятся без применения "тяжелой артиллерии" следующим правилом : |
|||
iptables -t raw -I PREROUTING -p tcp --sport 80 -m string --hex-string "|0D0A|Location: http://95.167.13.50" --algo bm -j DROP --from 40 --to 200 |
|||
Ростелеком : см tkt |
|||
|
|||
Способы получения списка заблокированных IP |
|||
------------------------------------------- |
|||
|
|||
1) Внесите заблокирванные домены в ipset/zapret-hosts-user.txt и запустите ipset/get_user.sh |
|||
На выходе получите ipset/zapret-ip-user.txt с IP адресами. |
|||
|
|||
2) ipset/get_reestr.sh получает список доменов от rublacklist и дальше их ресолвит в ip адреса |
|||
в файл ipset/zapret-ip.txt. В этом списке есть готовые IP адреса, но судя во всему они там в точности в том виде, |
|||
что вносит в реестр РосКомПозор. Адреса могут меняться, позор не успевает их обновлять, а провайдеры редко |
|||
банят по IP : вместо этого они банят http запросы с "нехорошим" заголовком "Host:" вне зависимости |
|||
от IP адреса. Поэтому скрипт ресолвит все сам, хотя это и занимает много времени. |
|||
Дополнительное требование - объем памяти в /tmp для сохранения туда скачанного файла, размер которого |
|||
несколько Мб и продолжает расти. На роутерах openwrt /tmp представляет собой tmpfs , то есть ramdisk. |
|||
В случае роутера с 32 мб памяти ее может не хватить, и будут проблемы. В этом случае используйте |
|||
следующий скрипт. |
|||
Скрипт автоматически вызывает ipset/get_user.sh и обновляет ipset |
|||
|
|||
3) ipset/get_anizapret.sh. быстро и без нагрузки на роутер получает лист с http://antizapret.prostovpn.org. |
|||
Скрипт автоматически вызывает ipset/get_user.sh и обновляет ipset |
|||
|
|||
На роутерах не рекомендуется вызывать эти скрипты чаще раза за 2 суток, поскольку сохранение идет |
|||
либо во внутреннюю флэш память роутера, либо в случае extroot - на флэшку. |
|||
В обоих случаях слишком частая запись может убить флэшку, но если это произойдет с внутренней |
|||
флэш памятью, то вы просто убьете роутер. |
|||
|
|||
Обновление ipset выполняет скрипт ipset/create_ipset.sh |
|||
|
|||
Пример установки на debian 7 |
|||
---------------------------- |
|||
Debian 7 изначально содержит ядро 3.2. Оно не умеет делать DNAT на localhost. |
|||
Конечно, можно не привязывать tpws к 127.0.0.1 и заменить в правилах iptables "DNAT 127.0.0.1" на "REDIRECT", |
|||
но лучше установить более свежее ядро. Оно есть в стабильном репозитории : |
|||
apt-get update |
|||
apt-get install linux-image-3.16 |
|||
Установить пакеты : |
|||
apt-get update |
|||
apt-get install libnetfilter-queue-dev ipset curl |
|||
Скопировать директорию "zapret" в /opt. |
|||
Собрать nfqws : |
|||
cd /opt/zapret/nfq |
|||
make |
|||
Собрать tpws : |
|||
cd /opt/zapret/tpws |
|||
make |
|||
Скопировать /opt/zapret/init.d/debian7/zapret в /etc/init.d. |
|||
В /etc/init.d/zapret выбрать пераметр "ISP". В зависимости от него будут применены нужные правила. |
|||
Там же выбрать параметр SLAVE_ETH, соответствующий названию внутреннего сетевого интерфейса. |
|||
Включить автостарт : chkconfig zapret on |
|||
(опционально) Вручную первый раз получить новый список ip адресов : /opt/zapret/ipset/get_antizapret.sh |
|||
Зашедулить задание обновления листа : |
|||
crontab -e |
|||
Создать строчку "0 12 * * */2 /opt/zapret/ipset/get_antizapret.sh". Это значит в 12:00 каждые 2 дня обновлять список. |
|||
Запустить службу : service zapret start |
|||
Попробовать зайти куда-нибудь : http://ej.ru, http://kinozal.tv, http://grani.ru. |
|||
Если не работает, то остановить службу zapret, добавить правило в iptables вручную, |
|||
запустить nfqws в терминале под рутом с нужными параметрами. |
|||
Пытаться подключаться к заблоченым сайтам, смотреть вывод программы. |
|||
Если нет никакой реакции, значит скорее всего указан неверный номер очереди или ip назначения нет в ipset. |
|||
Если реакция есть, но блокировка не обходится, значит параметры обхода подобраные неверно, или это средство |
|||
не работает в вашем случае на вашем провайдере. |
|||
Никто и не говорил, что это будет работать везде. |
|||
Попробуйте снять дамп в wireshark или "tcpdump -vvv -X host <ip>", посмотрите действительно ли первый |
|||
сегмент TCP уходит коротким и меняется ли регистр "Host:". |
|||
|
|||
ubuntu 12,14 |
|||
------------ |
|||
|
|||
Имеется готовый конфиг для upstart : zapret.conf. Его нужно скопировать в /etc/init и настроить по аналогии с debian. |
|||
Запуск службы : "start zapret" |
|||
Останов службы : "stop zapret" |
|||
|
|||
Другие linux системы |
|||
-------------------- |
|||
|
|||
Существует несколько основных систем запуска служб : sysvinit, upstart, systemd. |
|||
Настройка зависит от системы, используемой в вашем дистрибутиве. |
|||
Типичная стратегия - найти скрипт или конфигурацию запуска других служб и написать свой по аналогии, |
|||
при необходимости почитывая документацию по системе запуска. |
|||
Нужные команды можно взять из предложенных скриптов. |
|||
|
|||
Фаерволлы |
|||
--------- |
|||
|
|||
Если вы используете какую-то систему управления фаерволом, то она может вступать в конфликт |
|||
с имеющимся скриптом запуска. В этом случае правила для iptables должны быть прикручены |
|||
к вашему фаерволу отдельно от скрипта запуска tpws или nfqws. |
|||
Именно так решается вопрос в случае с openwrt, поскольку там своя система управления фаерволом. |
|||
При повторном применении правил она могла бы поломать настройки iptables, сделанные скриптом из init.d. |
|||
|
|||
Что делать с openwrt |
|||
-------------------- |
|||
|
|||
Установить дополнительные пакеты : |
|||
opkg update |
|||
opkg install iptables-mod-extra iptables-mod-nfqueue iptables-mod-filter iptables-mod-ipopt ipset curl bind-tools |
|||
|
|||
Самая главная трудность - скомпилировать программы на C. |
|||
Это можно сделать средствами кросс-компиляции на любой традиционной linux системе. |
|||
Читайте compile/build_howto_openwrt.txt. |
|||
Ваша задача - получить ipk файлы для tpws и nfqws. |
|||
Скопировать директорию "zapret" в /opt на роутер. |
|||
Установить ipk. Для этого сначала копируем на роутер ipk в /tmp, потом opkg install /tmp/*.ipk. |
|||
Смотрим, что появились исполняемые файлы /opt/zapret/tpws/tpws, /opt/zapret/nfq/nfqws. |
|||
Скопировать /opt/zapret/init.d/zapret в /etc/init.d. |
|||
В /etc/init.d/zapret выбрать пераметр "ISP". В зависимости от него будут применены нужные правила. |
|||
/etc/init.d/zapret enable |
|||
/etc/init.d/zapret start |
|||
В зависимости от вашего провайдера либо внести нужные записи в /etc/firewall.user, либо |
|||
скопировать 99-zapret в /etc/hotplug.d/firewall (сначала нужно mkdir /etc/hotplug.d/firewall). |
|||
В /etc/hotplug.d/firewall/99-zapret выбрать нужного провайдера. |
|||
/etc/init.d/firewall restart |
|||
Посмотреть через iptables -L или через luci вкладку "firewall" появились ли нужные правила. |
|||
Зашедулить задание обновления листа : |
|||
crontab -e |
|||
Создать строчку "0 12 * * */2 /opt/zapret/ipset/get_antizapret.sh". Это значит в 12:00 каждые 2 дня обновлять список. |
|||
|
|||
Если у вас linux x64, то вместо компиляции toolchain можно использовать пре-компилированный SDK от разработчиков openwrt. |
|||
https://downloads.openwrt.org/ |
|||
Найдите вашу версию openwrt, найдите вашу архитектуру, скачайте файл "OpenWrt-SDK-*". |
|||
Фактически это тот же buildroot, только в нем уже подготовлен toolchain для нужной версии openwrt, |
|||
нужной target архитектуры и хост-системы linux x64. |
|||
|
|||
|
Loading…
Reference in new issue