Перенаправляем весь трафик через TOR
Бывают ситуации когда необходима анонимность, но VPN под рукой нет. И VPN вряд ли можно назвать анонимным инструментом, ведь вы на него заходите как правило со своего IP (если это не двойной VPN), а значит оставляете следы, даже если не ведутся логи. Что уж говорить о VPN-услугах, которые вы покупаете у чужих людей. Они в свою очередь чаще всего ведут и логи и сниффают трафик и при любом обращении местных спецслужб эту информацию послушно предоставляют.
TOR — неплохой инструмент для анонимности и иногда необходимо через него пропускать не только трафик из вашего браузера (что делает например tor-browser), но и вообще трафик всей системы + не все необходимые вам программы могут поддерживать socks-прокси.
Установка и настройка TOR
Для настройки используется конфиг /etc/tor/torrc, открываем/создаём и вписываем туда следующее:
VirtualAddrNetworkIPv4 10.192.0.0/10 AutomapHostsOnResolve 1 TransPort 9040 DNSPort 53 # для жителей СНГ рекомендую исключить Exit-ноды следующих стран ExcludeExitNodes ,,
Настройка DNS
Использовать ДНС-сервера от Google, либо чьи-нибудь ещё — плохая идея, т.к. они тотчас вас деанонимизируют. Будем использовать локальный ДНС средствами TOR. Для выполним следующее:
$ sudo rm -f /etc/resolv.conf # удалим, т.к. иногда это сим-линк $ echo "nameserver 127.0.0.1" | sudo tee /etc/resolv.conf
Поскольку всякие NetworkManager очень любят перезаписывать этот файл — лучше его вообще залочить на запись:
$ sudo chattr +i /etc/resolv.conf
(для анлока вместо +i используйте -i)
Настройка Iptables и проверка работоспособности
Создаём скрипт iptables_setup.sh:
#!/bin/sh ### set variables #destinations you don't want routed through Tor _non_tor="192.168.1.0/24 192.168.0.0/24" #the UID that Tor runs as (varies from system to system) _tor_uid="XYZ" # XYZ меняем на UID пользователя TOR (!) #Tor's TransPort _trans_port="9040" ### flush iptables iptables -F iptables -t nat -F ### set iptables *nat iptables -t nat -A OUTPUT -m owner --uid-owner $_tor_uid -j RETURN iptables -t nat -A OUTPUT -p udp --dport 53 -j REDIRECT --to-ports 53 #allow clearnet access for hosts in $_non_tor for _clearnet in $_non_tor 127.0.0.0/9 127.128.0.0/10; do iptables -t nat -A OUTPUT -d $_clearnet -j RETURN done #redirect all other output to Tor's TransPort iptables -t nat -A OUTPUT -p tcp --syn -j REDIRECT --to-ports $_trans_port ### set iptables *filter iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT #allow clearnet access for hosts in $_non_tor for _clearnet in $_non_tor 127.0.0.0/8; do iptables -A OUTPUT -d $_clearnet -j ACCEPT done #allow only Tor output iptables -A OUTPUT -m owner --uid-owner $_tor_uid -j ACCEPT iptables -A OUTPUT -j REJECT
Переменную _tor_uid меняем на uid пользователя под которым работает tor. Определить это значение можно так:
$ grep tor /etc/passwd debian-tor:x:135:145::/var/lib/tor:/bin/false
Первая цифра, то есть 135 — uid, меняем в скрипте
Заворачиваем весь трафик ОС в Tor
В последнее время анонимность в сети является предметом горячих споров. Ни для кого не секрет, что данные о посещениях Интернет-ресурсов с локального устройства могут собираться на разных уровнях с целью построения «модели» пользователя, которая позже против него же и может быть использована (или могла бы). Поэтому не удивительно, что все большее количество активных пользователей Интернета становятся уверены в необходимости механизмов проксирования и анонимизации. В связи с этим появляется все больше новых VPN-клиентов, но, как показывает практика, далеко не всем из них по-настоящему можно доверять: то не все работает из коробки, то анонимизируется только HTTP-трафик, то качество реализации хромает, а то и вовсе разработчики грешат сливанием данных о своих пользователях.
В этой статье мы попробуем собрать из ряда программных компонентов собственный инструмент с UI, который бы позволил полностью анонимизировать трафик локальной системы и не допустить утечек по «прослушиваемым» каналам ни на одном из этапов работы.
Главной нашей целью будет «сборка» надежной утилиты из готовых инструментов. Очевидно, что идея создания с нуля качественного инструмента за разумный срок чревата ошибками, а поэтому бытрее и надежнее будет выбрать готовые компоненты, а затем правильно их связать!
Что должен уметь инструмент?
- Перенаправлять весь трафик целевой системы на промежуточные узлы (желательно несколько) для надежной маскировки источника
- Отслеживать возможные нарушения анонимности, исправлять их и сообщать о них с помощью UI уведомлений
Компонент №1: Tor
Именно вокруг этого компонента будет построена вся остальная инфраструктура инструмента. Tor предоставляет механизм, который находится в составе любого VPN-клиента — механизм заворачивания трафика через промежуточные анонимные для внешнего наблюдателя узлы (в стандартной конфигурации таких узла 3).
По умолчанию клиент Tor из стандартных пакетных репозиториев после установки начинает слушать порт 9050, принимающий любого клиента, «умеющего» socks. Проблема заключается в том, что помимо socks-трафика в нашей системе может быть куча другого трафика от приложений, не работающих по этому протоколу. В связи с этим прежде всего в пределах локальной системы придется прорубить окно в сеть Tor для любого нового сетевого соединения. Делается это достаточно просто с помощью поднятия transparent proxy в конфигурации torrc:
/etc/tor/torrc . TransPort 9040 # а это нам еще понадобится в дальнейшем для автоматизации из python ControlPort 9051 .
Отдельного внимания заслуживает UDP трафик. Дело в том, что в основе принципа луковой маршрутизации лежит концепция «соединения» (stream), существующего, как известно, только в TCP. Отправив через Tor UDP-пакет, целевая система не сможет получить на него ответ, так как ответный пакет не найдет обратной дороги. Но несмотря на эту особенность, у нас остается возможность анонимизировать DNS запросы, которые, как известно осуществляются по UDP, а заодно и включить .onion резолв:
/etc/tor/torrc . AutomapHostsOnResolve 1 DNSPort 53 .
На этом доступ в Tor открыт в пределах loopback’а.
Компонент №2: Iptables
Так как наша задача заключается в сокрытии истинного источника трафика от внешнего наблюдателя в пределах всей системы, а окно в Tor уже открыто, осталось только завернуть весь трафик в это окно. Поможет нам в этом системный файрвол, находящийся в комплекте с ядром Linux:
# заворачиваем tcp iptables -t nat -A OUTPUT -p tcp --syn -j REDIRECT --to-ports $TRANS_PORT # заворачиваем частично udp (dns only) iptables -t nat -A OUTPUT -p udp --dport 53 -j REDIRECT --to-ports 53 iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # запрещаем всему остальному трафику покидать систему iptables -A OUTPUT -j REJECT ip6tables -A OUTPUT -j REJECT
На данном этапе мы получаем рабочую утилиту, надежно маскирующую весь исходящий трафик, однако это только половина работы.
Компонент №3: python + Desktop Evironment UI
Каждый раз производить ручную конфигурацию из консоли (даже если это будет запуск bash-скрипта) будет достаточно утомительно, поэтому самое время приступить к написанию небольшой утилиты, помогающей нам конкретно в следующем:
- Автоматическая установка конфигурации
- Смена своего identity в пределах Tor в любой момент
- Отслеживание целостности правил iptables и их перезапись при нарушении
- Отслеживание текущего identity (IP)
- Уведомление о двух предыдущих пунктах с помощью уведомлений графическогой оболочки
При желании смены своего внешнего IP адреса, будет происходить взаимодействие со служебным портом Tor — 9051, открытым в самом начале для автоматизации смены IP:
with Controller.from_port(port = 9051) as controller: controller.authenticate() controller.signal(Signal.NEWNYM)
Отслеживание целостности можно реализовать достаточно банально (делаем же на коленке) с помощью периодического чтения структуры правил iptables и проверки их SHA256-суммы:
def rulesOk(self): RULES_CHECKSUM_CMD = " < iptables-save && ip6tables-save; >| sed s/\-\-uid\-owner\\\\s2\\\\+\\\\s//g | grep -viE '^#' | grep -viE '^\:' | sort | uniq | sha256sum | cut -d' ' -f 1" checkSum = getoutput(RULES_CHECKSUM_CMD).strip() alright = checkSum == Strings.RULES_CHECKSUM_CORRECT_HASH if not alright: rules = getoutput('iptables-save && ip6tables-save') self.lastSnapshotFileName = "/tmp/broken-rules-%s.log" % time.strftime("%d-%m-%Y_%I-%M-%S") open(self.lastSnapshotFileName, "w").write(rules) return False else: return True
Также при обнаружении несостыковок с ожидаемой контрольной суммой можно сохранить дамп правил iptables в /tmp/broken-rules-%d-%m-%Y_%I-%M-%S.log для дальнейших разбирательств. Если окажется, что
то будет инициирована перезапись таблицы правил iptables.
Наблюдение за текущим IP будет происходить с помощью постоянного обращения на какой-нибудь внешний ресурс, предоставляющий IP-клиента — например, ident.me .
Ну, и напоследок задействуем DE UI для сообщения о проблемах с правилами либо о смене IP. Каждое графическое окружение в каком-то роде уникально, особенно когда речь идет об использовании UI из процесса-демона, но все же на большинстве Linux’ов такой bash-код, вызываемый из Python будет успешно показывать уведомления:
# root UI eval "export $(egrep -z DBUS_SESSION_BUS_ADDRESS /proc/$(pgrep -u $LOGNAME gnome-session)/environ)" export DISPLAY=:0 for USR in `ls /home && echo root` do # ubuntu gnome + root UI export XAUTHORITY=/home/$USR/.Xauthority notify-send -u '' '' # ubuntu parallels for UID in `ls /run/user/` do su $USR -c "DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$UID/bus notify-send -u '' ''" done done
Объединив все это в 200-строчном Python скрипте, получаем то, чего добивались. Вот, например, как будет выглядеть уведомление о том, что наш identity обновился:
А вот так будет выглядеть уведомление о том, что была нарушена целостность правил Iptables с указанием выгруженного дампа, содержащего нарушение:
Компонент №4: systemd
Ну и напоследок нам определенно хотелось бы произвести единоразовую настройку и не думать в дальнейшем о своей безопасности, а потому на помощь приходят автозапуск и сервисы. В Linux есть несколько стандартных подсистем управления демонами: systemd, sysV, init. В нашем случае выбор пал на systemd из-за гибкости его настройки.
Предположим, что написанный в предыдущем шаге python-скрипт называется «toroxy» и лежит в /usr/bin/ , тогда его автозапуск и последующий мониторинг с определенной гибкостью управления демоном будет таким:
[Unit] Description=Toroxy After=network.target StartLimitIntervalSec=0 [Service] Type=simple Restart=always RestartSec=1 User=root # service toroxy start ExecStart=/usr/bin/toroxy service # service toroxy stop ExecStop=/usr/bin/toroxy stop # service toroxy reload ExecReload=/usr/bin/toroxy switch [Install] # запускаемся на init 3, чтобы с пользовательского уровня до загрузки UI трафик уже шел через Tor WantedBy=multi-user.target
Почти все готово для «промышленной» эксплуатации. Последний штрих, который хотелось бы внести в инструмент для дополнительной надежности — это автоматическая инициализация правил iptables при запуске системы (как известно, правила iptables при перезагрузке сбрасываются) с помощью iptables-persistent:
iptables-save > /etc/iptables/rules.v4 ip6tables-save > /etc/iptables/rules.v6 netfilter-persistent start && netfilter-persistent save
Заключение
Вот мы и собрали из совокупности разношерстных компонентов собственный инструмент, который с достаточно высокой степенью надежности способен обеспечивать непрерывную анонимность пользователя Linux в сети. В завершение следует сказать, что все описанное в статье реализовано в виде инструмента Toroxy, доступного на GitHub.