海外からの頻繁な不正アクセス
FTPサーバーを立てると、海外からの頻繁な不正アクセスに悩まされます。最初のうちは、ログからそのIPアドレスをピックアップして、拒否するIPアドレスに登録していたのですが、不正アクセスはアドレス(サーバー)をランダムに変えて攻撃してくるため、登録しきれなくなり、中止しました。
不正アクセスはadmin、ftpuser、master等あらゆるIDでログインを試みてきます。FTPサーバーに限らず、どこのサーバーでも簡単には入れないようになっていますが、相手はハッキングソフトですから、やられる可能性は0ではありません。官公庁のホームページが改ざんされるのは、FTPサーバーのハッキングが主な原因の一つといわれています。
そこで、当FTPサーバーは、限られたユーザーに公開してあるため、拒否するIPアドレス(PC)ではなく、許可するIPアドレスを登録して、それ以外は全て拒否する方法をとることにしました。それには、利用している全ユーザーのIPアドレスを知る必要があります。
有効IPアドレス一覧を作成
一年半分のFTPサーバーのログファイルからIPアドレスの一覧を作成することにします。ログファイルの中には、連続する不正アクセスで4MB、200000行という膨大なファイルもあります。しかし全てを読まないと意味がないので、一番大きなファイルをマックス行に設定して読み込むことにしました。
企業でも個人宅でも、一般的にはIPアドレスはプロバイダから割り振られたものになります。複数台のPCでもIPマスカレードという方法で一つのIPアドレスでアクセスできるようになっています。ただしプロバイダから割り振られたIPアドレスはランダムに変更されるたため、一定ではありません。(別料金で固定IPアドレスを取得している場合は一定になります。)
ネットワークアドレスを取得
ランダムに変更されるIPアドレスを一つ一つ登録していたのでは、数が多すぎて非効率になります。そこで、プロバイダから割り振られているIPアドレスの範囲(ネットワークアドレス)を登録することにします。ネットワークアドレスを取得するには、JPNIC WHOIS Gatewayを使用します。ここでIPアドレスを検索すると、割り振られたネットワークアドレスおよび、さらに上位のネットワークアドレスを取得することができます。WHOISを手動で利用する場合は問題ありませんが、プログラムから利用する場合は、連続でアクセスしないよう、注意が必要です。
この情報を整理すると、個々のIPアドレスを、共通するネットワークアドレスにまとめることができます。JPNICで管理しているIPアドレスは日本のものなので、海外は対象外となり、WHOISでは該当なしとなります。
サブネットマスクを計算
当サーバーは複数PCとして、ネットワークアドレスを登録することができます。だだし、/24等のプレフィックス表示ではなく、サブネットマスクが必要なので、プレフィックスからサブネットマスクを計算する必要があります。PHPによるサブネットマスク(IPアドレスの範囲)の計算方法は、当ブログのIPアドレスの計算方法に載せてあります。今回はWindows用にasp.netで作成しましたので、それを載せておきます。
vb.netにもビット演算はありますが、 あまり使い勝手がよくないので、ここでは .netのConvertクラスを使用します。 プレフィックスからサブネットマスクの ビット文字列を作成します。 *.*.*.*/24 24は有効ビット数で、これが先頭アドレス (ネットワークアドレス)になります。 dim mlen = 32 - 24 'mlen=8 8はマスクのビット数、このネットワークの総数になります。 dim wm = left("00000000000000000000000000000000",mlen) 'wm="00000000" dim mbit = right("11111111111111111111111111111111" & wm,32) 'mbit="11111111111111111111111100000000" (サブネットマスク)になります。 ビット文字列をIPアドレスに変換。 "11111111111111111111111100000000" を8文字づつ整数に変換して、"."で区切る。 dim su as integer = Convert.toint32("11111111",2) 'su=255 Convert.toint32は文字列を指定進数で数値に変換します。 これを4回繰り返すと、"255.255.255.0" という 文字列になる。 IPアドレスを数値に変換する方法も載せておきます。 上記と逆に"."で区切られた数値を 8文字のビット文字列に変換します。 dim txt = Convert.ToString(su, 2) txt = right("00000000" & txt,8) これを接続して、32文字のビット文字列にします。 32文字のビット文字列をint64に変換します。 dim su as long = Convert.toint64(txt,2) 32ビットのintegerでは桁あふれになるので注意。