/torxy

Rules-based transparent HTTP/HTTPS proxy for the TOR server.

Primary LanguagePython

Что это?

torxy - прозрачный HTTP/HTTPS-прокси, позволяющий перенаправлять трафик на выбранные домены через TOR-сервер.

Идея

Посылами к созданию проекта послужили три причины: блокировки некоторых сайтов, вызванные этим неудобства и полное отсутствие готовых решений. Разумеется, всегда можно завернуть вообще весь трафик в VPN, однако это имеет свои очевидные неудобства. Городить же ужасающие дикие костыли в виде резолвинга доменов в IP для их последующей хитрой маршрутизации это тоже такое себе решение. Хотелось иметь просто прозрачный HTTP/HTTPS-прокси, который можно установить на роутер и заворачивать в TOR не все сайты, а только необходимые.

Какие были пожелания, что прокси должен уметь:

  • Работать в прозрачном режиме;
  • Извлекать из запросов название домена и на основании заданных правил либо проксировать запрос "как есть", либо оборачивать в SOCKS и перенаправлять в TOR-сервер;
  • Поддерживать Server Name Indication, чтобы обрабатывать не только HTTP/1.1, но также и TLS;

Проведённые изыскания готовых решений показали полное отсутствие таковых. Наиболее подходящим на первый взгляд показался проект python-proxy. Однако он не умеет работать в прозрачном режиме и вообще не поддерживает SNI. Идея его допатчить до состояния стояния быстро пропала после изучения исходников, в которых скрупулёзно реализована абстрактная фабрика виртуальных метаклассов c шаблонными методами.

В итоге стало ясно, что придётся засучить рукава и взяться за дело самому.

Область применения

Проект предназначен для сугубо личного использования в небольшой (домашней) локальной сети. На серьёзную нагрузку не рассчитывался и вообще написан "на скорую руку" за один день как "pet-project". Однако, это не значит, что он не работает или работает плохо. Просто применять его следует по назначению.

Как работает

torxy принимает запросы, извлекает из них название домена и в зависимости от заданных правил либо пропускает запрос "как есть", без изменений, либо направляет в SOCKS5-сервер, встроенный в TOR-сервер. Запросы, которые не были распознаны как HTTP или HTTPS, будут пропущены "как есть".

Недостатки

  • Нет поддержки авторизации в SOCKS. Просто потому, что сам прокси и TOR-сервер работают на одном хосте и делать ещё и авторизацию было бы излишне параноидально;
  • Поддерживаются только TLS-подключения, в которых есть SNI. TLS-подключения без SNI будут обрабатываться "как есть", поскольку название хоста при этом неизвестно;

Настройка на роутере

Первым делом требуется добавить на интерфейс lo адрес 169.254.254.254/32. Это необходимо потому, что нельзя просто взять и сделать DNAT на адрес из сети 127.0.0.0/8. Потому как при настройках по-умолчанию ядро воспринимает такие пакеты как martian. Это можно отключить, но лучше не надо.

Добавляем адрес:

ip addr add 169.254.254.254/32 dev lo

Далее, для прозрачного проксирования нужно добавить правило DNAT:

iptables \
    -A PREROUTING \
    -s $LAN \
    -p tcp -m multiport --dports http,https \
    -j DNAT --to-destination 169.254.254.254:3128

Где $LAN - адрес локальной сети, например 10.193.68.0/24.

Настройки TOR-сервера выходят за рамки данного мануала, лучше будет обратиться к официальной документации. Для работы прокси нужно чтобы TOR-сервер принимал подключения по протоколу SOCKS5 без авторизации на порту 9050 (или любом другом).

Вариантов настройки DNS для зоны .onion много, один из них таков. В конфиге dnsmasq.conf добавляем запись:

address=/onion/$ROUTER

Где $ROUTER - локальный адрес роутера. Тогда любой домен в зоне .onion будет указывать на роутер, что в итоге приведёт к попаданию запроса в прокси, который с этим уже разберётся.

Правила перенаправления

Запрос, подпадающий под правило, будет направлен в SOCKS-сервер, предоставляемый сервером TOR.

Важно! Поиск по списку правил выполняется за O(n). То есть, не стоит добавлять туда слишком много правил, иначе запросы начнут дичайше тормозить.

Конфиг с правилами по-умолчанию находится в файле /etc/torxy.rules. По одному правилу на строку. Строки, начинающиеся с символа # считаются комментариями. Сравнение производится до первого совпадения. Сравнение выполняется методом вхождения подстроки в строку. Регулярные выражения не поддерживаются. Под сравнение подпадают только имена хостов (заголовок Host: в HTTP или SNI в TLS), URL не поддерживаются.

Примеры правил:

# Вся зона .onion.
.onion

# Один отдельный сайт.
homedepot.com

Сравнение по методу вхождения подстроки в строку подразумевает, что заданное правило ищется как подстрока в имени хоста в запросе. То есть:

Правило: example.com Хост: example.com => Правило сработало. Хост: www.example.com => Правило сработало. Хост: example.com.net => Правило сработало. Хост: example.org => Правило НЕ сработало.

Метод имеет свои недостатки, например правило сработает на хост notexample.com. Однако, является достаточно разумным компромиссом между гибкостью и удобством. Регулярные выражения были бы ещё более гибкими, но менее удобными, а wildcards (*.) потребовали бы создавать несколько записей для одного хоста (с www и без www).

Системные требования

Установка

Пример пакетирования под archlinux.

Запуск и управление

См. torxy --help. Поддерживается перезагрузка правил без остановки, по сигналу SIGHUP.

Лицензия

GPL.