#!/usr/bin/perl use strict; use warnings; use feature 'say'; use LWP::Simple; use Path::Tiny; use Data::Dump qw /dump/; my $dns_list_file = path 'dns.txt'; my $quick_test_file = path 'quick.txt'; my $deep_test_file = path 'deep.txt'; my $domains_list_file = path 'domains.txt'; my $quick_test_clock = 0.15; my $deep_test_clock = 1.0; my $quick_test_thresh = 21; my ( $ax, $bx, $cx, $dx, $dh, $dl, $dll ); sub delay { # Programmablauf unterbrechen # IN: -1---> [FLOAT] Zeit in Sekunden select( undef, undef, undef, shift ); } sub rndStr { # erzeugt eine Zufallszeichenkette # -1--> [SCALAR] Länge der Zeichenkette in Zeichen # -2--> [LIST] Menge der verfügbaren Zeichen # <---- [SCALAR] Zeichenkette join( '', @_[ map{ rand @_ } 1 .. shift ] ); }; sub myDig { # parst die für nshunter.pl nötigen Werte # der Ausgabe von dig in ein besser zu parsendes Format # -1--> [SCALAR] IP-Adresse des DNS-Servers # -2--> [SCALAR] Query # -3--> [SCALAR] Timeout # -4--> [SCALAR] Anzahl Versuche # <---- [SCALAR] Zeichenkette: 'STATUS;;ANTWORTZEIT[in ms]' my ( $dns, $query, $timeout, $tries ) = @_; my $status = 'ERROR'; my $qtime = '---'; my $in = qx[dig \@$dns $query +time=$timeout +tries=$tries]; my @list = split( /\n/, $in ); for ( @list ) { $status = 'NOCONN' if $_ =~ /;; connection timed out;/; $status = $1 if $_ =~ /.*status: (.*), .*/; $qtime = $1 if $_ =~ /^;; Query time: (.*) msec.*/; } # TODO Return a **HASH return "$status;;$qtime"; } say "DNS-SERVERLISTE AKTUALISIEREN..."; for ( qw[ de ch at ] ) { $ax = 'https://www.ungefiltert-surfen.de/nameserver/'.$_.'.txt'; $bx = get $ax; die "Konnte $ax nicht laden!" unless defined $bx; push @$dl, split( /\n/, $bx."\n" ); } # IPv4 only @$dl = grep( /.*\..*/, @$dl ); # doppelte IP's kicken %$dh = map { $_, 0 } @$dl; @$dl = keys( %$dh ); # Speichern @$dll = map( $_."\n", @$dl ); $dns_list_file->spew( @$dll ); ####### # QUICKTEST FOR ALL SERVERS ########################### $ax = $#$dl + 1; $cx = 1; say "QUICKTEST BEI $ax DNS-SERVERN DURCHFÜHREN..."; $quick_test_file->remove; local $SIG{CHLD} = "IGNORE"; # Kinder beenden sich selbst for ( @$dl ) { my $pid = fork; if ( not $pid ) { my $_temp = "$_;;"; $_temp .= myDig( $_, 'www.google.com', 4, 1 ).";;"; $_temp .= myDig( $_, 'www.google.com', 4, 1 ); $quick_test_file->append( $_temp."\n" ); exit; } say "[$cx/$ax] QUICKTEST DES DNS-SERVERS $_"; delay $quick_test_clock; $cx++; } say "AUF ANTWORTEN DER DNS-SERVER WARTEN..."; wait for @$dl; @$dl = $quick_test_file->lines; chomp(@$dl); $ax = $#$dl + 1; say "FÜR $ax DNS-SERVER LIEGEN DIE ERGEBNISSE DES QICKTESTS VOR..."; say $_ for @$dl; @$dl = grep( /.*;;NOERROR;;.*;;NOERROR;;.*/, @$dl ); $ax = $ax - $#$dl - 1; say "$ax DNS_SERVER SIND ZU FEHLERANFÄLLIG - LÖSCHEN!..."; $cx = 0; for ( 0 .. $#$dl ) { $ax = shift @$dl; $ax = [ split( /;;/, $ax ) ]; $bx = $$ax[2] + $$ax[4]; push @$dl, $$ax[0] if $bx < $quick_test_thresh; $cx++ if $bx >= $quick_test_thresh; } $ax = $#$dl + 1; say "$cx DNS-SERVER SIND GRUNDSÄTZLICH ZU LANGSAM - LÖSCHEN!..."; say "$ax DNS-SERVER WERDEN AN DEN DEEP_TEST ÜBERGEBEN..."; ####### # DEEP-TEST FOR WELL-QUICK-TESTED SERVERS ######################################### @$dll = $domains_list_file->lines; chomp( @$dll ); $deep_test_file->remove; $ax = $#$dl; $cx = 0; for ( 0 .. $ax ) { my $pid = fork; my $_ip = $$dl[$_]; if ( not $pid ) { my $_temp = "$_ip\n"; for ( @$dll ) { my $uncached = rndStr( 16, 'a'..'z' ).".$_"; $_temp .= " $uncached-->".myDig( $_ip, $uncached, 1, 1 )."\n"; } $deep_test_file->append( $_temp."\n" ); exit; } say "[".($cx+1)."/".($ax+1)."] DEEP-TEST DES DNS-SERVERS $_ip"; delay $deep_test_clock; $cx++; } say "AUF ANTWORTEN DER DNS-SERVER WARTEN..."; wait for 0 .. $ax;