Что если вам хочется ходить в сеть без надуманных ограничений, но не хочется каждый раз в браузере подменять прокси? Что если вы хотите заходить и на запрещенные сайты, и на обычные, и чтобы при этом скорость, с которой открываются обычные сайты, не страдала? Что если вам интересно знать что творится в удалённых частях глобальной сети?

Исходя из этих соображений нам нужно чтобы:

  • Обычные сайты открывались как обычно
  • Запрещенные сайты открывались через Tor без настроек
  • Все сайты в зоне .onion тоже открываются без настроек

С одной стороны, требования противоречивые. А другой стороны, чего не сделаешь ради удобства!

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

Важно:

Вы не получите полной анонимности следуя только этим инструкциям. Анонимность без мер OPSEC невозможна. Инструкция подразумевают лишь обход ограничений.

Что нам нужно?

Для начала нам нужен или роутер, или сервер, работающий в качестве прозрачного моста, пропускающего через себя весь трафик. Это может быть и существующий сервер, это может быть и коробочка с Raspberry Pi. Могут подойти и обычные компактные роутеры с Linux, если на них в принципе можно поставить необходимые пакеты.

Если подходящий роутер у вас уже есть, то настраивать отдельно мост не нужно и можно сразу перейти к настройке Tor.

Если же установка Tor на ваш роутер представляет проблему, то вам понадобится любой компьютер с двумя сетевыми интерфейсами и Debian Linux на борту. Его вы в конечном счёте подключите в разрыв сети между роутером, который смотрит во внешний мир, и вашей локальной сетью.

Если не до серверов и роутеров, то возможно получить все то же самое в рамках отдельного компьютера.

Настроим мост

Настройка моста в Debian проблемы не представляет. Вам понадобится программа brctl, которая есть в пакете bridge-utils:

apt install bridge-utils

Постоянная конфигурация для моста задаётся в /etc/network/interfaces. Если вы делаете мост из интерфейсов eth0 и eth1, то конфигурация будет выглядеть так:

# Отметим интерфейсы как настраиваемые вручную
iface eth0 inet manual
iface eth1 inet manual

# Мост поднимается автоматически после перезагрузки
auto br0

# Мост с получением IP по DHCP
iface br0 inet dhcp
  bridge_ports eth0 eth1

# Мост со статическим IP
iface br0 inet static
  bridge_ports eth0 eth1
    address 192.168.1.2
    netmask 255.255.255.0
    gateway 192.168.1.1

Вам нужно выбрать какую-то одну конфигурацию для моста: с динамическим IP или статическим.

Обратите внимание что на этом этапе не обязательно включать сервер в разрыв сети. Можно обойтись и одним подключенным интерфейсом.

Попросим систему применить новые настройки:

service networking reload

Теперь можно проверить существование моста командой brctl show:

# brctl show
bridge name bridge id       STP enabled interfaces
br0     8000.0011cc4433ff   no      eth0
                                    eth1

Посмотреть выданный IP адрес, и проверить вообще факт выдачи какого-то IP по DHCP или статически, можно командой ip:

# ip --family inet addr show dev br0 scope global
4: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 
    inet 192.168.1.2/24 brd 192.168.1.255 scope global br0

Если с IP адресами всё в порядке, то уже можно попробовать включить сервер в разрыв сети...

В конце концов все устройства в вашей сети, будучи включены через сервер, должны иметь полный доступ к глобальной сети будто никакого сервера между ними и внешним роутером нет. То же касается работы DHCP и прочего. Всё это стоит проверить до перехода к настройке Tor.

Если что-то работает не так же, как раньше, или вообще не работает, стоит сначала решить проблемы, лишь потом переходить к настройке собственно Tor.

Настроим демон Tor

Установка Tor выполняется обычно. Установим также базу данных привязки к странам:

apt install tor tor-geoipdb

В конец файла конфигурации /etc/tor/torrc нужно дописать директивы для включения функции прокси-сервера:

VirtualAddrNetworkIPv4 10.0.0.0/8
AutomapHostsOnResolve 1
TransPort 0.0.0.0:9040
DNSPort 0.0.0.0:5300

Перезапустим Tor и проверим что DNS в нашей конфигурации работает на каком-нибудь известном сайте:

# service tor restart
# dig +short facebookcorewwwi.onion @localhost -p 5300
10.11.127.156

Последняя команда должна вывести IP из подсети 10.0.0.0/8.

При перезапуске Tor по делу ругается на использование публичного IP для TransPort и DNSPort, которые в самом деле могут быть доступны посторонним. Исправим это недоразумение, разрешив только соединения из локальной сети (в моём случае это 192.168.1.0/24):

iptables -A INPUT -s 192.168.1.0/24 -p tcp --dport 9040 -j ACCEPT
iptables -A INPUT -s 192.168.1.0/24 -p udp --dport 5300 -j ACCEPT

iptables -A INPUT -p tcp --dport 9040 -j DROP
iptables -A INPUT -p udp --dport 5300 -j DROP

Последние два правила можно пропустить если у вас для цепочки INPUT по умолчанию стоит правило DROP.

Настроим доступ для всей локальной сети

Чтобы все устройства в сети смогли зайти на сайты в Tor нам нужно переадресовать все запросы к выделенной сети 10.0.0.0/8 на порт встроенного прокси-сервера Tor:

iptables -t nat -A PREROUTING -p tcp -d 10.0.0.0/8 -j REDIRECT --to-port 9040
iptables -t nat -A OUTPUT -p tcp -d 10.0.0.0/8 -j REDIRECT --to-port 9040

Два правила для цепочек PREROUTING и OUTPUT мы добавляем чтобы схем работала не только с устройств в сети, но и с самого сервера. Если не требуется чтобы эта схема работала с самого сервера, то добавления правила в цепочку OUTPUT можно пропустить.

Переадресация DNS запросов к зоне .onion

Эту проблему можно было бы решить либо заменой DNS сервера на свой в DHCP ответах клиентам, либо, если у вас в сети не принято использовать локальный DNS сервер, перехватом всего DNS трафика. Во втором случае не нужно будет ровным счетом ничего настраивать, но все ваши клиенты, и вы в том числе, потеряете возможность делать произвольные запросы к произвольным серверам. Это очевидное неудобство.

Мы же будем переадресовать лишь DNS запросы, упоминающие домен .onion, на порт встроенного DNS сервера, оставляя все остальные запросы в покое:

iptables -t nat -A PREROUTING -p udp --dport 53 -m string \
  --hex-string "|056f6e696f6e00|" --algo bm -j REDIRECT --to-ports 5300
iptables -t nat -A OUTPUT -p udp --dport 53 -m string \
  --hex-string "|056f6e696f6e00|" --algo bm -j REDIRECT --to-ports 5300

Магическая строка 056f6e696f6e00 связана с особенностями передачи точки в DNS запросах: она передаётся в виде длины следующей после неё строки. Потому в начале нашей магической строки стоит 0x05 для пяти символов в слове onion. В конце строки стоит нулевой байт 0x00 потому что корневой домен (точка) имеет нулевую длину.

Такой подход позволяет ваши пользователям (и вам самим) пользоваться какими им удобно DNS серверами, а также запрашивать информацию у любых DNS серверов без посредников. Вместе с тем никакие запросы в зоне .onion не будут попадать в открытый интернет.

Теперь попробуйте достучаться до какого-нибудь популярного сайта в сети Tor с любого устройства в локальной сети. Например, так:

$ curl -I facebookcorewwwi.onion
HTTP/1.1 301 Moved Permanently
Location: https://facebookcorewwwi.onion/

Теперь вы можете прочитать эту же страницу через Tor.

Отладка и решение возможных проблем

Если хочется убедиться что никакие DNS запросы к .onion не идут дальше сервера, то их отсутствие можно проверить так:

ngrep -q -d br0 -q -W byline onion udp port 53

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

Если Firefox не видит .onion

Начиная с версии 45.0 в Firefox по умолчанию блокируются запросы к .onion для защиты от случайной деанонимизации, предусмотренной RFC 7686.

Если вам это мешает, а перспектива случайной деанонимизации вас не волнует (ведь мы уже не пускаем DNS запросы к .onion в открытый интернет), отключить эту настройку можно в about:config по ключу network.dns.blockDotOnion.

Мобильный Safari и .onion

Программы под iOS, включая Safari и Chrome, в принципе игнорирует .onion при работе по такой схеме. Как исправить эту проблему в рамках такой схемы мне неизвестно.

Провайдер подменяет IP в DNS

Некоторые провайдеры из экономических соображений, вместо блокировки сайтов по IP или через DPI, лишь подменяют IP для DNS запросов по списку запрещенных сайтов.

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

iptables -t nat -A PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 5300
iptables -t nat -A OUTPUT -p udp --dport 53 -j REDIRECT --to-ports 5300

В моей сети используются IP из 10.0.0.0/8

Нет проблем! Во всех директивах выше используйте какую-то другую подсеть из предназначенных для этого, исключая зарезервированные. Серьезно, обратите внимание на резервированные.

Кроме того, не обязательно использовать сразу весь диапазон - можно ограничиться и подсетью. Например, подойдет 10.192.0.0/10.

Обход блокировок через Tor

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

ExcludeExitNodes {RU}, {UA}, {BY} 

К счастью, и благодаря особенностям работы сети, ответственные ведомства сейчас рекомендуют (?) или использовать DPI, или блокировать сразу по IP. Это работает нам на руку потому что нам не нужно в реальном времени следить за тем, какое доменное имя какого заблокированного сайта резолвится сейчас в какой IP - за нас это уже сделано создателями реестра. Понятно что иногда вы можете всё-таки наткнуться на блокировку если, например, сайт поменял IP, а в реестре его ещё нет.

Если мы работаем только с IP адресами заблокированных сайтов, то для переадресации через Tor запросов к множеству IP лучше использовать программу ipset из одноименного пакета. Создадим таблицу в которой будут храниться все адреса:

ipset -exist create blacklist hash:ip

Теперь мы можем добавить переадресацию для всех IP из списка на порт прокси-сервера Tor:

iptables -t nat -A PREROUTING -p tcp -m multiport --dports 80,443 \
    -m set --match-set blacklist dst -j REDIRECT --to-port 9040
iptables -t nat -A OUTPUT -p tcp -m multiport --dports 80,443 \
    -m set --match-set blacklist dst -j REDIRECT --to-port 9040

В этих правилах мы намеренно указываем только порты под HTTP и HTTPS: вы можете захотеть проверить работу какого-то сайта по другим каналам. Или же, не дай бог, зайти по SSH на какой-то IP из списка.

Проверим переадресацию

Проверим что наша схема с переадресацией в принципе работает. Для этого добавим в черный список IP сайта для проверки настройки Tor.

ipset add blacklist $(dig +short check.torproject.org)

Теперь зайдите на сам проверочный сайт check.torproject.org и убедитесь что вас поздравляют с успешной настройкой.

Если это не так, то проверьте ещё раз что вы задали все правила для iptables. Это можно сделать такой командой:

iptables-save -t nat

Всего у вас должно быть шесть правил в двух цепочках PREROUTING и OUTPUT.

Открываем заблокированные сайты через Tor

Получить список заблокированных адресов можно через API, любезно предоставленное проектом РосКомСвобода. Получим текущий список IP адресов и добавим их в таблицу для разблокировки, предварительно очистив ранее добавленные IP адреса:

ipset flush blacklist
curl reestr.rublacklist.net/api/ips | 
    grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | 
    xargs -n1 ipset add blacklist

Эта операция занимает существенное время, потому ждём спокойно. При этом сам список много памяти не займет - 30 тысяч IP адресов занимают лишь порядка 500 кб.

Проверяем доступность на первом попавшемся запрещенном сайте из списка. Например, на LinkedIn.

Обновляем реестр

Реестр не стоит на месте и список заблокированных сайтов пополняется. Потому вам нужно время от времени выгружать актуальный список IP и добавлять его в ipset. Лучше всего это делать не выгружая весь список целиком каждый раз, а выкачивая только изменения, например, отсюда c GitHub.

#!/bin/bash
set -e
mkdir -p /var/local/blacklist
cd /var/local/blacklist

git pull -q || git clone https://github.com/zapret-info/z-i.git .

ipset flush blacklist
tail +2 dump.csv | cut -f1 -d\; |
   grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' |
   tee /var/local/blacklist/blacklist.txt |
   xargs -n1 ipset add blacklist

Возможно удалять и добавлять только изменившиеся в списке IP, для чего вам может пригодится git whatchanged.

Если вам подходит скрипт выше, то ему самое место в /etc/cron.daily/blacklist-update. Не забудьте дать этому файлу права на выполнение.

chmod +x /etc/cron.daily/blacklist-update

Сохраняем настройки

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

apt install iptables-persistent

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

dpkg-reconfigure iptables-persistent

К сожалению, такого же удобного пакета для ipset пока нет, но эта проблема решается скриптом /etc/network/if-pre-up.d/ipset:

#!/bin/sh
ipset -exist create blacklist hash:ip 
cat /var/local/blacklist/blacklist.txt | 
    xargs -n1 ipset add -exist blacklist

Обязательно нужно дать и этому скрипту права на выполнение:

chmod +x /etc/network/if-pre-up.d/ipset

При следующей перезагрузке этот скрипт выполнится и восстановит список заблокированных IP.

Если забыть о серверах...

Окей, скажите вы, ну а что если я хочу получить все тот же удобный доступ к .onion, но без серверов - локально, на одном компьютере?

Нет проблем! В этом случае все даже проще. Хватить добавить эти три строчки в torrc:

AutomapHostsOnResolve 1
TransPort 9040
DNSPort 5300

Затем эти два правила для iptables:

iptables -t nat -A OUTPUT -p tcp -d 127.192.0.0/10 -j REDIRECT --to-port 9040
iptables -t nat -A OUTPUT -p udp --dport 53 -m string \
  --hex-string "|056f6e696f6e00|" --algo bm -j REDIRECT --to-ports 5300

И можно проверять. Доступ к заблокированным сайтам настраивается по инструкции выше.

Ложка дёгтя

Несмотря на простоту и удобство этот подход наследует часть недостатков сети Tor.

На запрещенные сайты в сети вы заходите от имени выходных узлов, что даёт администраторам выходных узлов принципиальную возможность наблюдать ваш трафик и ваши пароли, если для доступа к целевому сайту не используется шифрование (должны быть https в начале адреса или зеленый замочек 🔒 в адресной строке).

Можно было бы понадеяться что администраторы таких узлов не будут следить за вами из соображений их собственного крепкого ночного сна, но...

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

Вот и все!

Что-то все еще непонятно? Что-то нужно исправить или что-то особенно понравилось? Напишите ниже в комментариях.