The OpenNET Project / Index page

[ новости /+++ | форум | wiki | теги | ]

форумы  правила/FAQ  поиск  регистрация  вход/выход  слежка  RSS
"Парсер реестра с сайта Роскомнадзора"
Вариант для распечатки  
Пред. тема | След. тема 
Форум Открытые системы на сервере (Разное / FreeBSD)
Изначальное сообщение [ Отслеживать ]

"Парсер реестра с сайта Роскомнадзора"  +/
Сообщение от Hammer email(ok) on 04-Июн-14, 09:16 
#!/usr/local/bin/perl
use XML::DOM;
my $parser= XML::DOM::Parser->new();
my $doc = $parser->parsefile ("dump.xml"); # Дамп реестра
my $root = $doc->getDocumentElement();
@nodes =$doc->getElementsByTagName("domain");
open(f2 ,"+>result.txt") or die "ERROR: $!\n";
foreach my $nod (@nodes) {
    my $gtr = $nod->getFirstChild()->getData();
    print f2 "$gtr\n";
};

Вывод в файл result.txt

Ответить | Правка | Cообщить модератору

Оглавление

Сообщения по теме [Сортировка по времени | RSS]


1. "Парсер реестра с сайта Роскомнадзора"  +/
Сообщение от upf (ok) on 04-Июн-14, 13:32 
и гиде айпи? )
Ответить | Правка | ^ к родителю #0 | Наверх | Cообщить модератору

2. "Парсер реестра с сайта Роскомнадзора"  +/
Сообщение от Hammer email(ok) on 04-Июн-14, 13:55 
> и гиде айпи? )

Поменяй
@nodes =$doc->getElementsByTagName("domain");

на
@nodes =$doc->getElementsByTagName("ip");

будет тебе АЙПИ :)

Ответить | Правка | ^ к родителю #1 | Наверх | Cообщить модератору

3. "Парсер реестра с сайта Роскомнадзора"  +1 +/
Сообщение от McLeod095 (ok) on 04-Июн-14, 18:33 
>[оверквотинг удален]
> my $parser= XML::DOM::Parser->new();
> my $doc = $parser->parsefile ("dump.xml"); # Дамп реестра
> my $root = $doc->getDocumentElement();
> @nodes =$doc->getElementsByTagName("domain");
> open(f2 ,"+>result.txt") or die "ERROR: $!\n";
> foreach my $nod (@nodes) {
>     my $gtr = $nod->getFirstChild()->getData();
>     print f2 "$gtr\n";
> };
> Вывод в файл result.txt

я сделал так


sub parse_xml {
        my $xml = shift;
        my $simple = XML::Simple->new();
        my $data = $simple->XMLin($xml);
        my $urls;
        my $domains;
        my $blockDomains;
        my $ips;
        my %seenDomains;
        my %seenIps;

        foreach my $number (keys %{$data->{'content'}}){
                my $block = 0;
                if(ref($data->{'content'}{$number}{'url'}) eq "ARRAY"){
                        foreach my $url (@{$data->{'content'}{$number}{'url'}}){
                                if($url =~ /^https:/i){
                                        $block = 1;
                                }
                                push @$urls, quotemeta(trim($url));
                        }
                }
                else{
                        if($data->{'content'}{$number}{'url'} =~ /^https:/i){
                                $block = 1;
                        }
                        push @$urls, quotemeta(trim($data->{'content'}{$number}{'url'}));
                }
                if(! $seenDomains{$data->{'content'}{$number}{'domain'}}++){
                        if($block){
                                push @$blockDomains, $data->{'content'}{$number}{'domain'};
                        }
                        push @$domains, $data->{'content'}{$number}{'domain'};
                }
                if(ref($data->{'content'}{$number}{'ip'}) eq "ARRAY"){
                        foreach my $ip (@{$data->{'content'}{$number}{'ip'}}){
                                if(! $seenIps{$ip}++){
                                        push @$ips, $ip;
                                }
                        }
                }
                else{
                        if(! $seenIps{$data->{'content'}{$number}{'ip'}}++){
                                push @$ips, $data->{'content'}{$number}{'ip'};
                        }
                }
        }
        @$urls = sort @$urls;
        @$domains = sort @$domains;
        @$ips = sort @$ips;
        @$blockDomains = sort @$blockDomains;

        return ($urls, $domains, $ips, $blockDomains);
}

Пришлось поставить поддержку кодировки cp1251 для Simple::XML
Возвращаем url в виде пригодном для записи в файл который кормится squid у
domains аналогично только для блокировки по доменам
ips список ip адресов, у меня применяется для iptables+ipset
ну и blockDomains тоже список доменов которые вписываются в файл вида /etc/hosts и кормится dnsmasq, пришлось так извратиться что бы не заниматься подделыванием сертификатов на сквиде.

Ответить | Правка | ^ к родителю #0 | Наверх | Cообщить модератору

4. "Парсер реестра с сайта Роскомнадзора"  +/
Сообщение от Hammer (ok) on 04-Июн-14, 23:36 
> Пришлось поставить поддержку кодировки cp1251 для Simple::XML
> Возвращаем url в виде пригодном для записи в файл который кормится squid
> у
> domains аналогично только для блокировки по доменам
> ips список ip адресов, у меня применяется для iptables+ipset
> ну и blockDomains тоже список доменов которые вписываются в файл вида /etc/hosts
> и кормится dnsmasq, пришлось так извратиться что бы не заниматься подделыванием
> сертификатов на сквиде.

Ну у нас это бинд кушает, потому и отбираю по "domain", ip блокировать я считаю бессмысленным.

Ответить | Правка | ^ к родителю #3 | Наверх | Cообщить модератору

5. "Парсер реестра с сайта Роскомнадзора"  +/
Сообщение от McLeod095 (ok) on 05-Июн-14, 11:06 
>> Пришлось поставить поддержку кодировки cp1251 для Simple::XML
>> Возвращаем url в виде пригодном для записи в файл который кормится squid
>> у
>> domains аналогично только для блокировки по доменам
>> ips список ip адресов, у меня применяется для iptables+ipset
>> ну и blockDomains тоже список доменов которые вписываются в файл вида /etc/hosts
>> и кормится dnsmasq, пришлось так извратиться что бы не заниматься подделыванием
>> сертификатов на сквиде.
> Ну у нас это бинд кушает, потому и отбираю по "domain", ip
> блокировать я считаю бессмысленным.

Ну ипы блочатся только для хостов которые используют ssl, хотя может и для всех, давно делал не помню. Ну и по ip это уже так, для верности. Потому что готовилось все для прихода инспектора и здесь лучше перебдеть чем недобдеть.

Ответить | Правка | ^ к родителю #4 | Наверх | Cообщить модератору

6. "Парсер реестра с сайта Роскомнадзора"  +/
Сообщение от McLeod095 (ok) on 05-Июн-14, 11:10 
>> Пришлось поставить поддержку кодировки cp1251 для Simple::XML
>> Возвращаем url в виде пригодном для записи в файл который кормится squid
>> у
>> domains аналогично только для блокировки по доменам
>> ips список ip адресов, у меня применяется для iptables+ipset
>> ну и blockDomains тоже список доменов которые вписываются в файл вида /etc/hosts
>> и кормится dnsmasq, пришлось так извратиться что бы не заниматься подделыванием
>> сертификатов на сквиде.
> Ну у нас это бинд кушает, потому и отбираю по "domain", ip
> блокировать я считаю бессмысленным.

Если надо, могу выложить весь скрипт. Он довольно объемный оказался.
Логика работы простая
проверяем список, если есть изменения то применяем их. Также 4 раза в сутки производится обязательная закачка списка, что бы на той стороне видели что скачивается регулярно.

Ответить | Правка | ^ к родителю #4 | Наверх | Cообщить модератору

7. "Парсер реестра с сайта Роскомнадзора"  +/
Сообщение от Hammer email(ok) on 05-Июн-14, 12:02 
> Если надо, могу выложить весь скрипт. Он довольно объемный оказался.
> Логика работы простая
> проверяем список, если есть изменения то применяем их. Также 4 раза в
> сутки производится обязательная закачка списка, что бы на той стороне видели
> что скачивается регулярно.

Выложи, может кому пригодится.

Ответить | Правка | ^ к родителю #6 | Наверх | Cообщить модератору

9. "Парсер реестра с сайта Роскомнадзора"  +/
Сообщение от McLeod095 (ok) on 06-Июн-14, 10:56 
>> Если надо, могу выложить весь скрипт. Он довольно объемный оказался.
>> Логика работы простая
>> проверяем список, если есть изменения то применяем их. Также 4 раза в
>> сутки производится обязательная закачка списка, что бы на той стороне видели
>> что скачивается регулярно.
> Выложи, может кому пригодится.

Код не идеален, но вроде как работает и работает исправно


#!/usr/bin/env perl
#

use warnings;
use strict;
use MIME::Base64;
use SOAP::Lite;
use Fcntl qw(:flock);
use Archive::Extract;
use XML::Simple;
use Data::Dumper;
use utf8;
use Encode;
binmode STDOUT, ":utf8";

use constant {
    NOTICE => 0,
    WARN => 1,
    ERROR => 2,
    DEBUG => 3,
};

# Отключаем буферизацию вывода
$|=1;

# Название компании по которой делаем выгрузку, файлы должны иметь вид компания.req компания.sig
my $company = shift or die("Use script with parameters\n");
my $requestFile = "/root/bin/" . $company . ".req";
my $signatureFile = "/root/bin/" . $company .".sig";
my $registryFile = "/tmp/" . $company . ".registry.zip";
my $registryTime = 0;
my $retries = 240;                                            # Количество секунд ожидания приема файла
my $step = 30;                                                # Опрашивать каждые  step  секунд
my $update = 1;
our $debug = 0;

my $aclDomainFile = "/etc/squid/block_domain.acl";
my $aclUrlFile = "/etc/squid/block_url.acl";
my $hostFile = "/etc/squid/banned_hosts";

my $request;
my $signature;

sub trim {
    my $text = shift;
    $text =~ s/^\s+|\s+$//g;
    return $text;
}

sub getLevel {
    my $level = shift;
    if($level == 0){
        return "NOTICE";
    }
    elsif($level == 1){
        return "WARN";
    }
    elsif($level == 2){
        return "ERROR";
    }
    return "DEBUG";
}

sub _log {
    my $level = shift;
    my $message = shift;
    if($debug == 1 || ($level < DEBUG and $debug == 0)){
        my ($second, $minute, $hour, $mday, $mon, $year, $wday, $yday, undef) = localtime(time);
        $year += 1900;
        $mon += 1;
        printf("ddd-d:d:d : %s : %s", $year, $mon, $mday, $hour, $minute, $second, getLevel($level), $message);
    }
}

# Разархивируем файл
sub unzip {
    my $zip = shift;
    my $archive = Archive::Extract->new( archive => $zip);
    my $archive_ok = $archive->extract( to => '/tmp') or die "Cannot extract files from $zip: $archive->error";
    # Пока путь возвращаем через костыль
    return "/tmp/dump.xml";
}

# Пасрим XML
sub parse_xml {
    my $xml = shift;
    my $simple = XML::Simple->new();
    my $data = $simple->XMLin($xml);
    my $urls;
    my $domains;
    my $blockDomains;
    my $ips;
    my %seenDomains;
    my %seenIps;

    foreach my $number (keys %{$data->{'content'}}){
        my $block = 0;
        if(ref($data->{'content'}{$number}{'url'}) eq "ARRAY"){
            foreach my $url (@{$data->{'content'}{$number}{'url'}}){
                if($url =~ /^https:/i){
                    $block = 1;
                }
                push @$urls, quotemeta(trim($url));
            }
        }
        else{
            if($data->{'content'}{$number}{'url'} =~ /^https:/i){
                $block = 1;
            }
            push @$urls, quotemeta(trim($data->{'content'}{$number}{'url'}));
        }
        if(! $seenDomains{$data->{'content'}{$number}{'domain'}}++){
            if($block){
                push @$blockDomains, $data->{'content'}{$number}{'domain'};
            }
            push @$domains, $data->{'content'}{$number}{'domain'};
        }
        if(ref($data->{'content'}{$number}{'ip'}) eq "ARRAY"){
            foreach my $ip (@{$data->{'content'}{$number}{'ip'}}){
                if(! $seenIps{$ip}++){
                    push @$ips, $ip;
                }
            }
        }
        else{
            if(! $seenIps{$data->{'content'}{$number}{'ip'}}++){
                push @$ips, $data->{'content'}{$number}{'ip'};
            }
        }
    }
    @$urls = sort @$urls;
    @$domains = sort @$domains;
    @$ips = sort @$ips;
    @$blockDomains = sort @$blockDomains;

    return ($urls, $domains, $ips, $blockDomains);
}

sub _ipset {
    my $ips = shift;
    my $ipset = "/usr/sbin/ipset";
    my $ipsetName = "blockip";
    my $ipsetTemp = "blocktmp";

    system "$ipset create $ipsetTemp hash:ip";
    foreach my $ip (@{$ips}){
        system "$ipset add $ipsetTemp $ip";
    }
    system "$ipset swap $ipsetTemp $ipsetName";
    system "$ipset destroy $ipsetTemp";
}

# Логирования, надо отключить после тестов
my $logFile = "/tmp/" . $company . ".log";
open LOGFILE, ">>$logFile" or die "Cannot open log file $logFile: $!";

# Переключаем стандартный вывод в файл логирования
select LOGFILE;

my $currentTime = time;
my ($second, $minute, $hour, undef, undef, undef, undef, undef, undef) = localtime($currentTime);

# Если файл реестра существует запоминаем время последнего редактирования
if(-e $registryFile){
    _log DEBUG, "Registry file $registryFile exists\n";
    $registryTime = (stat($registryFile))[9];
}
else{
    _log DEBUG, "Registry file $registryFile not exists\n";
}

# 4 раза в сутки скачиваем файл реестра обязательно в независимости от последеного обновления файла и реестра
if( ($hour == 0 and ($minute >=0 and $minute <10) and $registryTime < $currentTime - 600) or
    ($hour == 6 and ($minute >=0 and $minute <10) and $registryTime < $currentTime - 600) or
    ($hour == 12 and ($minute >=0 and $minute <10) and $registryTime < $currentTime - 600) or
    ($hour == 18 and ($minute >=0 and $minute <10) and $registryTime < $currentTime - 600)) {
    _log NOTICE, "Time update is now\n";
    $registryTime = 0;
}
    
unless(open REQUEST, $requestFile){
    _log ERROR, "Cannot open request file $requestFile\n";
    exit 1;
}
$request .= $_ while <REQUEST>;
close REQUEST;

unless(open SIGNATURE, $signatureFile){
    _log ERROR, "Cannot open signature file $signatureFile\n";
    exit 1;
}
$signature .= $_ while <SIGNATURE>;
close SIGNATURE;

my $soap = SOAP::Lite->service("http://vigruzki.rkn.gov.ru/services/OperatorRequest/?wsdl");
$SOAP::Constants::PREFIX_ENV = 'SOAP-ENV';

# метод возвращает время в милисекундах, нам и секунд достаточно!! )
my $lastUpdateTime = ($soap->getLastDumpDateEx)[1] * 0.001;
# Убрать после теста
_log NOTICE, "File update time:     $registryTime\n";
_log NOTICE, "Registry update time: $lastUpdateTime\n";

# Если есть срочные обновления в реестре запращиваем файл реестра и в течении времени ожидания приема файла пробуем загрузить файл раз в step секунд
if($lastUpdateTime > $registryTime){
    _log NOTICE, "Trying update registry file\n";
    my @sendRequest = $soap->sendRequest($request, $signature);
    if($sendRequest[0] eq "true"){
        unless(open REGISTRY, ">$registryFile"){
            _log ERROR, "Cannot open file $registryFile\n";
            exit 1;
        }
        flock REGISTRY, LOCK_EX;
        my $code = $sendRequest[2];
        _log NOTICE, "Code for checking\t\t$code\n";
        while ($retries > 0) {
            _log NOTICE, "Trying get result for check code $code. Wait $retries seconds\n";
            $retries -= $step;
            sleep $step;
            my @getResult = $soap->getResult($code);
            if($getResult[0] eq "true"){
                _log DEBUG, "Update request for code $code is answered\n";
                print REGISTRY decode_base64($getResult[1]);
                _log NOTICE, "Registry updated\n";
                my $xml = unzip($registryFile);
                my ($urls, $domains, $ips, $blockDomains) = parse_xml(unzip($registryFile));
                
                _log DEBUG, "Update ipset";
                _ipset $ips;

                unless(open SQUIDACL, ">$aclDomainFile"){
                    _log ERROR, "Cannot open acl file $aclDomainFile\n";
                    exit 1;
                }
                flock SQUIDACL, LOCK_EX;
                binmode SQUIDACL, ":utf8";
                foreach (@{$domains}){
                    print SQUIDACL "$_\n";
                }
                close SQUIDACL;

                unless(open SQUIDACL, ">$aclUrlFile"){
                    _log ERROR, "Cannot open acl file $aclUrlFile\n";
                    exit 1;
                }

                flock SQUIDACL, LOCK_EX;
                binmode SQUIDACL, ":utf8";
                foreach (@{$urls}){
                    print SQUIDACL "$_\n";
                }
                close SQUIDACL;

                unless (open BLOCKHOSTS, ">$hostFile") {
                    _log ERROR, "Cannot open hosts file $hostFile\n";
                    exit 1;
                }

                flock BLOCKHOSTS, LOCK_EX;
                binmode BLOCKHOSTS, ":utf8";
                foreach (@$blockDomains){
                    print BLOCKHOSTS "192.168.202.1\t$_\n";
                }
                close BLOCKHOSTS;
                $update = 0;
                last;
            }
        }
        close REGISTRY;
    }
    else{
        _log ERROR, "Cannot send request:  $sendRequest[1]\n";
    }
}    
select STDOUT;
close LOGFILE;
exit $update;

Запускается он вот такой строчкой в /etc/crontab


*/5 * * * * root if /root/bin/vigruzki.update.pl company; then service squid reload; service dnsmasq reload; fi

Пришлось писать для разных файлов тк разные юр лица и для каждого менять в скрипте даже значение переменной не сильно хотелось.

Ответить | Правка | ^ к родителю #7 | Наверх | Cообщить модератору

11. "Парсер реестра с сайта Роскомнадзора"  +/
Сообщение от dlyserg (ok) on 03-Дек-15, 02:57 
>>> Если надо, могу выложить весь скрипт. Он довольно объемный оказался.

Добрый день, натолкнулся на ваше решение, интересует момент со сквидом.
Не возникло ли проблем с блокировкой сквидом распарсеных урлов?
Часть из имеющихся в реестре ну никак не поддаются блокировке.
такая беда например происходит с практически всеми урлами суицид-форума.
заранее спасибо.

Ответить | Правка | ^ к родителю #9 | Наверх | Cообщить модератору

12. "Парсер реестра с сайта Роскомнадзора"  +/
Сообщение от Hammer (ok) on 03-Дек-15, 03:58 
>>>> Если надо, могу выложить весь скрипт. Он довольно объемный оказался.
> Добрый день, натолкнулся на ваше решение, интересует момент со сквидом.
> Не возникло ли проблем с блокировкой сквидом распарсеных урлов?
> Часть из имеющихся в реестре ну никак не поддаются блокировке.
> такая беда например происходит с практически всеми урлами суицид-форума.
> заранее спасибо.

да нет там никаких проблем. могу помочь.

Ответить | Правка | ^ к родителю #11 | Наверх | Cообщить модератору

13. "Парсер реестра с сайта Роскомнадзора"  +/
Сообщение от dlyserg (ok) on 12-Дек-15, 23:12 
> да нет там никаких проблем. могу помочь.

благодарствую, поборол.
оказалось лучшие для сквида перекодировать урл обартно в utf8.


Ответить | Правка | ^ к родителю #12 | Наверх | Cообщить модератору

14. "Парсер реестра с сайта Роскомнадзора"  +/
Сообщение от Антон email(??) on 28-Апр-17, 22:25 
>[оверквотинг удален]
> close LOGFILE;
> exit $update;
>
> Запускается он вот такой строчкой в /etc/crontab
>
 
> */5 * * * * root if /root/bin/vigruzki.update.pl company; then service squid
> reload; service dnsmasq reload; fi
>

> Пришлось писать для разных файлов тк разные юр лица и для каждого
> менять в скрипте даже значение переменной не сильно хотелось.

Здравствуйте. Я в перле почти ничего не понимаю, поэтому прошу помощи.
Судя по скрипту Ip адреса парсятся все что есть в дампе, а как
можно переделать скрипт чтобы парсились только те IP, где в теге <content> стоит тип блокировки blockType="ip" Заранее спасибо.


Ответить | Правка | ^ к родителю #9 | Наверх | Cообщить модератору

8. "Парсер реестра с сайта Роскомнадзора"  +/
Сообщение от михалыч (ok) on 05-Июн-14, 17:26 
Потестил, тут, на досуге. Разными парсерами.
XML::DOM
#!/usr/bin/perl

use strict;
use warnings;
use XML::DOM;

my $parser = XML::DOM::Parser->new();
my $dom    = $parser->parsefile ("dump.xml") or die;

open(FH, ">", "result.txt") or die;

my @nodes = $dom->getElementsByTagName("domain");
foreach my $node (@nodes) {
    print FH $node->getFirstChild()->getData(), "\n";
}

close FH;

XML::LibXML
#!/usr/bin/perl

use strict;
use warnings;
use XML::LibXML;

my $parser = XML::LibXML->new();
my $dom    = $parser->parse_file("dump.xml") or die;

open(FH, ">", "result2.txt") or die;

my @nodes = $dom->getElementsByTagName("domain");
foreach my $node (@nodes) {
    print FH $node->firstChild()->data, "\n";
}

close FH;

XML::Twig
#!/usr/bin/perl

use strict;
use warnings;
use XML::Twig;

my $parser = XML::Twig->new();
my $dom    = $parser->parsefile('dump.xml') or die;

open(FH, ">", "result3.txt") or die;

my @nodes = $dom->root->children('content');
foreach my $node (@nodes) {
    print FH $node->first_child('domain')->text, "\n";
}

close FH;

XML::Simple
#!/usr/bin/perl

use strict;
use warnings;
use XML::Simple;

my $parser = XML::Simple->new();
my $dom    = $parser->XMLin('dump.xml') or die;

open(FH, ">", "result4.txt") or die;

foreach my $node (values %{$dom->{'content'}}) {
    print FH $node->{'domain'}, "\n";
}

close FH;

От Twig ожидал большего. Зря.)) Хотя.., это же как из пушки по воробьям палить.
А самый быстрый, можно сказать реактивный, оказался LibXML

Ответить | Правка | ^ к родителю #0 | Наверх | Cообщить модератору

10. "Парсер реестра с сайта Роскомнадзора"  +/
Сообщение от Hammer (ok) on 08-Июн-14, 06:31 
>[оверквотинг удален]
> use XML::Simple;
> my $parser = XML::Simple->new();
> my $dom    = $parser->XMLin('dump.xml') or die;
> open(FH, ">", "result4.txt") or die;
> foreach my $node (values %{$dom->{'content'}}) {
>     print FH $node->{'domain'}, "\n";
> }
> close FH;От Twig ожидал большего. Зря.)) Хотя.., это же как из пушки
> по воробьям палить.
> А самый быстрый, можно сказать реактивный, оказался LibXML

Спасибо! Дельный коммент. Мне что то и в голову не приходило пробовать разные варианты. Плюсую.

Ответить | Правка | ^ к родителю #8 | Наверх | Cообщить модератору

Архив | Удалить

Рекомендовать для помещения в FAQ | Индекс форумов | Темы | Пред. тема | След. тема




Спонсоры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2022 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру