Выгрузка и блокировка сайтов РосКомНадзора через squid

Описание работы системы

Как работает система:

1. Сервер zapret скачивает список запрещенных сайтов c сервера роскомнадзора
2. Парсит его на url и ip по виду трафика (http https)
3. Создает список IP, трафик с которых нужно перенаправлять на сервер фильтрации
4. Перекидывает его по на GW, который в свою очередь перенапраляет трафик идущий на ip адреса из списка на zapret
5. сервер Zapret Http url перенаправляет на squid, https блокироует по ip через iptables. Трафик не попадающий под правила идет обратно на GW

Схема работы

%d1%81%d1%85%d0%b5%d0%bc%d0%b0_%d1%80%d0%b0%d0%b1%d0%be%d1%82%d1%8b

Суть работы данной системы для понимания дальнейшей настройки:

Трафик от абонентов идет по 996 влану (193.254.225.0/24 — статические адреса) и по 211 влану (91.233.165.0/24 — по этим ip НАТятся динамические адреса) и попадает на GW.
На GW с помощью ip route и iptables траффик перенапраляется на 250 влан и идет на zapret для фильтрации
На zapret трафик делиться на http трафик (80 порт) и https траффик (443 порт)
http идет на squid с прозрачныи прокси и при переходе на запрещенный сайт/ссылку перенаправляется на странцу блокировки (squid блокирует по url)
https идет на табицы iptables через ipset и фильтруется по IP. При переходе на запрещенный сайт/ссылку будет выдаваться ошибка соединения с сервером
(Пока эта система реализовано как указано выше, но в перспективе можно переделать на схему через squid)
Траффик который не попал под правила блокировки передается по eth0 (193.254.224.169) обратно на GW и идет по назначению.

Серверы и их роли:

GW (193.254.225.1) — наш гейтвей, через него идет весь трафик от абонентов. С него идет переадресация исходящего на запрещенный сайты трафика на zapret2
Zapret2 (193.254.224.169) — сервер фильтрации
Zapret (193.254.225.180) — сервер проверки качества фильтрации (можно реализовать на любой линуксовой машине подключеной к нашей сети)

Установка и настройка сервера zapret2

Создание и настройка виртуальной машины

На XEN создаем виртуалку она будет находиться в 212 влане т.е. 193.254.224.129 будет шлюзом

xen-create-image -hostname=zapret2 -size=20Gb -swap=4096Mb -ip=193.254.224.169 --memory=2048mb --vcpus=2 -netmask=255.255.255.128 -gateway=193.254.224.129 -arch=amd64 -dist=wheezy -force -passwd --lvm=vmstorage -role=udev vif=[ 'script=vif-bridge,bridge=br0,model=rtl8139' ]

Копируем конфиг виртуалки в каталог auto для автозапуска после перезагрузки xen

cp /etc/xen/zapret2 /etc/xen/auto

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

xen create /etc/xen/auto/zapret2.cfg
xm console zapret2

Устанавливаем минимальный набор для работы

apt-get install ssh mc

Теперь можно подключаться по ssh
После установки wheezy стоит локаль «С» и некоторые символы отображаются неправильно.

export LANG=ru_RU.utf8
nano /etc/default/locale

меняем на

LANG=ru_RU.utf8

проверям sources.list

nano /etc/apt/sources.list

должно быть

deb http://mirror.yandex.ru/debian/ wheezy main
deb-src http://mirror.yandex.ru/debian/ wheezy main
deb http://security.debian.org/ wheezy/updates main
deb-src http://security.debian.org/ wheezy/updates main

Настройка сети

Нужно создать интерфейсы,один для приема и один передачи траффика. В нашем случае для передачи траффика обратно на GW будет использоваться основной интерфейс eth0 c ip 193.254.224.169 и шлюз по умолчанию 193.254.224.129

nano /etc/network/interfaces

auto vlan250
iface vlan250 inet static
vlan_raw_device eth0
address 192.168.10.10
netmask 255.255.255.0
gateway 192.168.10.1

Устанавливаем пакет vlan

apt-get install vlan

Добавляем модуль для работы вланов

nano /etc/modules
modprobe 8021q

перезагружаем демона нетворк

/etc/init.d/networking restart

Установка Skydns

Копируем dpkg файлы

skydns-zi-test_2.0.12_all.deb 
squid3_3.3.8-1.1_amd64.deb
libecap2_0.2.0-1_amd64.deb
skydns-zi-web_2.0.12_all.deb
squid3-common_3.3.8-1.1_all.deb

остальные для наших целей не нужны
Выполняем установку

dpkg -i skydns-zi-test_2.0.12_all.deb squid3_3.3.8-1.1_amd64.deb libecap2_0.2.0-1_amd64.deb skydns-zi-web_2.0.12_all.deb squid3-common_3.3.8-1.1_all.deb

Должен выдать ошибку зависимостей — для исправления выполнить:

apt-get -f install

Устанавливаем tcpdump (для проверки прохождения траффика через наш сервер)

apt-get install tcpdump

создаем каталог /var/lib/skydns-zi/zapret-info/dump-latest. Для тестов будем кидать туда dump.xml, а потом все автоматизируем

Редактируем конфиг skydns

nano /etc/skydns-zi/zapret-info.cfg
mj_download = False # Список минюста пока не нужен, будет мешать адекватной проверке нашего списка, можно включить потом
dns-servers = 127.0.0.1, 193.254.225.254, 8.8.8.8, 77.88.8.8
blockpage = /etc/skydns-zi/blockpage # раскоментить

после изменения zapret-info.cfg выполнить

service skydns-zi-update restart

Вносим сети которые траффик с которых будет фильтроваться:

nano /etc/skydns-zi/firewall/isp_nets_src

192.168.10.0/24
192.168.11.0/24
193.254.225.0/24
193.254.224.0/24
91.233.165.0/24

Далее настраиваем iptables

/etc/skydns-zi/firewall/zi-firewall.sh

Это автоматическая настройка от skydns, с ней все работает.

Проверка работы skydns

основной скрипт для скачивания дампа и при менения всех списков на firewall

su -c '/usr/bin/zi-cron.sh' skydns-zi

(На данном этапе можно запустить для проверки работоспособности самого скрипта, но для этого нужно кинуть файл дампа в каталог /var/lib/skydns-zi/zapret-info/dump-latest)

результат в каталоге
/var/lib/skydns-zi/zapret-info/dump-latest:
dump.xml– это XML-файл с реестром
dump.xml.sig– подпись Роскомнадзора
icapregexplist.zi– список URL, по которым сервер ICAP осуществляет фильтрацию
urllist_from_dump– список URL из реестра Роскомнадзора

Дополнительно можно проверить:

Запущена ли служба skydns-ziupdate

service skydns-zi-update status

должна вернуть результат skydns-zi-update is running

После того как служба skydns-ziupdate в течение нескольких минут разрешит домены запрещенных ресурсов в IP-адреса, в каталоге /var/lib/skydns-zi/zi-update будут созданы файлы со списками IP-адресов.

Эти ресурсы должны быть доступны

ping 8.8.8.8
ping ya.ru

проверить списки ipset

ipset -L

Проверить правила iptables

iptables -L
iptables -t nat -L
iptables -t mangle -L

должно быть тоже самое что и в скрипте zi-firewall.sh

Проверьте, что запущена служба squid3 (слушает на порту tcp3128 на всех интерфейсах)

service squid3 status

должна вернуть результат squid3 is running

Проверьте, что запущена служба supervisor, которая запускает пять экземпляров приложения zi-icap(слушает на адресе 127.0.0.1 на портах tcp1340-1344).

service supervisor status

должна вернуть результат supervisor is running

netstat -natp | grep python

должна показать, что процесс python слушает на портах с 1340 по 1344 на адресе 127.0.0.1
Вернет

tcp        0      0 127.0.0.1:1340          0.0.0.0:*               LISTEN      29005/python
tcp        0      0 127.0.0.1:1341          0.0.0.0:*               LISTEN      29006/python
tcp        0      0 127.0.0.1:1342          0.0.0.0:*               LISTEN      29007/python
tcp        0      0 127.0.0.1:1343          0.0.0.0:*               LISTEN      29008/python
tcp        0      0 127.0.0.1:1344          0.0.0.0:*               LISTEN      29009/python

На этом установка Skydns окончена

Настройка выгрузки списка запрещенных сайтов

Выгрузка списка запрещенных сайтов будет настроена на сервере zapret2

Установка и настройка openssl

Устанавливаем доп софт

apt-get install gcc make
apt-get install zlib1g-dev 
apt-get install libccid libpcsclite1 pcscd libtool
apt-get install zip

На сервере создаем папку в корне: /gost-ssl
ставим openssl(1.0.1c)(Вложен в тему) на этой версии точно работает:

http://www.openssl.org
Копируем openssl-1.0.1с на сервер

tar xzf openssl-1.0.1с.tar.gz
cd openssl-1.0.1с
./config shared zlib enable-rfc3779 --prefix=/gost-ssl
make depend
make
make test
make install

Make делает долго, можно не переживать

Правим конфиг /gost-ssl/ssl/openssl.cnf

В самом верху, первой строкой пишем:

openssl_conf = openssl_def

Далее добавляем в конец:

[openssl_def]
engines = engine_section
[engine_section]
gost = gost_section
[gost_section]
default_algorithms = ALL
engine_id = gost
dynamic_path = /gost-ssl/lib/engines/libgost.so
CRYPT_PARAMS = id-Gost28147-89-CryptoPro-A-ParamSet

Далее проверяем работоспособность и наличие GOST (полный путь до openssl обязателен)

/gost-ssl/bin/openssl ciphers | tr ":" "\n" | grep GOST

Подготовка сертификата

если используем руТокен (флешку с эцп), то необходимо средствами КриптоПро скопировать ключевой контейнер в реестр с возможность экспорта. Чудные товарищи из КриптоПро, ссылаясь на требования ФСБ, не поддерживают экспорт в формате PKCS#12 (сертификат + закрытый ключ), но экспорт осуществить можно при помощи: P12FromGostCSP.zip (Вложен в тему)

Подключаем USB flash устанавливаем триал крипто-про -> запускаем -> владка сервис -> кнопка Просмотреть сертификаты в контейнере -> выбираем флешку -> ОК -> Установить

Пользуясь вышеуказанной утилитой выгружаем сертификат в формате PCKS#12 и кидаем его в /gost-ssl/rzs/

P12FromGostCSP -> Выбираем сертификат из списка (должен содержать название нашей организации) -> ОК -> сохраняем в нужную директорию

проверяем, что у нас нормальный (содержит сертификат и закрытый ключ) PKCS#12 командой:

/gost-ssl/bin/openssl pkcs12 -in p12.pfx -nodes

конвертируем полученный на Windows PKCS#12 в PEM:

/gost-ssl/bin/openssl pkcs12 -in p12.pfx -out provider.pem -nodes -clcerts

Создание и подписание XML запроса сертификатом

создаем XML файл запроса, согласно памятке оператора (http://zapret-info.gov.ru/docs/description_for_operators_2012-11-09v1.4.pdf)

и конфертируем его при помощи icov в СP1251:

/usr/bin/iconv -f UTF8 -t WINDOWS-1251 request.xml -o request.xml

подписываем xml файл нашим сертификатом:

/gost-ssl/bin/openssl smime -sign -in request.xml -out request.bin -signer provider.pem -outform DER

скидываем в Windows и проверяем валидность на http://www.gosuslugi.ru/pgu/eds/

если все впоряде, то идем дальше…

Автоматизация

Нужно для работы скриптов download.pl и download1.pl

Устанавливаем необходимые компонентов

apt-get install libxml-twig-perl
apt-get install libxml-simple-perl
apt-get install xmlstarlet

Устанавливаем SOAP, Syslog

cpan -i SOAP::Lite
cpan -i Sys::Syslog

Пока проверять не надо, о скриптах будет описано ниже

настройка сервера GW

Настраиваем переадресацию траффика на zapret с GW
Настройку проводим на сервере GW

nano /etc/network/interfaces

и добавляем влан 250

#Влан для отправки пакетов на ZapretISP
auto vlan250
iface vlan250 inet static
        address 192.168.10.1
        netmask 255.255.255.0
        vlan_raw_device eth0

Устанавливаем ipset

apt-get install ipset

Создаем 3 списка

ipset -N zapret iphash
ipset -N zapret2 iphash
ipset -N zapret_noblocked iphash

zapret и zapret2 — это два одинаковых списка, нужны для того чтобыв в момент добавления IP адресов в список блокировка не пропадала (скрипт каждый раз очищает список IP, и пока он добавит все IP заново (3 мин) IP будут доступны. Дублирование списков решает эту проблему, хотя выполнение скрипта занимает больше времени)

zapret_noblocked — это список для сайтов которые меняют IP адреса, в него IP адреса добавляются на постоянной основе. Более подробно будет описано в разделе «Проверка качества фильтрации»

Далее нужно создать правила IP route и iptables

iptables -t mangle -A PREROUTING -i br0 -p tcp -m set --match-set zapret dst -m multiport --dports 80,443 -j MARK --set-mark 0x2
iptables -t mangle -A PREROUTING -i vlan211 -p tcp -m set --match-set zapret dst -m multiport --dports 80,443 -j MARK --set-mark 0x2

iptables -t mangle -A PREROUTING -i br0 -p tcp -m set --match-set zapret2 dst -m multiport --dports 80,443 -j MARK --set-mark 0x2
iptables -t mangle -A PREROUTING -i vlan211 -p tcp -m set --match-set zapret2 dst -m multiport --dports 80,443 -j MARK --set-mark 0x2

iptables -t mangle -A PREROUTING -i br0 -p tcp -m set --match-set zapret_noblocked dst -m multiport --dports 80,443 -j MARK --set-mark 0x2
iptables -t mangle -A PREROUTING -i vlan211 -p tcp -m set --match-set zapret_noblocked dst -m multiport --dports 80,443 -j MARK --set-mark 0x2

iptables -v -I FORWARD -m set --match-set zapret_noblocked dst -j DROP
ip route add default via 192.168.10.10 table 20
ip rule add fwmark 0x2 table 20

краткая суть такая:

1. первыми правилами мы маркируем пакеты перед маршрутизацией, пришедшие с интерфейса br0 или vlan211 по протоколу tcp идущие на ip адрес из списка ipset «zapret», «zapret2» и «zapret_noblocked» на 80 или 443 порт
zapret_noblocked — на всякий случай дропаем прямо на GW, т.к. некоторые сайты используют переадресацию на другой порт и траффик проходит.

2. далее мы создаем таблицу маршрутизации 20 с маршрутом по умолчанию через IP 192.168.10.10 (это IP адрес zapret2)
3. Последней мы добавлям правило, что все пакеты маркированные 0x2 отправляются в таблицу 20, т.е через 192.168.10.10

Подробнее можно почитать тут:
https://habrahabr.ru/post/108690/
http://ubuntuhowtoo.blogspot.ru/2014/04/linux-routing.html