zapret/https.txt

163 lines
12 KiB
Plaintext
Raw Normal View History

2016-12-22 17:20:28 +03:00
Расскажу как я решал вопрос с блокировкой https на роутере.
На тех провайдерах, что мне доступны, все, кроме одного либо банили https по IP (вообще нет конекта), либо захватывали TLS сессию и она намертво зависала - пакеты больше не приходили. На домру удалось выяснить, что DPI цепляется к SNI (Server Name Indication) в TLS, но сплит TLS запроса не помог. Я пришел к выводу, что https самым разумным будет прозрачно заворачивать в socks.
Tor поддерживает "из коробки" режим transparent proxy. Это можно использовать в теории, но практически - только на роутерах с 128 мб памяти и выше. Таких роутеров не так много. В основном объем памяти 32 или 64 мб. И тор еще и тормозной.
Другой вариант напрашивается, если у вас есть доступ к какой-нибудь unix системе с SSH, где сайты не блокируются. Например, у вас есть VPS вне России. Именно так и поступил.
Понятийно требуются следующие шаги :
1) Выделять IP, на которые надо проксировать трафик. У нас уже имеется ipset "zapret", технология создания которого отработана.
2) Сделать так, чтобы все время при загрузке системы на некотором порту возникал socks.
3) Установить transparent соксификатор. Redsocks прекрасно подошел на эту роль.
4) Завернуть через iptables трафик с порта назначения 443 и на ip адреса из ipset 'zapret' на соксификатор
Буду рассматривать систему на базе openwrt dedicated driver, где уже установлена система обхода dpi "zapret".
По крайней мере нужно иметь заполненный ipset 'zapret', устанавливать tpws или nfqws не обязательно.
Более того, если они на вашей системе не срабатывают, то можно соксифицировать не только https, но и http.
2016-11-07 18:35:40 +03:00
2016-12-22 17:20:28 +03:00
* Сделать так, чтобы все время при загрузке системы на некотором порту возникал socks
2016-11-07 18:35:40 +03:00
2016-12-22 17:20:28 +03:00
Т.к. дефолтный dropbear клиент не поддерживает создание socks, то для начала придется заменить dropbear ssh client на openssh : пакеты openssh-client и openssh-client-utils.
Устанавливать их нужно с опцией opkg --force-overwrite, поскольку они перепишут ssh клиент от dropbear.
После установки пакетов расслабим неоправданно жестокие права : chmod 755 /etc/ssh.
Следует создать пользователя, под которым будем крутить ssh client. Допустим, это будет 'proxy'.
Сначала установить пакет shadow-useradd.
Код:
2016-10-28 12:22:55 +03:00
useradd -d /home/proxy proxy
mkdir -p /home/proxy
chown proxy:proxy /home/proxy
2016-12-22 17:20:28 +03:00
Openssh ловит разные глюки, если у него нет доступа к /dev/tty.
Добавим в /etc/rc.local строчку : "chmod 666 /dev/tty"
Сгенерируем для него ключ RSA для доступа к ssh серверу.
Код:
2016-10-28 12:22:55 +03:00
su proxy
cd
mkdir -m 700 .ssh
cd .ssh
ssh-keygen
ls
exit
2016-12-22 17:20:28 +03:00
Должны получиться файлы id_rsa и id_rsa.pub.
Строчку из id_rsa.pub следует добавить на ssh сервер в файл $HOME/.ssh/authorized_keys.
Более подробно о доступе к ssh через авторизацию по ключам : http://vds-admin.ru/ssh/ssh-autentifikatsiya-po-klyucham-ispolzovanie-programm-ss...ygen-i-ssh-agent
Предположим, ваш ssh сервер - vps.mydomain.com, пользователь называется 'proxy'.
Проверить подключение можно так : ssh -N -D 1098 -l proxy vps.mydomain.com.
Сделайте это под пользователем "proxy", поскольку при первом подключении ssh спросит о правильности hostkey.
Соединение может отвалиться в любой момент, поэтому нужно зациклить запуск ssh.
Для этого лучший вариант - использовать procd - упрощенная замена systemd на openwrt версий BB и выше.
2016-10-28 12:22:55 +03:00
/etc/init.d/socks_vps :
2016-12-22 17:20:28 +03:00
Код:
2016-10-28 12:22:55 +03:00
#!/bin/sh /etc/rc.common
# Copyright (C) 2006-2011 OpenWrt.org
START=50
STOP=50
USE_PROCD=1
USERNAME=proxy
COMMAND="ssh -N -D 1098 -l proxy vps.mydomain.com"
start_service() {
procd_open_instance
procd_set_param user $USERNAME
procd_set_param respawn 10 10 0
procd_set_param command $COMMAND
procd_close_instance
}
2016-12-22 17:20:28 +03:00
Этому файлу нужно дать права : chmod +x /etc/init.d/socks_vps
Запуск : /etc/init.d/socks_vps start
Останов : /etc/init.d/socks_vps stop
Включить автозагрузку : /etc/init.d/socks_vps enable
Проверка : curl --socks5 127.0.0.1:1098 https://btc-e.com
2016-11-07 18:35:40 +03:00
2016-12-22 17:20:28 +03:00
* Организовать прозрачную соксификацию
2016-11-07 18:35:40 +03:00
2016-12-22 17:20:28 +03:00
Установить пакет redsocks. Redsocks есть готовый для CC 15.05.1 и DD, для более старых версий openwrt его можно взять c http://downloads.openwrt.org, либо воспользоваться прекомпилированным статическим бинариком из комплекта "zapret".
Если вы берете ipk с downloads.openwrt.org, то имейте в виду переход с uclibc в CC на musl в DD. Динамические бинарики между ними несовместимы.
2016-10-28 12:22:55 +03:00
/etc/redsocks.conf :
2016-12-22 17:20:28 +03:00
........
local_ip = 127.0.0.1;
local_port = 1099;
........
ip = 127.0.0.1;
port = 1098;
type = socks5;
........
После чего перезапускаем : /etc/init.d/redsocks restart
Смотрим появился ли листенер : netstat -tnlp | grep 1099
Автостарт redsocks при таком конфиге не работает, потому что на момент запуска сеть не инициализирована, и у нас даже нет 127.0.0.1.
Вместо штатного автостарта будем вешаться на события поднятия интерфейса. Разберем это позже.
Пока что отключим автостарт : /etc/init.d/redsocks disable
2016-11-07 18:35:40 +03:00
2016-12-22 17:20:28 +03:00
* Завертывание соединений через iptables
2016-11-07 18:35:40 +03:00
2016-10-28 12:22:55 +03:00
/etc/firewall.user
2016-12-22 17:20:28 +03:00
Код:
2016-10-28 12:22:55 +03:00
SOXIFIER_PORT=1099
. /lib/functions/network.sh
network_find_wan wan_iface
for ext_iface in $wan_iface; do
network_get_device ext_device $ext_iface
iptables -t nat -C OUTPUT -p tcp --dport 443 -o $ext_device -m set --match-set zapret dst -j REDIRECT --to-port $SOXIFIER_PORT ||
iptables -t nat -I OUTPUT -p tcp --dport 443 -o $ext_device -m set --match-set zapret dst -j REDIRECT --to-port $SOXIFIER_PORT
done
sysctl -w net.ipv4.conf.br-lan.route_localnet=1
iptables -t nat -C prerouting_lan_rule -p tcp --dport 443 -m set --match-set zapret dst -j DNAT --to 127.0.0.1:$SOXIFIER_PORT ||
iptables -t nat -I prerouting_lan_rule -p tcp --dport 443 -m set --match-set zapret dst -j DNAT --to 127.0.0.1:$SOXIFIER_PORT
2016-12-22 17:20:28 +03:00
Внести параметр "reload" а /etc/config/firewall в указанное место :
Код:
2016-10-28 12:22:55 +03:00
config include
option path '/etc/firewall.user'
option reload '1'
2016-12-22 17:20:28 +03:00
Перезапуск : /etc/init.d/firewall restart
Все, теперь можно проверять :
2016-10-28 12:22:55 +03:00
/etc/init.d/redsocks stop
curl https://btc-e.com
2016-12-22 17:20:28 +03:00
# должно обломаться с надписью "Connection refused". если не обламывается - значит ip адрес btc-e.com не в ipset,
# либо не сработали правила фаервола. например, из-за не установленных модулей ipt
2016-10-28 12:22:55 +03:00
/etc/init.d/redsocks start
curl https://btc-e.com
2016-12-22 17:20:28 +03:00
# должно выдать страницу
2016-11-07 18:35:40 +03:00
2016-12-22 17:20:28 +03:00
* Автозапуск redsocks
2016-11-07 18:35:40 +03:00
2016-12-22 17:20:28 +03:00
Я сделал для себя небольшой скриптик, вешающийся на события поднятия и опускания интерфейсов.
2016-10-28 12:22:55 +03:00
/etc/hotplug.d/iface/99-exec-on-updown
2016-12-22 17:20:28 +03:00
Код:
2016-10-28 12:22:55 +03:00
#!/bin/sh
local cmd
if [ "$ACTION" = ifup ]; then
cmd=$(uci get network.$INTERFACE.exec_on_up)
[ -n "$cmd" ] && $cmd
fi
if [ "$ACTION" = ifdown ]; then
cmd=$(uci get network.$INTERFACE.exec_on_down)
[ -n "$cmd" ] && $cmd
fi
2016-12-22 17:20:28 +03:00
Теперь можно в описания интерфейсов в /etc/config/nework внести в соответствующий раздел :
Код:
2016-10-28 12:22:55 +03:00
config interface 'wan'
........
option exec_on_up '/etc/init.d/redsocks start'
2016-12-22 17:20:28 +03:00
Теперь reboot. Заходим снова, смотрим, что есть redsocks, есть ssh, опять проверяем curl https://btc-e.com.
Пробуем зайти на https://btc-e.com с компа внутри локалки.
2016-11-07 18:35:40 +03:00
2016-12-22 17:20:28 +03:00
* Если у вас нет своего сервера
2016-11-07 18:35:40 +03:00
2016-12-22 17:20:28 +03:00
Если у вас нет своего сервера, да и просто для упрощения настройки, можно использовать proxy от antizapret.prostovpn.org.
Посмотрите на http://antizapret.prostovpn.org/proxy.pac. Вы увидите список доменов, по которому броузер выносит решение : идти напрямую или использовать proxy. Proxy указано как "proxy.antizapret.prostovpn.org:3128".
Этот прокси работает только на IP назначения из списка https://github.com/zapret-info/z-i/raw/master/dump.csv, на остальные возвращает ошибку, чтобы его не использовали для других целей. Поддерживается метод CONNECT, а значит можно его использовать для проксирования https.
В последней версии "zapret" я добавил скрипт "ipset/get_antizapret.sh". Он парсит список ip от "antizapret" и заносит в ipset "zapret". Это гарантирует, что вызов прокси будет по тем адресам, которые разрешены для проксирования.
2016-11-07 18:35:40 +03:00
2016-12-22 17:20:28 +03:00
* Как изменится вышеописанная процедура
2016-11-07 18:35:40 +03:00
2016-12-22 17:20:28 +03:00
Убираем все, что связано с ssh. Это нам не потребуется.
В /etc/redsocks.conf меняем :
Код:
2016-10-28 12:22:55 +03:00
ip = 127.0.0.1;
port = 1098;
type = socks5;
2016-12-22 17:20:28 +03:00
на :
Код:
2016-10-28 12:22:55 +03:00
ip = proxy.antizapret.prostovpn.org;
port = 3128;
type = http-connect;
2016-12-22 17:20:28 +03:00
В отличие от SSH, TLS хэндшейк теперь пойдет в открытую, то есть DPI его могут высечь из proxy протокола и проверить поле SNI (Server Name Indication).
Так же могут поступить чуть проще : анализировать IP назначения в методе "CONNECT".
Однако, практически это вряд ли будут делать. Если и будут, то немногие.
Но если вы вдруг захотите таким способом проксировать http, то здесь вероятность перехвата и облома очень высока. Многие DPI прекрасно ловят proxy запросы.
Сначала проверьте работает ли у вас antizapret в предложенном ими варианте : http://antizapret.prostovpn.org