以前の記事で、iptables を用いて特定のポートへの接続を日本国内のみに制限するスクリプトを書いたが、BlueOnyx では勝手に iptables がリセットされて、ファイアウォールが全開になっていることがたまにあった。これでは危険なので、hosts.allow を用いて、せめて sshd だけでも塞いでおくことにした。
複数の CIDR ブロックを集約 (aggregation) するために、aggregate というプログラムを RPM でインストールする。
# mkdir /usr/local/rpm
# cd /usr/local/rpm
# wget "http://sourceforge.jp/frs/g_redir.php?m=jaist&f=%2Fcnsubnetlookup%2Faggregate-1.6-4.el5.i386.rpm"
# rpm -ivh aggregate-1.6-4.el5.i386.rpm
各ファイルを格納するためのディレクトリを作成する。
# mkdir /root/countryfilter
各国の IP アドレスの割当リストから日本のものを取り出し、10 進数表記に変換する Perl スクリプトを作成する。
# vi conv.pl
#!/usr/bin/perl
use strict;
while (<STDIN>) {
chomp;
my ($registry, $cc, $type, $start, $value, undef, $status) = split(/\|/);
unless ($type eq 'ipv4' && ($status eq 'allocated' || $status eq 'assigned')) { next; }
#unless ($cc eq 'JP') { next; }
my $SubnetMaskBin = sprintf('%b', scalar($value));
if ($SubnetMaskBin !~ /^1(0+)$/) {
# CIDR 表記できない
next;
}
my $prefix = 32 - length($1);
my $num;
$num = ($num << 8) + $_ foreach (split(/\./, $start));
if (($num % $value) != 0) {
# 分割しなければならない
next;
}
print $start.'/'.$prefix."\t".$cc."\n";
}
日本国内の IP アドレスリスト (jp.txt) を生成して hosts.allow に書き込むシェルスクリプト (update.sh) を作成する。
# vi update.sh
#!/bin/sh
DIR=$(cd $(dirname $0); pwd)
cd $DIR
# aggregate がインストールされているかチェック
aggregate=`which aggregate 2> /dev/null | wc -l`
if [ $aggregate -ne 1 ]; then
echo "aggregate: command not found" >&2
exit 1
fi
# 各 RIP から IP アドレスの割当リストを取得
rm -f ./delegated-*
wget ftp://ftp.arin.net/pub/stats/arin/delegated-arin-latest > /dev/null 2>&1
wget ftp://ftp.ripe.net/pub/stats/ripencc/delegated-ripencc-latest > /dev/null 2>&1
wget ftp://ftp.apnic.net/pub/stats/apnic/delegated-apnic-latest > /dev/null 2>&1
wget ftp://ftp.lacnic.net/pub/stats/lacnic/delegated-lacnic-latest > /dev/null 2>&1
wget ftp://ftp.afrinic.net/pub/stats/afrinic/delegated-afrinic-latest > /dev/null 2>&1
if [ ! -f delegated-apnic-latest ]; then
echo "delegated-apnic-latest was not found." >&2
exit 1
fi
# 日本国内のもののみを取り出して集約
cat delegated-* | perl ./conv.pl | grep -E 'JP$' | sort -n | aggregate -q > jp.txt
# CIDR 表記をサブネットマスク表記に変換
sed -i 's/\/8$/\/255.0.0.0 /' ./jp.txt
sed -i 's/\/9$/\/255.128.0.0 /' ./jp.txt
sed -i 's/\/10$/\/255.192.0.0 /' ./jp.txt
sed -i 's/\/11$/\/255.224.0.0 /' ./jp.txt
sed -i 's/\/12$/\/255.240.0.0 /' ./jp.txt
sed -i 's/\/13$/\/255.248.0.0 /' ./jp.txt
sed -i 's/\/14$/\/255.252.0.0 /' ./jp.txt
sed -i 's/\/15$/\/255.254.0.0 /' ./jp.txt
sed -i 's/\/16$/\/255.255.0.0 /' ./jp.txt
sed -i 's/\/17$/\/255.255.128.0 /' ./jp.txt
sed -i 's/\/18$/\/255.255.192.0 /' ./jp.txt
sed -i 's/\/19$/\/255.255.224.0 /' ./jp.txt
sed -i 's/\/20$/\/255.255.240.0 /' ./jp.txt
sed -i 's/\/21$/\/255.255.248.0 /' ./jp.txt
sed -i 's/\/22$/\/255.255.252.0 /' ./jp.txt
sed -i 's/\/23$/\/255.255.254.0 /' ./jp.txt
sed -i 's/\/24$/\/255.255.255.0 /' ./jp.txt
sed -i 's/\/25$/\/255.255.255.128 /' ./jp.txt
sed -i 's/\/26$/\/255.255.255.192 /' ./jp.txt
sed -i 's/\/27$/\/255.255.255.224 /' ./jp.txt
sed -i 's/\/28$/\/255.255.255.240 /' ./jp.txt
# /etc/hosts.allow をリセット
sed -i -e '/#countryfilter/d' /etc/hosts.allow
# 日本国内の IP アドレスリストを書込
cat ./jp.txt | awk '{print "sshd: "$1" #countryfilter"}' >> /etc/hosts.allow
hosts.deny を編集して、sshd へのアクセスを原則禁止とする。
# vi /etc/hosts.deny
sshd: ALL
※ ssh で作業している場合、この時点で切断すると再接続できなくなるので注意。
ローカルホストからのアクセスは許可するために、hosts.allow の先頭に次の1行を追加する。
# vi /etc/hosts.allow
ALL: 127.0.0.1
:
作成したシェルスクリプトに実行権を与えて、実行する。
# chmod 700 update.sh
# ./update.sh
cron で一週間ごとに実行するように設定する。
# ln -s /root/countryfilter/update.sh /etc/cron.weekly/
以上で sshd への接続は日本国内のみに制限された。
コメント