OXY NOTES

iptablesの設定とログファイルのローテーション

iptablesとログファイルのローテーション

前回」に続いて「GMO VPSを契約してWordPressを安定動作させるまでのサーバ設定方法」第三弾。

この投稿ではiptablesを設定しますが、このページでは個別の設定については追いません。詳しく知りたい方は「以前の投稿」を参照してください。

今回の解説で利用したVPSはこちら


目次


世界のipリストを作成

世界の最新IPリストを取得して、国単位でのアクセス制御に利用します。
取得に失敗した時に送信するメールアドレス「info@example.com」は環境に合わせて変更しておいてください。

# vi /etc/cron.daily/iplist_check.sh
#!/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# ファイルの取得
wget -q http://nami.jp/ipv4bycc/cidr.txt.gz -P /tmp

# 解凍してリネーム
gunzip -q -f -c /tmp/cidr.txt.gz > /tmp/iplist.new

# /tmp下なので240時間で自動的に削除されますが、念のため削除
rm -f /tmp/cidr.txt.gz

# iplistが存在しているかチェック
if [ -s /tmp/iplist ]; then

	# diffでエラーが出るので実行権限の変更。「-f」を付けて初回にファイルがない場合に対応
	chmod -f 700 iplist.new
	chmod -f 700 iplist
	
	# 差分チェック(正常にファイルが取得できたかチェック)
	ipdiff=$(diff /tmp/iplist /tmp/iplist.new | grep -c "^<")

	# 上記が存在していて、差分の数が1000行以上の場合
	if [ $ipdiff -gt 1000 ]; then
		# メールでIPリストが正常に取得できなかった由を伝える。
		cat <<EOM | mail -s "iplist_check" info@example.com
		iplist false
EOM
		# 正常に取得できなかったリストを破棄
		rm -f /tmp/iplist.new
	else
		# 正常に取得できた場合ファイル名をiplistに変更
		mv /tmp/iplist.new /tmp/iplist

		# メールでIPリストが正常に取得できた由と変更されたIPの数を伝える。
		cat <<EOM | mail -s "iplist_check" info@example.com
		iplist true change IP $ipdiff
EOM
	fi
else
	# 初回実行時は差分をチェックすべきバックアップがないのでそのままファイル名を変更して利用
	mv /tmp/iplist.new /tmp/iplist
fi

これスクリプトで「/tmp/iplist」にリストが書きだされます。
Cronで毎日実行されて上書きされ、tmpディレクトリなので一定期間すぎれば自動でされるため、大量に作成され容量を圧迫することもありません。

エラーがないかテスト

# cd /etc/cron.daily/
# sh iplist_check.sh

/tmp/iplist」が正しく作成されていることを確認。

実行権限を与える

# chmod 755 /etc/cron.daily/iplist_check.sh

iptables.shの設定スクリプトを作成

ブロードキャスト用IP192.168.0.255と、SSHのポート23456を実情に合わせて変更してください。

# su -
# vi iptables.sh
#!/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

/etc/rc.d/init.d/iptables stop

# ポリシーの設定
iptables -P INPUT DROP
iptables -P OUTPUT ACCEPT
iptables -P FORWARD DROP

# IP Spoofing攻撃対策
iptables -A INPUT -i eth0 -s 127.0.0.1/8 -j DROP
iptables -A INPUT -i eth0 -s 10.0.0.0/8 -j DROP
iptables -A INPUT -i eth0 -s 172.16.0.0/12 -j DROP
iptables -A INPUT -i eth0 -s 192.168.0.0/16 -j DROP
iptables -A INPUT -i eth0 -s 192.168.0.0/24 -j DROP

# Ping攻撃対策
iptables -N PING_ATTACK
# Ping攻撃対策 + Ping Flood攻撃対策
iptables -A PING_ATTACK -m length --length :85 -m limit --limit 1/s --limit-burst 4 -j ACCEPT
iptables -A PING_ATTACK -j LOG --log-prefix "[IPTABLES PINGATTACK] : " --log-level=debug
iptables -A PING_ATTACK -j DROP
iptables -A INPUT -p icmp --icmp-type 8 -j PING_ATTACK

# Smurf攻撃対策+不要ログ破棄
iptables -A INPUT -d 255.255.255.255 -j DROP
iptables -A INPUT -d 224.0.0.1 -j DROP
iptables -A INPUT -d 192.168.0.255 -j DROP

# Smurf攻撃対策
sysctl -w net.ipv4.icmp_echo_ignore_broadcasts=1 > /dev/null
sed -i '/# Disable Broadcast Ping/d' /etc/sysctl.conf
sed -i '/net.ipv4.icmp_echo_ignore_broadcasts/d' /etc/sysctl.conf
echo "# Disable Broadcast Ping" >> /etc/sysctl.conf
echo "net.ipv4.icmp_echo_ignore_broadcasts=1" >> /etc/sysctl.conf

# SYN flood攻撃対策でSYN cookiesを有効に設定
sysctl -w net.ipv4.tcp_syncookies=1 > /dev/null
sed -i '/# Enable SYN Cookie/d' /etc/sysctl.conf
sed -i '/net.ipv4.tcp_syncookies/d' /etc/sysctl.conf
echo "# Enable SYN Cookie" >> /etc/sysctl.conf
echo "net.ipv4.tcp_syncookies=1" >> /etc/sysctl.conf

# Auth/IDENT用の113番ポートは拒否
iptables -A INPUT -p tcp --dport 113 -i eth0 -j REJECT --reject-with tcp-reset

# 拒否IPリストに記載されたIPを拒否する
if [ -s /root/deny_ip ]; then
	for ip in `cat /root/deny_ip`
	do
		iptables -I INPUT -s $ip -j DROP
	done
fi

# 特定の国からのアクセスを許可する
if [ -s /tmp/iplist ]; then
	iptables -N ACCEPT_JP_FILTER
	sed -n 's/^JP\t//p' /tmp/iplist | while read address;
	do
		iptables -A ACCEPT_JP_FILTER -s $address -j ACCEPT
	done
fi

# 特定の国からのアクセスを拒否する
# 中国、インド、エジプト、パキスタン、ロシア
if [ -s /tmp/iplist ]; then
	iptables -N DROP_COUNTRY_FILTER
	sed -n 's/^\(CN\|IN\|EG\|PK\|RU\)\t//p' /tmp/iplist | while read address;
	do
		iptables -A DROP_COUNTRY_FILTER -s $address -j DROP
	done
	iptables -A INPUT -j DROP_COUNTRY_FILTER
fi

# ステートフル・パケットインスペクションで正しいTCPと既に許可された接続を許可
iptables -A INPUT -p tcp ! --tcp-flags SYN,RST,ACK SYN -m state --state NEW -j DROP
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

## ここから個別のサービスで利用するポートを開放する ##

# lo(ループバックインターフェース)の許可
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

# SSH用のポートを日本からのみ許可
iptables -A INPUT -p tcp -m state --state NEW --dport 23456 -m hashlimit --hashlimit-burst 10 --hashlimit 1/h --hashlimit-mode srcip --hashlimit-htable-expire 3600000 --hashlimit-name ssh-limit -j ACCEPT_JP_FILTER

# http用のポート許可
iptables -A INPUT -p tcp -m state --state NEW --dport 80 -j ACCEPT

# DNS用ポートの許可。DNS Ampやカミンスキー攻撃対策に適宜ログを取る
iptables -A INPUT -p udp -m state --state NEW --dport 53 -i eth0 -j DNSAMP
iptables -N DNSAMP
iptables -A DNSAMP -m recent --name dnsamp --set
iptables -A DNSAMP -m recent --name dnsamp --rcheck --seconds 60 --hitcount 10 -j LOG --log-prefix "[IPTABLES DNSAMP] : " --log-level=debug
iptables -A DNSAMP -m recent --name dnsamp --rcheck --seconds 60 --hitcount 10 -j DROP
iptables -A DNSAMP -j ACCEPT

iptables -A INPUT -p tcp -m state --state NEW --dport 53 -j ACCEPT

# smtps用にポートを許可
iptables -A INPUT -p tcp -m state --state NEW --dport 465 -j ACCEPT

# imaps(pop3 protocol over TLS/SSL)用にポートを許可
iptables -A INPUT -p tcp -m state --state NEW --dport 993 -j ACCEPT

# pop3s(imap4 protocol over TLS/SSL)用にポートを許可
iptables -A INPUT -p tcp -m state --state NEW --dport 995 -j ACCEPT

# smtp tcp用にポートを許可
iptables -A INPUT -p tcp -m state --state NEW --dport 25 -j ACCEPT

# サブミッションポート用にポートを許可
iptables -A INPUT -p tcp -m state --state NEW --dport 587 -j ACCEPT

# https(http protocol over TLS/SSL) tcp用にポートを許可
iptables -A INPUT -p tcp -m state --state NEW --dport 443 -j ACCEPT

# NTP用にポートを許可
iptables -A INPUT -p udp -m state --state NEW --dport 123 -j ACCEPT

# 上記の条件に当てはまらない通信を記録して破棄
iptables -A INPUT -m limit --limit 1/s -j LOG --log-prefix "[IPTABLES DROP INPUT] : " --log-level=debug
iptables -A INPUT -j DROP

# 設定を保存してiptablesを起動
/etc/rc.d/init.d/iptables save
/etc/rc.d/init.d/iptables stop
/etc/rc.d/init.d/iptables start

テストで実行する

拒否リストが膨大になった場合は5分くらいかかることもある。必要なければ拒否リストは少なめにしてください。

# sh iptables.sh

iptablesの自動起動を有効にする

# chkconfig iptables --list
# chkconfig iptables on

作成したスクリプトの移動

どうせ「/etc/cron.daily/iplist_check.sh」で毎日IPリストを取得するので、このファイル内でリストを取得した後に実行することにします。
(更新を毎日する必要が無いという場合などはCronで個別に設定してください。)

/usr/script」ディレクトリを作成してコピーします。

# mkdir /usr/script/
# cp iptables.sh /usr/script/iptables.sh

続いて「/etc/cron.daily/iplist_check.sh」の「33行目」と「42行目」のあとに以下を追加。

	# 新しく取得したリストでiptablesの設定スクリプトを実行
	sh /usr/script/iptables.sh > /dev/null

rsyslogの設定とログのローテーション

iptables用のログファイルをログローテーションする。

# vi /etc/rsyslog.conf

*.info;mail.none;authpriv.none;cron.none」の直後に追加。

# iptables用の設定
:msg, contains, "IPTABLES PINGATTACK"	-/var/log/iptables-ping-attack.log
:msg, contains, "IPTABLES DNSAMP"	-/var/log/iptables-dnsamp.log
:msg, contains, "IPTABLES DROP INPUT"	-/var/log/iptables-input-drop.log

空ファイルの作成

# touch /var/log/iptables-ping-attack.log
# touch /var/log/iptables-dnsamp.log
# touch /var/log/iptables-input-drop.log

ローテーションを設定する

一緒くたにローテーションを設定します。

# vi /etc/logrotate.d/iptables
/var/log/iptables-dnsamp.log /var/log/iptables-input-drop.log /var/log/iptables-ping-attack.log {
	weekly
	rotate 4
	create
	postrotate
		/etc/init.d/iptables reload > /dev/null 2> /dev/null || true
	endscript
}

syslogを止めてからrsyslogを起動

# /etc/init.d/syslog stop
# service rsyslog start

rsyslog自動起動の設定

# chkconfig rsyslog on
# chkconfig --list rsyslog

syslogの自動起動の停止

# chkconfig syslog off
# chkconfig --list syslog

今回の解説で利用したVPSはこちら
GMOクラウドのVPS

以上でiptablesと、それに関するログファイルに関する設定が完了しました。
出力したログファイルを使った細かなアクセス制御などを行いたい場合は「以前の投稿」を参照してください。

次は「Nginxとリバースプロキシ、php-fpmとOPcacheのインストールと設定」です。