вторник, 19 августа 2014 г.

Squid: Tor + Privoxy + transparent DNS redirect. Часть II

Как мы это делаем? Всегда правой!


Введение

В предыдущей статье я вкратце описал техники блокирования. В этой части мы рассмотрим реализацию игнорирования блокировок в масштабе сети любого размера. :) То бишь на предприятии.

Суть предложенной комплексной методики заключается в залповом решении проблем обхода всех известных видов блокировок даже при их одновременном разнобойном применении. С сохранением полной невидимости для провайдера - МарсТелекома - и сохранением части трафика открытым. Дабы не смущать марсиан.

Как и в случае автомата Калашникова, составные части известны. Я всего лишь собрал их в кучу и заставил относительно эффективно и прозрачно работать. ;)

С некоторой степенью уверенности можно говорить, что заблокировать такой доступ можно лишь полным отключением Интернета для использующей методологию сети.

Я еще раз подчеркиваю - гарантированный пробой блокировок МарсТелекома обеспечивается лишь при выполнении всех частей методологии. 

Обеспечение чистого DNS

Нам необходимо обеспечить чистый источник DNS-ответов: избегать широко известных публичных сервисов, которые легко прозрачным образом перехватить, использования корневых серверов, общеизвестных стандартных (и легко перехватываемых) портов.

Мы предполагаем, что у вас уже есть сервер с работающим Squid, Unbound и dnscrypt. Читать здесь, здесь и здесь.

Итак, у нас есть настроенный Squid, Unbound и dnscrypt.

Нам надо немного скорректировать конфигурации для обеспечения максимальной безопасности получения DNS-данных.

dnscrypt

Вам потребуется последний dnscrypt. Он содержит CSV-список провайдеров, поддерживающих шифрованный доступ.

Изменим конфигурацию. 

Надо отказаться от использования OpenDNS - его адреса и порты безопасного доступа известны.

Первое. Выберем в качестве провайдера dnscrypt.eu-dk, например. Из списка $BASE_DIR/share/dnscrypt-proxy/dnscrypt-resolvers.csv . 
Второе. Во избежание прозрачного перехвата UDP/53, пожертвуем производительностью (у нас все равно позади dnscrypt стоит кэш DNS) и будем использовать только TCP (ключ --tcp-only у dnscrypt).

Перезапустим сервис. Убедимся, что мы получаем DNS-ресловинг от выбранного сервиса.

Unbound

Unbound требует некоторой модификации в конфигурации. 

Первое. Необходимо исключить обращение к корневым DNS. Закомментируйте параметр root-hints: "/etc/opt/csw/unbound/named.root"
Второе. Уберите любые ссылки на открытые (и уязвимые) форвардеры:

forward-zone:
name: "."
forward-addr: 127.0.0.1@5553

У вас должна остаться единственная ссылка на dnscrypt.

Перезапустите Unbound и убедитесь, что кэш пуст.

ВАЖНО
Учтите следующее. Перед вашим транспарентным прокси наверняка стоит маршрутизатор, или switch L3, выдающий динамикой адреса, шлюз и DNS. Однако стоит учитывать тот факт, что, во-первых, у вас есть не только динамические клиенты, но и те, которые прописали параметры TCP вручную. А во-вторых, прокси у вас прозрачный - но есть и другие клиенты - не-HTTP - которым тоже нужен чистый DNS для работы - Google Drive, IRC, итп., которые могут идти мимо транспарентного прокси.

Поэтому проделаем на внутреннем роутере (который форвардит HTTP на прокси по WCCP) транспарентный перехват всех вообще DNS-запросов нашей собственной сети (Cisco):

ip access-list extended transparent_dns
permit udp any any eq 53
!
route-map redirect_dns permit 10
match ip address transparent_dns
set ip next-hop ip.of.your.server
route-map redirect_dns permit 20
!
interface fax/x
ip address xxx.xxx.xxx.xxx xxx.xxx.xxx.xxx
ip policy route-map redirect_dns
!

Как видно из примера, мы будем переотправлять все вообще запросы с Cisco DNS proxy только на наш собственный кэш, где уже стоит Unbound+dnscrypt. Так надо.

Да, это та же самая методика, что и у МарсТелекома. ;) Только с противоположной целью. :)

Tor + Privoxy

Небольшое пояснение, на кой нужна именно такая связка. 

Дело в том, что Tor- не HTTP-прокси. И его нельзя сделать прямым peer для нижележащего (и кэширующего) Squid'а. Полноценно он предоставляет SOCKS-проксирование (разумеется, в числе прочих функций), о чем будет написано ниже.

Tor
Первое, конечно же, Tor. В принципе, вы можете настроить его как угодно - только как клиент, как бридж, как релэй. Достаточно одной клиентской конфигурации. Но если вы имеете постоянное (и достаточно скоростное) подключение - лучше релэй или бридж. ВАЖНО: Не делайте его выходной нодой. Так меньше шансов, что МарсТелеком возьмет вас за задницу и/или забанит IP (особенно в случае статики). Кстати, примите как данность, что выходные ноды и так весьма часто попадают под бан - на сервисах в том числе. Вопросы производительности тоже немаловажны (вы же через туннель будете качать приличный объем, поэтому либо не включайте аккаунтинг Tor вообще - либо задайте его достаточно высокой дневной величиной - согласно вашей собственной статистике), поэтому позаботьтесь о резервировании достаточной полосы пропускания в конфигурации собственно Tor (в идеале не менее полной максимальной полосы пропускания вашего канала - так задержки при прогрузке сведутся к минимуму).

Приведу собственную конфигурацию (Имя ноды, по понятным причинам, изменено ;)):

SocksPort 9050
Log notice file /var/log/tor.log

RunAsDaemon 1
CookieAuthentication 1

ORPort 9001

Nickname FuckYouMan

RelayBandwidthRate 400 KB #
RelayBandwidthBurst 800 KB #

AccountingMax 100 GB
AccountingStart day 00:00
# NOTE: Monitoring statistics can not get if accounting not configured

## Uncomment this if you run more than one Tor relay, and add the identity
## key fingerprint of each Tor relay you control, even if they're on
## different networks. You declare it here so Tor clients can avoid
## using more than one of your relays in a single circuit. See
## https://www.torproject.org/docs/faq#MultipleRelays
## However, you should never include a bridge's fingerprint here, as it would
## break its concealability and potentionally reveal its IP/TCP address.
#MyFamily $keyid,$keyid,...

#ExitPolicy accept *:6660-6667,reject *:* # allow irc ports but no more
#ExitPolicy accept *:119 # accept nntp as well as default exit policy
ExitPolicy reject *:* # no exits allowed

Обратите внимание - мы сконфигурировали SOCKS-вход со стандартным портом в сеть Tor, доступный (по умолчанию) только с localhost. Если хотите торифицировать другие сервисы в локальной сети, укажите также адекватный ACL (не откуда хочешь! а то подарите анонимный SOCKS-прокси хакерскому сообществу) для, скажем, 192.168.0.0/16.

Privoxy
Теперь надо установить и сконфигурировать Privoxy. Последняя версия Privoxy берется на http://www.privoxy.org, конфигурируется хитрым образом, и собирается в нужной разрядности:


0. groupadd privoxy
useradd -g privoxy -c "privoxy_daemon" -d /var/empty -s /bin/false privoxy

1. make && make clean

2.
# 32 bit GCC
./configure --prefix=/usr/local/privoxy --enable-large-file-support --with-user=privoxy --with-group=privoxy --disable-force --disable-editor --disable-toggle 'CFLAGS=-O3 -m32 -mtune=core2 -pipe'

# 64 bit GCC
./configure --prefix=/usr/local/privoxy --with-user=privoxy --with-group=privoxy --disable-force --disable-editor --disable-toggle 'CFLAGS=-O3 -m64 -mtune=core2 -pipe' 'LDFLAGS=-m64'

3.
gmake
gmake install-strip


Учтите, что для Solaris придется написать SMF-сервис. Или взять мой.

Конфигурация Privoxy (показаны только те параметры, которые реально требуется менять/задавать):

listen-address 127.0.0.1:8118
toggle 0
enable-remote-toggle 0
enable-remote-http-toggle 0
enable-edit-actions 0
forward-socks5t / localhost:9050 .
max-client-connections 4096


Точка в строке forward-socks5t - не опечатка!

В зависимости от нагрузки на туннель, может потребоваться скорректировать значение max-client-connections.

Запустим Privoxy. Убедимся, что сервис работает и слушает порт 8118. Итак, мы нацелили его на наш SOCKS5-вход Tor и слушаем HTTP/HTTPS запросы на порту 8118. Ролью Privoxy будет трансляция HTTP(S) в SOCKS5t. Напоминаю, что Privoxy - не кэширующий прокси! Кэшированием у нас будет заниматься Squid.

UPDATE

Начиная с версии Tor 0.3.2, его теоретически можно использовать непосредственно как туннелинговый HTTP-прокси. Это теоретически избавляет нас от необходимости использовать лишний сервис.

Для этого достаточно добавить в torrc следующую строку:

 # Starting from Tor 0.3.2  
 HTTPTunnelPort 8118   

Однако тут нас подстерегает вот такая ошибка. Она означает, что Тор может туннелить только HTTPS-соединения, от начала до конца HTTPS.

Казалось бы, в 2018 году это нормально, да? Мамкины летсэнкриптщики торжествуют и всякое такое.

Однако черта с два.

Когда пользователь набирает в командной строке браузера torproject.org, он не будет писать "https://torproject.org". Нет, он наберет "torproject.org" и нажмет Enter. И соединение начнется по HTTP. Прилетит на сервер, на котором mod_rewrite перепишет URL под https. В эту точку ваш Тор уже не придет. Он отвалится раньше (и браузер покажет пустую страницу под HTTP), так как он не туннелит по

HTTPTunnelPort

собственно HTTP (И вот нафига было называть параметр HTTPTunnelPort, если он работает только для HTTPS? Назвали бы HTTPSTunnelPort. Каждый программист - метросексуал). А совсем не каждый браузер в принципе имеет установленный плагин HTTPSEverywhere. Впрочем, вы можете попробовать установить его в каждый браузер каждого клиентского устройства. Расскажете, что получится в этом случае. :)

Мы понимаем, что налицо совокупность гомосексуальности программистов Тор, браузеров, нас нет, мы не программисты и гетеросексуальны. Однако все это в существующем виде не позволяет нам выкинуть Privoxy. Так что терпите. Мамкины админы, которые это советуют - просто никогда не пробовали делать подобные вещи на практике. Гребаные диванные теоретики.

 

Squid

Итак, у нас уже есть настроенный транспарентный Squid с качественным кэшированием (ну и сохранением в дисковом кэше роликов Ютуба, в идеале ;)). Осталось доделать совсем немного.

Небольшое пояснение. Мы будем торифицировать только некоторые URL, остальной трафик будем выпускать как есть (ну, через Squid, разумеется). Регулярные выражения редиректов поместим в отдельный текстовый файл. И - так как мы будем видеть входы в туннель из внутренней сети, для защиты нас и наших пользователей, запретим журналировать доступы к Tor-сети (остальные доступы так и будут писаться в access log). Нам же дорога их и наша приватность, верно? ;)

Вот что нужно добавить в конфигурацию Squid:

# Tor acl
acl tor_url url_regex "/usr/local/squid/etc/url.tor"

# Tor access rules
never_direct allow tor_url

# Local Tor is cache parent
cache_peer 127.0.0.1 parent 8118 0 no-query no-digest default

cache_peer_access 127.0.0.1 allow tor_url
cache_peer_access 127.0.0.1 deny all

# We don't log tor tunnel access - Squid 2.x rule
log_access deny tor_url

# For Squid 3.x log_access is deprecated:
access_log daemon:/data/cache/log/access.log buffer-size=256KB logformat=squid !tor_url

# For Squid 4.x:
acl hasRequest has request
access_log daemon:/data/cache/log/access.log buffer-size=256KB logformat=squid hasRequest !tor_url


Файл /usr/local/squid/etc/url.tor содержит регулярные выражения url_regex, по которым мы будем выборочно заворачивать в туннель Tor заданные URL:

livejournal\.com.*
youtube.*
ytimg.*
googlevideo.*
google.*
googleapis.*
googleusercontent.*
gstatic.*
gmodules.*
blogger.*
blogspot.*
telegram.*
tdesktop.*
torproject\.org.*

Дополнить список согласно своему желанию. :)

Перезапускаем Squid, проверяем - вуаля.

Масштабирование

Специально для мамкиных админов и диванных теоретиков Хабра:

Те из вас, кто заявляет, что Тор - медленный: с разморозкой! Вылазьте из криокамеры, посмотрите на календарь, попробуйте - и не надо трындеть о том, что лично вы не пробовали.

Тор в настоящее время достаточно быстр. А если вы желаете и рыбку съесть и шкурку сдать, то у меня для вас плохие новости: бесплатный сыр бывает только в мышеловке и только лишь для второй мыши. Претензии к скорости интернета (Ютубчик, торрентики) в подобном решении предъявляйте к РКН, а не к решению.

Описываемое решение достаточно легко масштабируется. Настроенный ванильный Squid (не с конфигурацией по умолчанию) может быть легко отмасштабирован до 5000+ клиентских станций за ним для одного инстанса. Privoxy и Tor могут быть отмасштабированы как собственными настройками, так и запуском множества экземпляров процессов на разных портах. Например, Privoxy по умолчанию тредовый (он, в общем-то, не для десктопа писался):

#  3.2. single-threaded
#  =====================
#
#  Specifies:
#
#      Whether to run only one server thread.
#
#  Type of value:
#
#      1 or 0
#
#  Default value:
#
#      0
#
#  Effect if unset:
#
#      Multi-threaded (or, where unavailable: forked) operation, i.e.
#      the ability to serve multiple requests simultaneously.


Описываемая конфигурация легко осиливает 300-500 рабочих станций локальной сети. Разумеется, при условии, что вы не будете пытаться тащить через Тор торренты, смотреть дурацкие сериалы или пялиться в Youtube.

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

Врубаетесь? Но это надо брать и делать, а не ставить софт из репов с дефолтными конфигами ныть по форумам, как это медленно и печально работает. Масштабируемого автоматически из коробки софта - не существует.


Заключение

Обратите внимание на следующее.

Соединение видите только вы, до точки входа в туннель, причем отключив журналирование конкретно редиректного ACL вы (и Те, Кому Надо) перестаете их видеть. Только прямой трафик кэширующего прокси. Дальше, начиная с вашей точки доступа, никто ничего не видит - ни DNS-запросов, ни туннелированного трафика. Просто шифрованные сессии.

Что со скоростью?

После подстройки параметров производительности промежуточных звеньев  вы получаете весьма приличную производительность (во всяком случае, существенно выше, чем у Tor Browser). HTTPS, идущий через Tor, кэшироваться, к сожалению, не будет (туннелинг без рекриптинга, увы).

Почему МарсТелеком может не напрягаться по поводу данного решения? (а он может не напрягаться)

Потому, что среднестатистический хомяк всего этого ниасилит. :) Никогда. :)

Он скорее потащится на Яндекс, давиться мусором, рекламой ну и сорить на всех углах своей приватностью и правом свободы выбора.  :)