オープンリゾルバ撲滅に向けて
イタズラしたい人はご遠慮ください。作り方を公開しておきます。
※ Nginx + Mojolicious の環境を前提としています。
apacheでも大丈夫です♪
■Mojoliciousの環境作成
1 2 3 4 5 6 7 8 9 10 |
apt-get install perlbrew perlbrew init perlbrew install perl-5.16.3 perlbrew install-cpanm cat ~/perl5/perlbrew/etc/bashrc >> ~/.bashrc sourc ~/.bashrc perlbrew use perl-5.16.3 cpanm install Mojolicious cpanm install Net::DNS cpanm install IO::Socket::IP |
■プログラム
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
vi myapp.pl ----- #!/usr/bin/env perl use Mojolicious::Lite; use Net::DNS; use Sys::Syslog; use IO::Socket::IP; # share our %h_checkedFlag; # Documentation browser under "/perldoc" plugin 'PODRenderer'; openlog("dnschk", 'ndelay,pid', 'user'); my $res = Net::DNS::Resolver->new; $res->udp_timeout(1); $res->tcp_timeout(1); get '/check' =>sub { my $c = shift; my $flag = 0; #my $rAddr = $c->tx->remote_address; my $rAddr = $c->req->headers->header('X-Forwarded-For'); # When the IP is same, stop 60 sec. if(time - $h_checkedFlag{$rAddr} < 60 ){$flag = 3;} $h_checkedFlag{$rAddr} = time; if($rAddr =~ /[^.:0-9a-fA-F]+/) { $flag = 2; $rAddr = ''; } elsif(!$flag) { foreach my $vc (0..1) { $res->usevc($vc); $res->nameservers($rAddr); my $reply = $res->search("m.ROOT-SERVERS.NET"); if ($reply) { foreach my $rr ($reply->answer) { next unless $rr->type eq "A"; my $addr = $rr->address; $flag = 1; syslog('info', '%s,%s', $rAddr, $addr); } } else { syslog('info', 'query failed %s', $rAddr); } } } my $data = { ip => $rAddr, flag => $flag }; $c->render(json => $data); }; closelog; app->start; ----- |
プログラムを起動する
1 |
morbo myapp.pl |
■index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
cd /var/www/vhost/dnschk.snowdrop.asia/ wget 'http://code.jquery.com/jquery-1.11.1.min.js' vi index.html ------ <htlm> <head> <script src="/jquery-1.11.1.min.js"></script> <script> // <!-- function checkResolver(f) { $("#result-dns-open-resolver").html('checking...'); $.getJSON("/check",{},function(result) { switch (result.flag) { case 3: $("#result-dns-open-resolver").html('please wait.'); break; case 2: $("#result-dns-open-resolver").html('unexpected error.'); break; case 1: $("#result-dns-open-resolver").html('Oops. RELAY...'); break; case 0: $("#result-dns-open-resolver").html('Good! SAFETY.'); break; } }); } // --> </script> </head> <body> <form id="f" action="#"> <input type="button" value="check" /> <div id="result-dns-open-resolver"> </div></form> </body> ------ </htlm> |
■nginxの設定
1 2 3 4 5 6 7 8 9 10 |
vi /etc/nginx/conf.d/dnschk.snowdrop.asia.conf ----- proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Remote-Addr $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; location /check { proxy_pass http://127.0.0.1:3000/check; } ----- |
反映する
1 |
sudo /etc/init.d/nginx reload |