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


投稿日:2015年1月25日
  • 5
  • 1
  • 10



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

gmo_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のインストールと設定」です。



現在のページを共有する



現在のページに関連する記事


おすすめの記事


いただいたコメントなど

  1. linux入門者 のコメント:

    何度もすいません、先ほど質問させて頂きました者です。詳しく説明いたしますと
    sh iptables.sh を実行すると
    iptables: setting chains to policy accept:fileter ok
    iptables: flushing firewall rules ok
    iptables: unloading modules ok  ←この後反応がなくなりテラタームが落ちます

    • oxy のコメント:

      コメントありがとうございます「linux入門者」さん。
      何度もとありますが、このページヘはこの質問が初めてのようです。

      Tera Termが落ちるとのことですが、iptablesを再起動しているので、それで正常です。
      問題は再びログインできるようになった時点で正しくフィルターのリストが作成されているかです。
      以下のコマンドでフィルターのリストを出力して確認して下さい。

      # iptables -nL -v > filter_list
      # vi filter_list

  2. linux入門者 のコメント:

    # vi filter_list でリストが表示できました。ありがとうございます。
    ついでにもう一つ質問で恐縮ですが、このページの「エラーがないかテスト」にて
    sh iplist_check.sh とすると
    下記のようにエラーがでます
    iplist_check.sh: line 36: mail: command not found
    info@example.comは自分のドメインに書き換えてます。
    何が問題なのでしょう??

    • oxy のコメント:

      command not foundというエラーはそのまま「コマンドがありません」という意味です。
      mailを使えるようにmailxというパッケージをインストールします。
      以下のコマンドでインストールしてください。

      # yum install mailx

  3. linux入門者 のコメント:

    ありがとうございます。メールをインストールしたら大丈夫でした。

    さらにこのページで
    「syslogを止めてからrsyslogを起動」で下記エラーがでます。
    /etc/init.d/syslog stop
    -bash: /etc/init.d/syslog: No such file or directory
    フォルダの中にsyslogは無いのですが、どうしたらよいでしょう??

    • oxy のコメント:

      ログを記録するためにsyslogではなく、rsyslogを使うという趣旨なので、
      元々無いなら停止する必要はありません(というより存在しないので起動しているわけがない)。

      そもそもsyslogが実行された状態でrsyslogを実行すると
      「Shut down sysklogd before you run rsyslog」というエラーが出て起動が失敗するので、
      syslogが既に起動しているかどうかは判断できます。

      ということで、rsyslogだけ実行しておいてください。

  4. Linux初心者 のコメント:

    大変参考にさせて頂いております。

    どうしても上手くいかないところがあり質問させていただきます。

    AWSのEC2 AMIにてサーバー構築をしていまして、
    wget のところでどうしても、wget: unable to resolve host address ‘nami.jp’
    というエラーがでてしまいます。

    よろしければご教授頂ければと思います。よろしくお願いいたします。

    • oxy のコメント:

      nami.jpは生きているようなので、AWS側の問題ですね。
      「/etc/resolv.conf」でネームサーバの設定はしていますか?
      無ければ以下の2行を追加してみてください。

      nameserver 8.8.8.8
      nameserver 8.8.4.4
      
  5. 初心者 のコメント:

    お世話になります。
    こちらのブログを拝見させていただき、iptablesを使わせていただいております。
    今までは日本のみ許可部分を使ってうまくいっていたのですが、
    下記も導入しようと追加して、shすると、
    iptables: Setting chains to policy ACCEPT: filter [ OK ]
    iptables: Flushing firewall rules: [ OK ]
    iptables: Unloading modules: [ OK ]
    この後
    何故かどうしてもネットワークエラーでsshがシャットダウンしてしまいます。

    # 特定の国からのアクセスを拒否する
    # 中国、インド、エジプト、パキスタン、ロシア
    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

    ドロップなので、# 拒否IPリストに記載されたIPを拒否する
    の前に挿入しています。生成時の負荷かと思い、サーバーのメモリを増やしてshしたりも試してみたのですが、同じ結果になってしまいます。
    何か考えられますでしょうか?よろしくお願いいたします

    • oxy のコメント:

      iptableでは、新しいルールを適応する際に全ての接続を遮断します。
      そのため、適応に時間のかかるルールの場合、SSHがタイムアウトして切断します。

      面倒かもしれませんが、再度接続し直してください。

コメントを残す

コメントは認証制のため、すぐには反映されません。

プログラミングに関する質問は「日本語でプログラミングの悩みを解決するQ&Aサイト sukegra」をご利用ください。