У вас есть старенький (или не очень) компьютер с двумя сетевыми картами? Вам надоела реклама и лишние телодвижения для обхода блокировок? Вы не хотите с этим мириться? Тогда добро пожаловать под кат.
Цель
Настроить интернет шлюз таким образом, чтобы клиенты внутри локальной сети без дополнительных настроек работали с интернетом без ограничений. К заблокированным сайтам доступ будет осуществляться через тор, к остальным через обычное интернет соединение. К .onion ресурсам доступ из любого браузера как к обычным сайтам. В качестве бонуса, настроим блокировку рекламных доменов и доступ к условно заблокированным сайтам через тор (имеются в виду сайты, которые ограничивают функциональность для пользователей из РФ). Мой интернет провайдер чтоб тебе икнулось осуществляет перехват DNS запросов и подмену адресов (т.е. при резольвинге запрещенных сайтов возвращает адрес своей заглушки), поэтому все DNS запросы я отправляю в тор.
Идеи и способы реализации взял отсюда и отсюда. Авторам этих статей большое спасибо.
Итак поехали
Предполагается, что на начальном этапе у вас уже есть установленная ОС (в моем случае Ubuntu server 16.04) на компьютере с двумя сетевыми интерфейсами. Один из которых (у меня это ppp0) смотрит в сторону провайдера, а второй (у меня это enp7s0) в локалку. Внутренний IP шлюза 192.168.1.2. Локальная сеть 192.168.1.0/24.
Как подойти к этому этапу в данной статье не рассматривается, так как информации в сети более чем достаточно. Скажу только, что pppoe подключение к провайдеру удобно настраивать утилитой pppoeconf.
Подготовительный этап
Если вы, как и я, используете н{е|оу}тбук, то возможно вам захочется, чтобы он не засыпал при закрытии крышки.
sudo nano /etc/systemd/logind.conf
HandleLidSwitch=ignore
Разрешаем форвардинг в ядре. Я за одно отключил IPv6.
sudo nano /etc/sysctl.conf
net.ipv4.ip_forward=1
# IPv6 disabled
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
Применим изменения без перезагрузки.
sudo sysctl -p
Настройка DHCP
Мы хотим, чтобы клиенты настраивались автоматически, поэтому без DHCP сервера не обойтись.
$ sudo apt install isc-dhcp-server
$ sudo nano /etc/dhcp/dhcpd.conf
Приводим файл примерно к такому виду.
default-lease-time 600;
max-lease-time 7200;
subnet 192.168.1.0 netmask 255.255.255.0 {
range 192.168.1.100 192.168.1.200;
option routers 192.168.1.2;
option domain-name-servers 192.168.1.2, 8.8.8.8;
option broadcast-address 192.168.1.255;
}
range 192.168.1.100 192.168.1.200; — диапазон адресов, который будет выдаваться сервером,
option routers 192.168.1.2; — адрес шлюза
option domain-name-servers 192.168.1.2, 8.8.8.8; — адреса DN серверов
option broadcast-address 192.168.1.255; — широковещательный адрес.
Перезапустим сервер
sudo /etc/init.d/isc-dhcp-server restart
Настройка TOR
Устанавливаем и открываем настройки.
$ sudo apt install tor
$ sudo nano /etc/tor/torrc
Добавляем строки
#Определяем подсеть в которую тор будет разрешать имена onion
#такой диапазон достаточно жирный. Можно смело сокращать.
VirtualAddrNetworkIPv4 10.0.0.0/8
#Включаем DNS от луковицы
AutomapHostsOnResolve 1
#Определяем порты прозрачного прокси и DNS
TransPort 0.0.0.0:9040
DNSPort 0.0.0.0:5353
#Не пользуемся выходными узлами из этих стран
ExcludeExitNodes {RU}, {UA}, {BY}
Настройка DNS
Если вам не нужна блокировка рекламы, то данный пункт можно не выполнять. Если вы хотите просто пользоваться DNS от тора, добавьте в файл /etc/tor/torrc строку DNSPort 0.0.0.0:53 и всё.
Но я буду резать рекламу, а значит устанавливаем и открываем настройки
$ sudo apt install bind9
$ sudo nano /etc/bind/named.conf.options
Приводим файл к следующему виду
options {
directory "/var/cache/bind";
forwarders {
127.0.0.1 port 5353;
};
listen-on {
192.168.1.2;
127.0.0.1;
};
dnssec-validation auto;
auth-nxdomain no;
listen-on-v6 { none; };
};
Если ваш провайдер не химичит с DNS запросами, можете направить трафик на другие днс серверы. Например на сервера гугла:
forwarders {
8.8.8.8;
8.8.4.4;
};
Теоретически должно работать по шустрее, чем через тор.
К дальнейшей настройке DNS вернемся чуть позже. Пока этого достаточно. А сейчас перезапустим службу.
sudo /etc/init.d/bind9 restart
Настройка iptables
Вся магия будет твориться именно здесь.
- Формируем список IP адресов на которые мы хотим ходить через тор.
- Заворачиваем запросы к этим адресам на прозрачный прокси тора.
- Заворачиваем DNS запросы к ресурсам .onion на DNS тора
- Тор при резольвинге имен из зоны .onion возвращает IP адрес из подсети 10.0.0.0/8 (которую мы указали при настройке ТОР). Разумеется, эта зона не маршрутизируется в интернете и нам нужно завернуть обращения на эту подсеть на прозрачный прокси тора.
forwarders {
127.0.0.1 port 5353;
};
Не приводит к желаемому результату, так же как выделение отдельной зоны ".onion" с forwarders на 127.0.0.1 port 5353.
Если кто-нибудь знает почему так происходит и как это исправить, напишите в комментариях.
Полагаю, что iptables уже установлен. Устанавливаем ipset. С помощью этой утилиты мы сможем управлять списком заблокированных адресов и заворачивать пакеты в прозрачный прокси тора.
sudo apt install ipset
Далее последовательно из под рута выполняем команды по настройке iptables. Я поместил эти команды в /etc/rc.local перед exit 0 и они выполняются каждый раз после загрузки.
#Создаем ipset для списка блокировок
ipset -exist create blacklist hash:ip
#Редирект запросов DNS на TOR для доменов onion. Средствами bind9 такой редирект настроить не удалось
iptables -t nat -A PREROUTING -p udp --dport 53 -m string --hex-string "|056f6e696f6e00|" --algo bm -j REDIRECT --to-port 5353
iptables -t nat -A OUTPUT -p udp --dport 53 -m string --hex-string "|056f6e696f6e00|" --algo bm -j REDIRECT --to-port 5353
#Редирект на ТОР IP адресов из списка блокировок
iptables -t nat -A PREROUTING -p tcp -m set --match-set blacklist dst -j REDIRECT --to-port 9040
iptables -t nat -A OUTPUT -p tcp -m set --match-set blacklist dst -j REDIRECT --to-port 9040
#Редирект на тор для ресурсов разрезольвенных тором в локалку 10.0.0.0/8
#обычно это .onion
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
###########################################
#Все что ниже относится к настройке самого шлюза, а не к обходу
#блокировок
###########################################
#Включаем NAT
iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE
# Рзрешаем пинги
iptables -A INPUT -p icmp --icmp-type echo-reply -j ACCEPT
iptables -A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT
iptables -A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
# Отбрасываем неопознанные пакеты
iptables -A INPUT -m state --state INVALID -j DROP
iptables -A FORWARD -m state --state INVALID -j DROP
# Отбрасываем нулевые пакеты
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
# Закрываемся от syn-flood атак
iptables -A INPUT -p tcp ! --syn -m state --state NEW -j DROP
iptables -A OUTPUT -p tcp ! --syn -m state --state NEW -j DROP
#Разрешаем входящие из локалки и локальной петли, и все уже установленные соединения
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -i enp7s0 -j ACCEPT
iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
#Остальные входящие запрещаем
iptables -P INPUT DROP
#Разрешаем форвардинг изнутри локалки.
iptables -A FORWARD -i enp7s0 -j ACCEPT
iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
#Остальной форвардинг запрещаем
iptables -P FORWARD DROP
После перезагрузки мы должны получить шлюз, который:
- Выдает IP адреса и настройки сети клиентам.
- Раздает интернет.
- Резольвит имена через тор DNS.
- Резольвит имена .onion и позволяет посещать эти ресурсы через обычный браузер.
- Закрывает нас от входящих подключений.
Обхода блокировок пока нет, так как несмотря на то, что мы создали blacklist и настроили маршрутизацию, сам blacklist пока пустой. Настало время это исправить.
Заполняем blacklist
Создаем каталог в котором будет лежать скрипт.
# mkdir -p /var/local/blacklist
Создаем скрипт
# nano /var/local/blacklist/blacklist-update.sh
со следующим содержимым
#! /bin/bash
#Переходим в каталог скрипта
cd $(dirname $0)
#Скачиваем с github репозиторий со списком заблокированных ресурсов
git pull -q || git clone https://github.com/zapret-info/z-i.git .
#Обрабатываем dump.csv так чтобы получился файл blacklist.txt с IP адресами заблокированных ресурсов
cat dump.csv | cut -f1 -d; | grep -Eo '[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}' | sort | uniq > blacklist.txt
#Обрабатываем файл my-blacklist c именами доменов, которые не под блокировкой
#но на которые мы хотим ходить через тор. Дополняем blacklist.txt
dig +short -f my-blacklist >> blacklist.txt
#Очищаем ipset
ipset flush blacklist
#Запиcываем новые данные
cat blacklist.txt | xargs -n1 ipset add blacklist
Делаем скрипт исполняемым
# chmod +x /var/local/blacklist/blacklist-update.sh
создаем файл my-blacklist, который в дальнейшем будем наполнять вручную теми ресурсами, на которые хотим ходить через тор.
# echo lostfilm.tv > /var/local/blacklist/my-blacklist
Выполняем скрипт
# /var/local/blacklist/blacklist-update.sh
Скрипт работает долго, будь пациентом be patient. Теперь должна открываться флибуста должны работать заблокированные сайты. Добавляем в конец файла /etc/rc.local, но перед exit 0
#Ждем минуту чтобы тор полностью загрузился, подключился,
#заработал тор DNS
sleep 60
#Заполняем список запрещенных сайтов. Длительная операция.
/var/local/blacklist/blacklist-update.sh
Настраиваем фильтр рекламы
- Устанавливаем и запускаем микро HTTP сервер, который слушает 80 и 443 порты и на любой запрос возвращает картинку png с одним прозрачным пикселем.
- Получаем список рекламных доменов.
- Настраиваем bind как авторитативный сервер для них.
- Заворачиваем все запросы на рекламные домены на наш HTTP сервер с чудесной картинкой.
Приступим. Создаем скрипт
# nano var/local/blacklist/ad-update.sh
с содержимым
#! /bin/bash
cd /etc/bind/
curl "http://pgl.yoyo.org/adservers/serverlist.php?hostformat=bindconfig&showintro=0&mimetype=plaintext" | sed 's/null.zone.file//etc/bind/db.adzone/g' > named.ad.conf
rndc reload
Делаем его исполняемым
# chmod +x /var/local/blacklist/ad-update.sh
и выполняем
# /var/local/blacklist/ad-update.sh
Создаем файл зоны
# nano /etc/bind/db.adzone
со следующим содержимым
$TTL 86400 ; one day
@ IN SOA ads.example.com. hostmaster.example.com. (
2014090102
28800
7200
864000
86400 )
NS my.dns.server.org
A 192.168.1.2
@ IN A 192.168.1.2
* IN A 192.168.1.2
Добавляем в файл
# nano /etc/bind/named.conf
строку
include "/etc/bind/named.ad.conf";
Применяем изменения
rndc reload
Настраиваем обновление списка доменов при загрузке. Для этого открываем файл /etc/rc.local и добавляем после sleep 60
/var/local/blacklist/ad-update.sh
Последние штрихи
Для периодического обновления списков, создадим файл
# nano /etc/cron.daily/blacklist-update
Со следующим содержимым
#!/bin/bash
#Загружаем свежий список рекламных доменов для фильтрации
/var/local/blacklist/ad-update.sh
#Заполняем список запрещенных сайтов. Длительная операция.
/var/local/blacklist/blacklist-update.sh
Делаем его исполняемым
# chmod +x /etc/cron.daily/blacklist-update
.
Замечание для пользователей десктопных версий Ubuntu
Несмотря на то, что целью было создать шлюз, который не требует настроек клиентов, в моем случае получилось не совсем так. В качестве рабочей операционной системы я использую десктопную Ubuntu 16.04. Для настройки сети в ней используется утилита NetworkManager, которая по умолчанию настроена таким образом, что адрес DN сервера с DHCP сервера, а устанавливается как 127.0.1.1:53. На этом порту висит dnsmasq и только по ему известным правилам резольвит имена. В обычной жизни это никак не мешает, а в нашем случае делает совершенно неработоспособной зону .onion
Чтобы это исправить нужно в файле /etc/NetworkManager/NetworkManager.conf закоментировать строку
dns=dnsmasq
вот так
#dns=dnsmasq
После перезагрузки все работает.
Заключение лишь бы не под стражу
Клиенты на андроид работают нормально без дополнительных настроек.
Windows не проверял, так как не использую, но думаю, проблем возникнуть не должно.
Ограничения для firefox и iOs описаны здесь
Прошу прощения за сумбурное изложение. Дополнения, исправления, замечания приветствуются.
Спасибо за внимание.
Автор: UrsusMaritimus