◆ Basic 認証に失敗したら自動で拒否る → ウェブのセキュリティうp!→ (^p^)
今回もメモです。ちょっと会社で仕事中、同僚と「あったら良いかもね」という話になり作ってみたのがこれ。Apache の Basic 認証に失敗すると、自動的にアクセスを拒否する Perl スクリプトをつくってみました。
動作原理はシンプルです。 .htaccess の「deny from xxxx」という記述を自動生成する CGI を作成しました。具体的なステップは、以下の通りです。
HTTP コード 401 (Unauthorized) 時に指定の CGI を動作
↓
IP アドレスをファイルに記録する
↓
記録された IP アドレスが既定回数を超える
↓
.htaccess でホストを拒否る(deny from に追加する)
という単純なものです。
試作したスクリプトでは、連続x回アクセスすると拒否するようにしてみました(xは任意)。
動作確認の出来る URL は http://pocketstudio.jp/auth/ です。ここでは、3回連続してパスワードを間違えると、次回以降は自動でアクセスを拒否し、認証画面すら表示させません。
以下、設置手順です。
◆動作条件
動作の前提として
- .htaccess がサーバで利用可能なこと(AllowOverride All)
- ウェブサーバが Apache で、Basic 認証が使えること(Options All)
- 拡張子 .cgi のファイルを CGI (Perlスクリプト) として動作できること
が必要になります。
◆ 設置
まず、URL は「 http://example.jp/auth/ 」、サーバ内のパスは「 /var/www/html/auth/ 」と仮定して進めます。
サーバの /var/www/html/auth/ ディレクトリ内には、以下のファイルを設置します。
- .htaccess ( パーミッション rw—-rw- [606] )
ErrorDocument 401 /autodeny.cgi AuthType Basic AuthName "Authentication required" AuthUserFile /var/www/html/auth/.htpasswd AuthGroupFile /dev/null require valid-user Order Allow,Deny Allow from all
- .htlist ( パーミッション rw—-rw- [606])
認証に失敗したIPアドレスと回数を記録するものです。設置時は中身はカラッポで大丈夫です。(ファイル名を .htlist にしたのは、Apache のデフォルト設定で .ht* の付くファイル名は非表示に設定されているからです。非表示設定がなければ、このファイルはドキュメントルートとは違う階層にファイルを置くべきです。) - .htpasswd (rw—-r– [604])
認証用ファイルです。作成は、htpasswd コマンドを使います。$ htpasswd -c /var/www/html/auth/.htpasswd ユーザ名 New password: (画面に表示されませんが、パスワードを入力) Re-type new password: (パスワードを再入力) Adding password for user ユーザ名
次は、拒否用のスクリプト http://URL/deny.cgi を /var/www/html/autodeny.cgi に設置します。パーミッションは rwx—r-x [705] にしておきます。以下 autodeny.cgi の内容です。
#!/usr/bin/perl
# autodeny.cgi ver 0.1
#
# Masahito Zembutsu
# http://pocketstudio.jp/
$htaccess = '/var/www/html/auth/.htaccess';
$htlist = '/var/www/html/auth/.htlist';
$denyhost = $ENV{'REMOTE_ADDR'};
$COUNT = '3'; # 指定した回数連続して認証失敗すると、拒否する
if ($denyhost) {
my ($ip,$hit);
if (open(HOST,$htlist)) {
my $host = <HOST>;
($ip,$hit) = split(/\t/, $host);
close(HOST);
if ($ip ne $denyhost) {
$ip = $denyhost;
$hit = 1;
} else {
$hit++;
}
&denyHost($ip) if ($hit >= $COUNT);
}
if (open(HOST,">$htlist")) {
print HOST "$ip\t$hit";
close(HOST);
}
}
print "Content-type: text/plain\n\n";
print "Access Denied"; # 認証失敗後に表示されるメッセージ
exit;
sub denyHost {
if(open (HT,">>$htaccess")) {
print HT "deny from $_[0]\n";
}
return;
}
1;
あとは、ブラウザから http://URL/auth/ にアクセスします。3回連続してパスワード入力に失敗すると「Forbidden」に切り替わり、二度と認証できなくなります。
なお、再び認証できるようにするためには、.htaccess ファイルを開き、「deny from <IP Address>」の行を削除してください。
※ 例として HTTP status が 401 (Unauthorized) の時に適用されるようにしましたが、403 (forbiddon) や 404 (File not found) 時でも、同様の動作をさせることが出来ます。
設置・動作等でよく分からなければ、コメント欄等でお気軽にお訊ねください(・∀・)