Платформа: Windows XP/Vista/7
Язык: Perl
Сервис, созданный Роскомнадзором носит очень длинное, трудное для восприятия название: «Единый реестр доменных имён, указателей страниц сайтов в сети «Интернет» и сетевых адресов, позволяющих идентифицировать сайты в сети «Интернет», содержащие информацию, распространение которой в Российской Федерации запрещено», поэтому далее будем называть его для простоты-сервис «Роскомнадзор».
Задача
Организовать автоматическое скачивание списков запрещенных сайтов с ресурса «Роскомнадзор». Система должна быть реализована в рамках одного хоста, скаченные файлы должны ротироваться с заданной глубиной.
Лирика
По поводу списка запрещенных сайтов, сказано было уже немало и обсуждать эту тему снова не имеет смысла.
Однако ежедневное скачивание списка запрещенных сайтов, несмотря на всю очевидную бессмысленность данного занятия, стало необходимостью для многих интернет-провайдеров. Делается это в основном для того, чтобы избежать претензий со стороны Роскомнадзора. Естественно что первое что приходит на ум-автоматизировать процесс скачивания. К сожалению на сайте Роскомнадзора способ автоматизации описан довольно туманно, а техподдержка практически отсутствует. Кроме того в случае автоматизации процесса, работа с сервисом идет по протоколу SOAP, что тоже не добавляет радости.
По этому поводу хочу представить один из возможных способов организации автоматического скачивания списка запрещенных сайтов. Возможно что у кого-то тоже возникла такая проблема, и я надеюсь моя статья поможет тем людям, которые в данный момент ищут ее решение.
Должен сказать, что на эту тему уже написано некоторое количество статей, в том числе и на Хабре, методы, представленные в этих статьях, большей частью, не позволяли достигнуть полной автоматизации. Где-то нужно было руками формировать запрос на получение списка, где-то руками запускать скрипты и т.д. В моем случае система работает полностью автоматически, я только иногда поглядываю все ли нормально. Скажу честно, чтобы поднять систему, я воспользовался статьей, которую нашел на Toster. В ней были представленны скрипты на Perl, которые я немного изменил и кое-что добавил.
Реализация конечно получилась довольно грубой, но вполне рабочей. Все удалось разместить на одном хосте. Это старый компьютер из бухгалтерии под Windows XP, в который воткнули Rutoken, подключили к сети и закрыли в стойке. Соответственно директория, в которую скачиваются архивы с сервиса Роскомнадзор расшарена в локальную сеть.
Теперь рассмотрим реализацию.
В качестве ОС, как я уже сказал, была использована Windows XP(какой версии не имеет значения), также для этих целей подойдет и Windows Vista и Windows 7.
Изначально считаем, что единственное назначение хоста-работа с реестром запрещенных сайтов.
1.Квалифицированная открепленная электронная подпись (ЭП) и програмное обеспечение (ПО) для работы с ней
Приобретение электронной подписи-отдельная тема для разговора. Приобрести ее можно у различных компаний, имеющих соответствующую лицензию, как это сделать-обычно стоит выяснять в самой компании. В нашем случае ЭП была приобретена у компании ООО «КРИПТО-ПРО», поэтому именно этот случай я опишу.
В приобретенный комплект входили: носитель подписи (Rutoken) с криптографическим ключом, сертификат ЭП, сертификат на техподдержку и диск с набором ПО.
Когда ОС установлена и хост готов к работе первое что необходимо сделать-это установить необходимое ПО для работы с ЭП.
Сначала устанавливаем драйверы для Rutoken (те что были на диске с ПО не подошли). Найти их можно на сайте производителя (раздел Рутокен для Windows).
Скачиваем драйверы и устанавливаем. Если все сделано верно, то после того как Rutoken будет вставлен в USB-порт на нем начнет светиться светодиод. (Программа соответственно называется-«Панель управления Рутокен»).
Далее устанавливаем программу Крипто-ПРО. Делать это нужно с подключенным Rutoken.
Сертификат действителен один год, потом его необходимо обновлять. В этом случае необходимо удалить старый сертификат и подключить новый. Информацию о сертификатах
можно посмотреть в «Пуск->Крипто-Про->Сертификаты»
Если в этом месте возникают затруднения, то лучше всего позвонить в техподдержку, там объяснят все достаточно корректно.
В моем случае я обновлял устаревший сертификат. Для этого я зашел в раздел «Сертификаты», далее
«Сертификаты-текущий пользователь->Личные->Реестр->Сертификаты», и удалил старый сертификат вручную, вставил Rutoken и перегрузил машину. Актуальный сертификат подцепился автоматически.
Чтобы проверить что сертификат установлен верно можно подписать файл вручную при помощи программы Крипто-АРМ, которая входит в комплект.
Для этого устанавливаем программу и создаем произвольный, желательно не пустой файл.
Включаем Крипто-АРМ, далее «Подпись->Подписать», выбираем файл и проходим диалог, в конце выбираем сертификат и жмем OK. Если все сделано верно. То в указаной в диалоге директории, появится файл filename.sig. Этот файл и есть открепленная электронная подпись.
Программа Крипто-АРМ в системе автоматической выгрузки списков запрещенных сайтов не участвует.
Самое главное, что нам нужно-утилита csptest.exe,(проверку ЭП можно сделать и с ее помощью) которая входит в состав Крипто-ПРО.
Это консольная утилита для создания ЭП. Работает только под ОС Windows.
По словам разработчиков, эта утилита нужна исключительно для тестов и в боевой системе ее использовать нельзя, т.к. она обладает неполными возможностями. Для нормальной работы используется другая утилита, которая может работать и на Linux-сервере, но за нее требуется заплатить отдельно.
Практика показала, что для решения поставленой задачи csptest.exe вполне подходит.
2. Организация автоматического скачивания
Работа с сервисом «Роскомнадзор» происходит по протоколу SOAP.
Алгоритм следующий
Раз в 5 минут проверяем, производилось ли скачивание за текущий день(существует ли архив с нужным именем)
 Если да-ничего не делаем.
 Если нет-начинаем скачивание.
   Создаем актуальный запрос на выгрузку списка запрещенных сайтов
   Создаем файл подписи
   Отправляем на сервер запрос и получаем код запроса (или сообщение об ошибке если запрос корректный)
    Если запрос корректный ждем 5 минут (запрос обрабатывается 1-2 минуты) и отправляем на сервер код запроса
    Принимаем архив со списком запрнещенных файлов в бинарном режиме
   Если запрос некорректный-получаем код ошибки и ничего не делаем.
Система выгрузки представляет из себя следующее:
4 файла, из которых 3-скрипты на perl и один файл типа .bat
Файлы: make_request.pl,get_register.pl,rotation.pl,roscomnadzor.bat
Назначение скриптов.
make_request.pl-создает запрос к сервису «Роскомнадзор»
get_register.pl-отправляет запросы к сервису «Роскомнадзор» и обрабатывает результаты
rotation.pl-производит ротацию скаченных архивов с заданной глубиной
roscomnadzor.bat-синхронезирует работу скриптов и утилит
Развертывание системы
Создаем в корне диска С:// (или иногог диска) рабочую директорию. У меня она называется roscomnadzor.
Внутри нее создаем 2 поддиректории: source и result.
В директорию source нужно поместить скрипты, в директории result будет находится результат ее работы, т.е. архивы со списками запрещенных сайтов.
После размещения скриптов необходимо прописать пути к файлам от корневой директории (или вынести в config, если есть желание сделать все красиво).
Принцип работы
Для выполнения процедуры необходимо запустить файл roscomnadzor.bat
Листинг roscomnadzor.bat
if not exist "D:roscomnadzorresultreestr_%Date:~6,4%_%Date:~3,2%_%Date:~0,2%.zip" (
rem Запускаем скрипт формирования запросов
perl D:roscomnadzorsourcemake_request.pl
rem запускаем утилиту для создания подписи
<путь к csptest>csptest.exe -sfsign -sign -detached -add -in <путь к фалу>request.txt -out <путь к файлу>request.txt.sig -my <имя владельца сертификата>@example.ru
rem запускаем скрипт для полученрия списка запрещенных сайтов
perl D:roscomnadzorsourceget_register.pl
ren D:roscomnadzorresultreestr.zip "reestr_%Date:~6,4%_%Date:~3,2%_%Date:~0,2%.zip"
perl D:roscomnadzorsourcerotation.pl
)
1. Создание файла запроса
За создание запроса отвечает скрипт make_request.pl, файл запроса создается в директории source
Запрос на скачивание представляет изсебя файл в формате xml, следующего вида:
<?xml version="1.0" encoding="windows-1251"?>
<request>
<requestTime>yyyy-mm-ddT115:00:00.000+04:00</requestTime>
<operatorName>Название организации</operatorName>
<inn>ИНН организации</inn>
<ogrn>ОГРН организации</ogrn>
<email>company@cmail.ru</email>
</request>
Листинг make_request.pl
use POSIX qw(strftime);
my $date = strftime "%Y-%m-%d", localtime;
#Удаляем старые файлы с запросом и подписью если такие есть
unlink('<путь к фалу>request.txt');
unlink('<путь к фалу>request.txt.sig');
#Формируем xml запрос на сервер
$request='<?xml version="1.0" encoding="windows-1251"?><request><requestTime>'.$date.'T115:00:00.000+04:00</requestTime><operatorName>COMPANY NAME</operatorName><inn>1111111111</inn><ogrn>1111111111111</ogrn><email>company@example.ru</email></request>';
#Создаем в рабочей директории файл запроса
my $filename = '<путь к фалу>request.txt';
open(my $fh, '>', $filename) or die "Не могу открыть '$filename' $!";
print $fh $request;
close $fh;
2. Создание файла подписи
Для создания файла-подписи мы и используем ту самую утилиту csptest.exe Вызывается она из bat-файла
D:"Program files""Crypto Pro"CSPcsptest.exe -sfsign -sign -detached -add -in <путь к фалу>request.txt -out <путь к фалу>request.txt.sig -my <имя владельца сертификата>@example.ru
где:
-my — Указывает владельца ключа;
-in — Указывает какой файл нужно подписывать. Если файл находится не в папке с csptest то нужно указывать полный путь.;
-out — Указывает имя файла подписи;
3. Диалог с сервисом «Роскомнадзор»
За отправление запросов и обработку результатов отвечает скрипт get_register.pl
Листинг get_register.pl
use MIME::Base64;
use SOAP::Lite;
use POSIX qw(strftime);
#-----------------------------------------------------------------------
#Создаем предохранители на случай, если файл запроса или файл подписи не существует
$key1=0;
$key2=0;
if (open(FP, '<путь к фалу>request.txt'))
{$key1=1;}
if (open(FP, '<путь к фалу>request.txt.sig'))
{$key2=1;}
#Если оба файла существуют-начинаем
if( ($key1==1)&($key2==1))
{
#----------------------------
#Читаем в буфер файл запроса
open(FIL,"<путь к фалу>request.txt");
while ($line = <FIL>)
{
$ln.=$line;
}
close (FIL);
$req=$ln;
#----------------------------
#Читаем в буфер файл подписи
open(FIL1,"<путь к фалу>request.txt.sig");
while ($line1 = <FIL1>)
{
$ln1.=$line1;
}
close (FIL1);
$sig=$ln1;
#----------------------------
#Получаем описание методов джля работы с сервисом через wsdl-схему
$soap = SOAP::Lite->service('http://vigruzki.rkn.gov.ru/services/OperatorRequest/?wsdl');
$r = $soap->getLastDumpDate();
#Отправляем запрос на сервер
@r = $soap->sendRequest($req, $sig);
$code = $r[2];
#Ждем 5 минут и отправляем код запроса на сервер
sleep 1, print "$_n" for 1..300; #300
@r = $soap->getResult($code);
#-------------------------
#Принимаем и сохраняем в файл архив(принимаем в бинарном режиме)
#my $date = strftime "%Y-%m-%d_at_%H-%M-%S", localtime;
#my $date = strftime "%Y-%m-%d", localtime;
my $filename = '<путь к фалу>reestr.zip';
open(my $fh, '>', $filename) or die "Не могу открыть '$filename' $!";
binmode $fh;
print $fh decode_base64($r[1]);
close $fh;
}
Результатом выполнения скрипта(при условии доступности сервера) является архив с именем вида: reestr_yyyy_mm_dd.zip
4.Ротация результатов
Даже при невысокой частоте скачивания, рано или поздно все пространство на жестком диске машины окажется занятно, что может привести к самым плачевным последствиям. Для того, чтобы длительное время поддерживать работоспособность системы необходимо организовать ротацию, т.е. по мере скачивания новых архивов, старые будут постепенно удаляться.
За ротацию отвкчает скрипт rotation.pl
Глубина ротации определяет, какое количество архивов будет одновременно находится в директории result(при заданной логике-за какой временной интервал в прошлое относительно текущего дня)
Листинг rotation.pl
use POSIX qw(strftime);
use Time::Local;
#Глубина ротации
$birthtime =timelocal(localtime());
$interval = 0 + # 0 секунд
0 * 60 + # 0 минут
0 * 60 * 60 + # 0 часов
50 * 60 * 60 * 24; # и 20 дней
$then = $birthtime - $interval;
my $date = strftime "%Y_%m_%d", localtime($then);
#Убираем устаревший файл
unlink('<путь к фалу>reestr_'.$date.'.zip');
5.Запуск по расписанию
Для запуска по расписанию использовал стандартный планировщик заданий Windows
schtasks (http://www.windowsfaq.ru/content/view/83/57)
Интервал времени, через который будет запускаться roscomnadzor.bat должен быть большим, чем время ожидания запроса от сервера
Я запустил систему в середине марта, пока все работает без сбоев.
Спасибо за внимание. Надеюсь моя статья была вам полезна.
Автор: mihail1812