◆ 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) 時でも、同様の動作をさせることが出来ます。
設置・動作等でよく分からなければ、コメント欄等でお気軽にお訊ねください(・∀・)