IPアドレスを入れると日本か海外が表示されます。
ただし、結果に責を負うものではありませんのでご承知ください。
ブログにスパム?海外からアクセス
it-azusaのトップに時々多量のアクセスがあります。ロボットでもなく、通常のアクセスでもないようです。アクセスログを調べていますが、米国だったり、他の国だったり、日本ではないようです。
リファラスパムという可能性もあるようです。リファラスパムというのは、このようにアクセス解析をおこなっているものが、リファラを辿って送信先のページをクリックするのを狙っているようです。最悪の場合はウィルスを拾うことにもなりかねないようです。
いずれにしろ、海外からのアクセスはロボットを除いては必要ないので、まずは海外かどうかをそれを調べようと思います。
海外からのアクセスを制限する方法は、.htaccessファイルでおこなうか、Googleアナリティクスのフィルタでもできるようです。
IPアドレスのデータベースを作成
IPアドレスは各国への割り当てが決まっているので、IPアドレスを調べれば、それが日本か海外かが分かります。日本のIPアドレスの一覧はJPNIC他いくつかのサイトが公開してくれています。ここでは、下記のサイトの一覧表テキストを使用しました。
日本[jp]に割り当てられたIPアドレスの一覧 : ipv4.fetus.jp
テキストの中身は以下のようになっています。CIDR方式で、/の右の数字はサブネットマスクです。左からの有効ビットの桁数です。それぞれがIPアドレスの範囲を表しています。
このままではデータベースにはならないので、これをMySQLのフォーマットに変換してやります。notepadd++等のエディタで\r\n等を使って置換できます。ここでは5個の数字に分解してセットしています。
60.236.0.0/14 60.254.192.0/18 61.4.128.0/19 61.4.160.0/20 : INSERT INTO `MST_IP` VALUES(60,236,0,0,14); INSERT INTO `MST_IP` VALUES(60,254,192,0,18); INSERT INTO `MST_IP` VALUES(61,4,128,0,19); INSERT INTO `MST_IP` VALUES(61,4,160,0,20); :
IPアドレスの計算方法
これでデータベースには5個の数値コラムができましたが、このままでは入ってきたIPアドレス(例えば60.238.xxx.xxx)が範囲内にあるかどうか、簡単には分かりません。そこで、先頭アドレスと終了アドレスのコラムを作る必要があります。
IPアドレスを数値にする方法は、いくつかあるようですが、普通は4個の数字を2進数に変換して、それを連結し2進数から10進数に変換するという方法のようです。4個の数字をそれぞれ3桁の数字文字列にしてから、それを連結して12桁の数値に変換するという方法もあるようです。ただし12桁の数値は32ビットOSでは桁あふれになりますから注意が必要です。
ここではPHPのip2long()という関数を使ってアドレスの計算をします。
60.236.0.0/14 の場合 $max = ip2long('255.255.255.255'); $ips = ip2long('60.236.0.0'); $bit = 14; $sft = 32 - $bit; $int = $max; $int = $int >> $sft; $int = $int << $sft; $sub = $int; $subの中身 11111111111111000000000000000000
ip2long()という関数は、ipをlong_intに変換するという意味だと思われますが、PHPにはlong_intの定義がないので、計算時には注意が必要です。
$maxは32ビットの最大値です。
$bitがサブネットマスクの有効ビット数です。
32との差を右と左にシフトしてサブネットマスクを作ります。
32ビット整数であれば、左シフトだけでいいのですが、64ビットだと思いがけない数値になる可能性があるからです。
$ipsと$subのANDを計算すると、先頭アドレスになりますが、ここでは$ipsをそのまま先頭アドレスとして使用します。
サブネットマスクのビットを反転します。ここでは反転した数値を$maxでマスクしています。
$sub = ~$sub & $max; $subの中身 111111111111111111
上記と同じ理由で64ビットの場合、反転しただけだと下記の数値になり、予定していた結果にはなりません。
1111 …… 1111100000000000000111111111111111111
$ipsと$subのORを計算すると、終了アドレスが出ます。
$ipe = $ips | $sub; 結果は、 $ips 1022099456 (60.236.0.0) $ipe 1022361599 (60.239.255.255)
となり、60.238.xxx.xxxはこの範囲に入るこをが分かります。つまり国内からのアクセスということです。
この先頭アドレスと終了アドレスをMySQLに登録して検索できるようにします。ただしそのままint定義のコラムにセットするとおかしな数値になることがあるので注意が必要です。理由は上記と共通なところもありますが、整数は一番上のビットをマイナスとして扱う性質があるからです。そのため今回は12桁のdecimalとして登録しました。正常に動作しています。