#!/usr/bin/perl
$ver = "1.0"; #変更しないで下さい
#+------------------------------------------------------------------------
#|最後の良心 (ページの門番 - CGI方式)
#|(C)1999-2003 不可思議絵の具 (http://www.skipup.com/~fuka/)
#+------------------------------------------------------------------------
#- 改修履歴 -
# 2003/01/13 1.0 より柔軟なアドレス指定。ログ機能追加。
# 2000/06/09 0.3 さらにクソつまんない欠陥を修正。 逝ってよし>俺
# 2000/06/07 0.2 つまんないsyntax errorを修正。
# 1999/10/12 0.1 ちくちく作ってみる。
#+------------------------------------------------------------------------
#☆☆☆☆☆ 設定部 ☆☆☆☆☆
#+------------------------------------------------------------------------
### ≪必須設定項目≫
# [来て欲しくない人(ホスト)ブラックリスト]
# ワイルドカードを使用できます。 * は任意数の文字列を、? は1文字を表します。
@uDenyHost = (
'proxy*.*', #先頭に"proxy"を含むドメイン全てを排除 = プロキシを使うユーザを排除
'211.250.61.*',
'pxy*.*',
'proxy*.*',
'*proxy*.*',
'*proxy.*',
);
# [ログファイル名]
$uLogName = 'gate.log';
# [ログ保存件数]
$uMaxLog = 50;
# [チェックした後に転送したいページ]
$uURL = 'wingbbs.cgi';
### ≪警告画面の表示設定≫
# [スタイルシートファイル名]
$uCssName = 'gate.css';
# [警告画面のタイトル]
$uMsgTitle = '注意';
# [警告画面の内容]
# HTMLを使用できます。
$uMsgBody = '
−注意−
残念ですが、あなたのアクセスは許されていません。
直ちに退去してください。
';
# ※ここからは分かる人だけ弄って下さい。
# (タブのサイズ・[4]、折返し・[無し]で綺麗に表示されます)
#+------------------------------------------------------------------------
#|&main
#+------------------------------------------------------------------------
### 初期処理
# 変数宣言
my @log; # ログ格納用ワーク
my $NewLine = ''; # 新規ログ行
my $IsReject = 0; # 招かれざる客であるか?
my $host = ''; # IP/ホスト名
# HTMLヘッダ部
$HTMLHeader = "
$uMsgTitle
";
# HTMLフッタ部(+コピーライト)
$HTMLFooter = "
最後の良心 ${ver}
";
# 訪問者のリモートホストを取得する
$host = &getRemoteHost($ENV{'REMOTE_ADDR'});
### メイン処理
&openLog; # ログファイルを開く
$IsReject = &compareIP(\@uDenyHost, $host); # IPをチェックする
if ($IsReject == 0) { ## ブラックリストと一致しなかった場合
$NewLine = &makeNewLine('OK', $host); # ログ新規行準備
# 本来のページに飛ばす
print "Location: $uURL\n\n";
} else { ## ブラックリストと一致した場合
$NewLine = &makeNewLine('NG', $host); # ログ新規行準備
# 準備したエラー画面を出力する
print "Content-type: text/html\n\n";
print "$HTMLHeader";
print "$uMsgBody";
print "$HTMLFooter";
}
### 後処理
&writeLog; # ログを書き込む
&closeLog; # ログファイルを閉じる
exit;
### ログ新規行準備
sub makeNewLine {
my($status, $host) = @_;
return &makeDate(time)."\t$status\t$host";
}
### ログ開く
sub openLog {
unless (open(LOG,"+<./${uLogName}")) {
print "$HTMLHeader";
print "ログファイルを開くことができませんでした。
";
print "$HTMLFooter";
exit(1);
}
flock(LOG, 2);
chomp(@log = );
}
### ログ書き込む
sub writeLog {
unshift(@log, $NewLine); # 新しいログを付け足し、
splice(@log, $uMaxLog); # 古いログは消し去る
seek(LOG, 0, 0);
foreach (@log) { print LOG "$_\n"; }
truncate(LOG,tell);
}
### ログ閉じる
sub closeLog {
flock(LOG, 8);
close(LOG);
}
### リモートホストを取得する
sub getRemoteHost {
my($ip) = @_;
$ip = gethostbyaddr(pack("C4", split(/\./, $ip)), 2) || $ip;
return $ip;
}
#---------------------------------------------------------------------
# 弾くべきIPかチェック ($IPlistと$targetIPを比較し、一致数を返す)
# 引数:
# $IPlist (IPアドレス/FQDN入り配列参照)
# $targetIP (比較対象IPアドレス/FQDN)
# 返り値:
# 0 (一致無し)
# 1以上 (一致有り/一致件数)
#---------------------------------------------------------------------
sub compareIP {
my($IPlist, $targetIP) = @_;
my $hit = 0;
foreach (@$IPlist) {
$_ = '^'.$_.'$';
s/\./\\\./g; # "." → "\."
s/\?/\./g; # "?" → "."
s/\*/\.\*/g; # "*" → ".*"
if ($targetIP =~ $_) { $hit++; }
}
return $hit;
}
#---------------------------------------------------------------------
# 通算秒から日時を得る関数
# 引数:
# 通算秒 (1970/01/01 00:00:00から)
# 返り値:
# 文字列 [年/月/日/(曜) 時:分:秒]
#---------------------------------------------------------------------
sub makeDate {
my($t) = @_;
my(@wdays, $sec, $min, $hour, $day, $mon, $year, $wday);
@wdays=('日','月','火','水','木','金','土');
($sec,$min,$hour,$day,$mon,$year,$wday) = localtime($t);
return sprintf("%d/%02d/%02d(%s) %02d:%02d:%02d",1900+$year,$mon+1,$day,$wdays[$wday],$hour,$min,$sec);
}