Обсудим, как сделать шлюз из Интернета в скрытые сайты Tor.
Сеть Tor — это система прокси-серверов, позволяющая устанавливать анонимное сетевое соединение. С помощью Tor можно анонимно подключаться к обычным серверам и хостить непрослушиваемые серверы в самой сети Tor. В последнем случае создается скрытый сервер в зоне onion. Имя сервера включает 16 букв и цифр (фингерпринт).
Как можно заходить на скрытые серверы:
- установить Tor и направить через него трафик браузера. Tor-браузер — это portable-приложения, которое включает всё необходимое;
- однако не все люди устанавливают Tor-браузер, поэтому нужен способ показать содержимое скрытого сервера обычному пользователю сети. На помощь приходят сервисы tor2web, предоставляющие прямой доступ к скрытым сайтам.
Сайт Hidden Wiki (kpvzxxbbraaigawj.onion) можно открыть в обычном браузере (kpvzxxbbraaigawj.tor2web.fi). Если пользователь подключается к сайту через tor2web, то он теряет анонимность в обмен на доступ к скрытому сайту без установки Tor. Приведу список подобных сервисов, некоторые из которых закрылись.
- *.Tor2web.org (3 сервера)
- *.Tor2web.fi
- *.Tor2web.blutmagie.de
- *.onion.sh (отключен)
- *.onion.to (отключен)
- *.onion.lu (отключен)
- *.t2w.pw (отключен)
- *.tor2web.ae.org (отключен)
Рассмотрим существующие способы запустить tor2web-сервис, после чего я поделюсь своим собственным.
Проект Tor2web-3.0?
Tor2web-3.0 — важная часть проекта GlobaLeaks, которая облегчает доступ пользователей сети к скрытым серверам.
Пример сайта: kpvzxxbbraaigawj.tor2web.org
К проекту Tor2web-3.0 подключено 3 сервера. Можно установить Tor2web на свой сервер и примкнуть к их сети. Отключенные серверы .lu и .to принадлежат тем же людям.
Tor2web-3.0 устанавливается как отдельная служба. Код написан на Python. К Tor2web-3.0 практически нет нареканий, но мне хотелось избежать дополнительного участника (пользователь — Nginx — Tor2web-3.0 — Tor — целевой сайт). Кроме того, мне не по душе сетевой софт, написанный на Python.
Polipo?
Polipo — HTTP-сервер, который умеет перенаправлять подключения в SOCK5-сервер. Раньше Polipo использовался для этой цели в составе Tor-браузера.
Можно было бы выстроить цепочку: Nginx — Polipo — Tor. Как и в случае с Tor2web-3.0, возникает лишний участник, так как Nginx не умеет проксировать трафик через SOCK5-сервер. Кроме того, для нормального отображения сайтов хочется заменять в ответе сервера onion-ссылки ссылками на шлюз: s/.onion/.onion.xx/
Патчим Nginx?
Существует патч для Nginx, который добавляет возможность проксировать трафик через SOCK5-сервер. На самом деле, протокол SOCKS5 очень простой, поэтому странно, что до сих пор нет официального модуля. Это решение выглядит заманчивым, но оно не доведено до ума: пришлось бы патчить Nginx при каждом обновлении. Хочется иметь решение, которое бы работало на обычном Nginx из
Пишем модуль для Nginx на Lua
Nginx давно поддерживает возможность встраивать сценарии на Lua. Коду на Lua предоставляется широкий круг возможностей, в том числе манипуляции с сокетами прямого доступа. К сожалению, модуль для подключения к SOCKS5-серверу я не нашел, поэтому написал свой. Для каждого запроса устанавливается соединение с программой Tor через порт 9050, проходит рукопожатие SOCKS5 и передаётся адрес целевого сайта. После этого сокет используется, как если бы это был прямой сокет к целевому сайту. Запрос пользователя считывается в память, редактируется и передаётся серверу. Ответ сервера считывается, редактируется (замена ссылок) и передается пользователю. Все операции неблокирующие. Эту часть я оформил как отдельный модуль onion2web.
При первом подключении к сайту пользователь видит заглушку с формой подтверждения захода на сайт. Это нужно, чтобы нельзя было включать картинки со скрытых сервисов в страницы обычных сайтов.
Модуль socks5 содержит функции, с помощью которых сокет пробрасывается через SOCK5-сервер. Функции описаны на страничке модуля. Модуль onion2web содержит одну функцию handle_onion2web, которая обслуживает tor2web-шлюз. Пример использования см. ниже. Есть возможность задать адрес и порт тора и отключить форму подтверждения захода на сайт.
Недоработки:
- реализован очень простой HTTP-клиент версии 1.0, в котором отключены keep-alive и сжатие передаваемых данных.
- Запрос и ответ читаются целиком в память, после чего передаются получателю. Это увеличивает расход памяти и замедляет передачу информации, особенно в направлении от сайта к пользователю. Подозреваю, что с SOCKS5-сервером нужно общаться в отдельной сопрограмме. Возникнут сложности с подменой адресов в ответе сервера (граница блоков данных может прийтись на заменяемый адрес).
- Форма загрушки не содержит защиты от CSRF и всегда перенаправляет на главную страницу (лучше перенаправлять на путь, который был открыт изначально).
- Ответ сервера надо редактировать более аккуратно: заменять ссылки только в HTML и только в атрибутах.
На этом варианте я и остановился и использовал его для своего tor2web-шлюза. К недостаткам самого сайта можно отнести отсутствие SSL. Думаю, есть и другие недостатки. И вообще пока решение скорее костыльное.
Как поднять свой tor2web-шлюз
Нужны домен, сервер и wildcard SSL-сертификат на этот домен.
В домене нужно прописать всем поддоменам IP-адрес нашего сервера:
На сервере потребуется Tor, Nginx со свежим ngx_lua и мой модуль onion2web для подключения к SOCKS5-серверу из Nginx. В Debian Wheezy есть пакет nginx-extras, который содержит слишком старый ngx_lua. (Этой старый ngx_lua не поддерживает некоторых используемых методов, например, ngx.req.raw_header.) Версия nginx-extras из wheezy-backports содержит достаточно свежий ngx_lua. Модуль onion2web можно установить через luarocks (это автоматически установит модуль socks5 как зависимость).
Установка для Debian Wheezy:
# echo deb http://ftp.us.debian.org/debian/ wheezy-backports main > /etc/apt/sources.list.d/wheezy-backports.list
# apt-get update
# apt-get install tor luarocks nginx-extras/wheezy-backports
# luarocks install onion2web
В Nginx создаем такой сайт:
server {
listen 80;
server_name *.onion.gq;
location / {
default_type text/html;
content_by_lua '
require("onion2web").handle_onion2web(".onion.gq");
';
}
}
Домен фигурирует в конфиге в двух местах: server_name и внутри Lua-кода.
Сайт готов: kpvzxxbbraaigawj.onion.gq
Исходники модуля socks5: github.com/starius/lua-resty-socks5
Исходники модуля onion2web: github.com/starius/onion2web