Настройка Tor-роутера под BSD (transparent Tor-proxy как anonymizing middlebox)
Пример, приведённый в официальном Tor-faq, на текущий момент не применим для OpenBSD PF из-за смены синтаксиса, и, на мой взгляд, содержит ряд неточностей. Ниже привожу пример настройки с дополнительным закручиванием гаек в PF. Цель — прозрачно выпускать несколько локальных подсетей в Tor, где каждая из них будет привязана к своему Tor-клиенту (в рассматриваемом примере две подсети).
Пусть выходной сетевой интерфейс — fxp0, а входные — vr0 и vr1. Тестировались только OpenBSD и NetBSD. При установке Tor из портов пользователь tor (_tor) и группа tor (_tor) создаются автоматически в NetBSD (OpenBSD). Далее с помощью vipw добавляем аналогичного юзера для второй подсети (достаточно сменить UID, сохранив ту же группу, имена пользователей для удобства можно упорядочить как, например, tor1 и tor2). Для tor-пользователей создаются конфигурационные файлы наподобие таких:
$ cat torrc_1 SocksPort 9050 SocksListenAddress 127.0.0.1 RunAsDaemon 1 DataDirectory /tmp/tor_1 User tor1 AutomapHostsOnResolve 1 Log notice file /tmp/tor_1.log VirtualAddrNetwork 10.192.0.0/10 TransPort 9060 DNSPort 5353
$ cat torrc_2 SocksPort 8050 SocksListenAddress 127.0.0.1 RunAsDaemon 1 DataDirectory /tmp/tor_2 User tor2 AutomapHostsOnResolve 1 Log notice file /tmp/tor_2.log VirtualAddrNetwork 172.16.0.0/12 TransPort 8060 DNSPort 5363
/usr/local/bin/tor -f /path/to/torrc_1 /usr/local/bin/tor -f /path/to/torrc_2
/usr/pkg/bin/tor -f /path/to/torrc_1 /usr/pkg/bin/tor -f /path/to/torrc_2
Вопреки сказанному в Tor-faq, прав на чтение /dev/pf достаточно не только для OpenBSD, но и для NetBSD, потому назначаем:
# chgrp tor /dev/pf # chmod g=r /dev/pf
# переменные: in0 = "vr0" IPin0 = "IP_НА_vr0" net0 = "СЕТЬ_НА_vr0" TransPort0 = "9060" DnsPort0 = "5353" in1 = "vr1" IPin1 = "IP_НА_vr1" net1 = "СЕТЬ_НА_vr1" TransPort1 = "8060" DnsPort1 = "5363" out0 = "fxp0" IPout0 = "IP_НА_fxp0" lh = "localhost" tor_users = "{ tor1, tor2 }" # опции по вкусу: scrub all no-df random-id min-ttl 128 # редиректы: rdr on $in0 inet proto tcp from $net0 to ! $IPin0 -> 127.0.0.1 port $TransPort0 rdr on $in0 inet proto udp from $net0 to ! $IPin0 port domain -> 127.0.0.1 port $DnsPort0 rdr on $in1 inet proto tcp from $net1 to ! $IPin1 -> 127.0.0.1 port $TransPort1 rdr on $in1 inet proto udp from $net1 to ! $IPin1 port domain -> 127.0.0.1 port $DnsPort1 # фильтрация: block all block in quick from any os NMAP antispoof log quick for {$in0,$in1,$out0} pass in on $in0 inet proto tcp from $net0 to $lh port $TransPort0 user root pass in on $in0 inet proto udp from $net0 to $lh port $DnsPort0 user root pass in on $in1 inet proto tcp from $net1 to $lh port $TransPort1 user root pass in on $in1 inet proto udp from $net1 to $lh port $DnsPort1 user root pass out on $out0 inet proto tcp from $IPout0 to any user $tor_users block inet6 all
block all block in quick from any os NMAP antispoof log quick for {$in0,$in1,$out0}
block return log (all)
# tcpdump -i pflog0 -n -e action block
Такая же конфигурация на OpenBSD 4.8 с учётом смены синтаксиса PF выглядит так4:
# редиректы: match in on $in0 inet proto tcp from $net0 to ! $IPin0 rdr-to 127.0.0.1 port $TransPort0 match in on $in0 inet proto udp from $net0 to ! $IPin0 port domain rdr-to 127.0.0.1 port $DnsPort0 match in on $in1 inet proto tcp from $net1 to ! $IPin1 rdr-to 127.0.0.1 port $TransPort1 match in on $in1 inet proto udp from $net1 to ! $IPin1 port domain rdr-to 127.0.0.1 port $DnsPort1 # фильтрация: block all block in quick from any os NMAP antispoof quick for {$in0,$in1,$out0} pass in on $in0 inet proto tcp from $net0 to $lh port $TransPort0 user unknown pass in on $in0 inet proto udp from $net0 to $lh port $DnsPort0 user unknown pass in on $in1 inet proto tcp from $net1 to $lh port $TransPort1 user unknown pass in on $in1 inet proto udp from $net1 to $lh port $DnsPort1 user unknown pass out on $out0 inet proto tcp from $IPout0 to any user $tor_users block inet6 all
Замечания:
- Стоить отметить один важный феномен. Конфиг для старого синтаксиса PF (т.е. первый) работает для входящих только при опции user root, а для нового — только при user unknown5, при этом в описании опции user в man pf.conf ничего не менялось. Для работоспособности исходящих соединений tor нужно указывать user tor6, но и это не консистентно с документацией на PF, где чёрным по-белому указано, что при дропе привелегий владельцем сокета остаётся исходный пользователь (в нашем случае root, т.к. запуск из /etc/rc.local). Для входящих соединений, согласно документации, должен быть user unknown, если это — транслируемый траффик, либо пользователь, слушающий на заданном порту7. С этой точки зрения что должно быть на самом деле для pass in согласно букве документации вообще не ясно (траффик сначала перенаправляется rdr, а лишь затем передаётся на порт Tor. Если считать, что rdr не меняет критерий user, то по логике вещей для pass in должен стоять root [см. выше про дроп привелегий]).
- В Tor-faq указан более короткий вариант правил (совмещает в себе и разрешение входящих и редирект), но я для большей контролируемости предпочитаю писать фильтрацию и трансляцию/перенаправления отдельно. Как мне представлялось (и как пишется во многих руководствах), пакет проходит фильтрацию до перенаправления и после. На практике стало понятно, что фильтрацию до перенаправления он не проходит, потому соответствующие правила из PF были изъяты3.
Указанная конфигурация легко заливается с помощью скрипта mklivecd на NetBSD LiveCD, что позволяет сделать бездисковый Tor-рутер из любого старого компьютера8. Конфиг будет работать и на одной сетевой с одним интерфейсом (надо будет для in0 и in1 указать тот же интерфейс).
P.S.: Конфигурацию с local redirection пока не настраивал, потому PF-аналог Linux-настройки привести не могу.
1Раздел /tmp целесообразно монтировать в память посредством mfs.
2В NetBSD 3.0 текущая версия Tor через pkgsrc собирается без поддержки прозрачной торификации (причины мне не известны), потому протестить не удалось.
3Если кто объяснит, где я не прав и как всё на самом деле, буду очень благодарен.
4Начало конфига до "опций" совпадает с предыдущим.
5Определялось экспериментально.
6Если вообще указывать опцию user, что в данной заметке делается по умолчанию.
7Например, user root для входящих pass in на ssh.
8Сколь-нибудь автоматизированных средств сборки OpenBSD LiveCD в сети не обнаружено, а все how-to написаны для довольно старых версий OpenBSD и не работают на 4.8 (ядро не влазит в отведённый размер boot при дискетоподобной системе загрузки LiveCD). Под FreeBSD есть средства автоматизированной сборки LiveCD, но я их не тестировал.