2011年05月17日

iptables で日本以外のアクセスを全部拒否する

 今日たまたまサーバの様子をmuninで見たら、普段は見かけないCPU usageが出ていたので、どうしたんだろうと思って調べると、sshdが余計に動いている。不審に思ってnetstatしてみると、.cnからのsshブルートフォース攻撃を受けていた。本来、JPのアドレスから以外のアクセスはiptablesで叩き落としていたのだが、先日いろいろカーネルをいじっていた時にiptablesの設定を変更して、そのJPフィルターを外したままにしてしまっていたのである。反省しきり。

 と、いうのは経験談として、日本以外のアクセスを全部拒否する、である。やりたいことは、RIRから日本に割り当てられているアドレスだけをリストアップして、iptablesでACCEPTし、該当しないものはDROPへ落とす、ということである。
 割り当て済みIPアドレスのリストはAPNICが配布している(http://ftp.apnic.net/stats/apnic/delegated-apnic-latest)が、このアドレスの一覧はiptablesにそのまま流し込めるようなフォーマットをしていない。しかし、このリストを使いやすいようにアドレス/マスクの形式に変換して提供している Office Namiという素晴らしいサイトがあるので、有り難くこれを使用させて貰うことにする。

 とりあえず、cidr形式のリストをダウンロードして、コマンドに列挙するなら、こんな感じになる。
% wget -q -O - http://nami.jp/ipv4bycc/cidr.txt.gz | \
gzip -d | \
grep "JP" | \
awk '{print "iptables -I RH-Firewall-1-INPUT 1 -p all -s ",$2," -j ACCEPT"}' \
> jpfilter.sh
% head jpfilter.sh
iptables -I RH-Firewall-1-INPUT 1 -p all -s 1.0.16.0/20 -j ACCEPT
iptables -I RH-Firewall-1-INPUT 1 -p all -s 1.0.64.0/18 -j ACCEPT
iptables -I RH-Firewall-1-INPUT 1 -p all -s 1.1.64.0/18 -j ACCEPT
iptables -I RH-Firewall-1-INPUT 1 -p all -s 1.5.0.0/16 -j ACCEPT
(略)
 awkのiptableコマンドの引数は環境に応じて適当に変更が必要だが、これで出てきたjpfilter.shをrootで実行すれば、今のiptablesにJPフィルターが追加できる。

 しかし、日本からのアクセスだからと言って無条件に許可するわけではないので、もう少し手を加える。
 INPUTチェインに入ってきたパケットは、日本以外のアクセスであれば叩き落とし、日本からのアクセスであれば、通常のフィルター動作を適用したいので、

1. 日本のアドレスのリストは ALLOW-JP-INPUT という別チェインにし、
2. INPUTチェインでは通常のフィルター(RH-Firewall-1-INPUT)でなくALLOW-JP-INPUTに渡し、
3. ALLOW-JP-INPUTチェインでは許可したものだけをRH-Firewall-1-INPUTに渡す

という風にする。
というわけで、まず /etc/sysconfig/iptables は、こんな感じ。
# Firewall configuration written by system-config-securitylevel
# Manual customization of this file is not recommended.
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:ALLOW-JP-INPUT - [0:0]
:RH-Firewall-1-INPUT - [0:0]
-A INPUT -s 127.0.0.0/8 -j ACCEPT
-A INPUT -s 192.168.0.0/16 -j RH-Firewall-1-INPUT #これはローカルネットワークの許可用
-A INPUT -j ALLOW-JP-INPUT
-A INPUT -j DROP
-A RH-Firewall-1-INPUT -i lo -j ACCEPT
(略)
 そして、{{{ALLOW-JP-INPUTチェインを生成する}スクリプトを作る}スクリプトを作る}。ややこしい。起動毎に適用したいので、/etc/sysconfig/iptabels-allowjp にフィルター内容を保存することにして、そのスクリプトを作るためのスクリプトを(get-iptable-jp.sh)作成。スクリプト get-iptable-jp.sh によって、スクリプト iptabels-allowjp が作成され、iptables の起動毎に iptabels-allowjp を実行させる、ということだ。
#!/bin/sh
wget -q -O - http://nami.jp/ipv4bycc/cidr.txt.gz |\
gzip -d |\
grep "JP" |awk '{print "iptables -A ALLOW-JP-INPUT -p all -s ",$2," -j RH-Firewall-1-INPUT"}'\
> /etc/sysconfig/iptables-allowjp
 次いで、/etc/rc.d/init.d/iptables に、起動時にJPフィルターを適用するように変更を加える。start() 内で、
:
if [ -n "$IPTABLES_MODULES" ]; then
echo -n $"Loading additional $IPTABLES modules: "
ret=0
for mod in $IPTABLES_MODULES; do
echo -n "$mod "
modprobe $mod > /dev/null 2>&1
let ret+=$?;
done
[ $ret -eq 0 ] && success || failure
echo
fi

if [ -s /etc/sysconfig/iptables-allowjp ]
then
/bin/sh /etc/sysconfig/iptables-allowjp
fi

touch $VAR_SUBSYS_IPTABLES
:
 以上のものが出来たら、get-iptable-jp.sh を実行してJPフィルター設定スクリプトを作成した後、service iptables restart。iptables -nL でフィルターが出来ているか確認する。

 アドレスの割り当ては変更されることがあるので、何日かに1回定期的に、get-iptable-jp.sh をしてiptablesをrestartするように、cronを回しておくとよい。
posted by usoinfo at 10:05 | Comment(0) | 開発 | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前: [必須入力]

メールアドレス:

ホームページアドレス:

コメント: [必須入力]