mirror of
https://github.com/bol-van/zapret.git
synced 2024-12-02 14:40:52 +03:00
170 lines
14 KiB
Plaintext
170 lines
14 KiB
Plaintext
|
zapret v.3
|
|||
|
|
|||
|
Для чего это надо
|
|||
|
-----------------
|
|||
|
|
|||
|
Обойти блокировки веб сайтов 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.....".
|
|||
|
Как заставить систему разбивать запрос на 2 части ? Подменить поле tcp window size
|
|||
|
на первом входящем TCP пакете с SYN,ACK. Тогда клиент подумает, что сервер установил
|
|||
|
для него маленький window size и первый сегмент с данными отошлет не более указанной длины.
|
|||
|
В следующем пакете мы не будем менять ничего, поэтому клиент это поймет так,
|
|||
|
что сервер увеличил window size, и все пойдет как обычно.
|
|||
|
|
|||
|
Другие DPI спотыкаются, когда заголовок "Host:" пишется в другом регистре : например, "host:".
|
|||
|
|
|||
|
Как это реализовать на практике в системе linux
|
|||
|
-----------------------------------------------
|
|||
|
|
|||
|
Перехватить пакет с 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 будет небольшая задержка при установлении соединения.
|
|||
|
От 0.5 до 1.5 сек.
|
|||
|
Чтобы не трогать хосты, которые не блокируются провайдером, можно сделать такой ход.
|
|||
|
Создать список заблоченых доменов или скачать его с 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 соединения.
|
|||
|
|
|||
|
|
|||
|
nfqws
|
|||
|
-----
|
|||
|
|
|||
|
Эта программа и есть модификатор пакетов и обработчик очереди NFQUEUE.
|
|||
|
Она берет следующие параметры :
|
|||
|
--qnum=200 ; номер очереди
|
|||
|
--wsize=4 ; менять tcp window size на указанный размер
|
|||
|
--hostcase ; менять регистр заголовка "Host:"
|
|||
|
--daemon ; демонизировать прогу
|
|||
|
|
|||
|
tpws
|
|||
|
-----
|
|||
|
|
|||
|
tpws - это transparent proxy.
|
|||
|
--bind-addr ; на каком адресе слушать
|
|||
|
--port=<port> ; на каком порту слушать
|
|||
|
--split-http-req=method|host ; способ разделения http запросов на сегменты : около метода (GET,POST) или около заголовка Host
|
|||
|
--hostcase ; change Host: => host:
|
|||
|
--daemon ; daemonize
|
|||
|
|
|||
|
Провайдеры
|
|||
|
----------
|
|||
|
|
|||
|
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 адресами.
|
|||
|
|
|||
|
Пример установки на debian 7
|
|||
|
----------------------------
|
|||
|
|
|||
|
Установить пакеты :
|
|||
|
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_reestr.sh
|
|||
|
Зашедулить задание обновления листа :
|
|||
|
crontab -e
|
|||
|
Создать строчку "0 12 * * */2 /opt/zapret/ipset/get_reestr.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:".
|
|||
|
|
|||
|
Что делать с 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_reestr.sh". Это значит в 12:00 каждые 2 дня обновлять список.
|