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と、それに関するログファイルに関する設定が完了しました。
出力したログファイルを使った細かなアクセス制御などを行いたい場合は「以前の投稿」を参照してください。
何度もすいません、先ほど質問させて頂きました者です。詳しく説明いたしますと
sh iptables.sh を実行すると
iptables: setting chains to policy accept:fileter ok
iptables: flushing firewall rules ok
iptables: unloading modules ok ←この後反応がなくなりテラタームが落ちます
コメントありがとうございます「linux入門者」さん。
何度もとありますが、このページヘはこの質問が初めてのようです。
Tera Termが落ちるとのことですが、iptablesを再起動しているので、それで正常です。
問題は再びログインできるようになった時点で正しくフィルターのリストが作成されているかです。
以下のコマンドでフィルターのリストを出力して確認して下さい。
# iptables -nL -v > filter_list
# vi filter_list
# vi filter_list でリストが表示できました。ありがとうございます。
ついでにもう一つ質問で恐縮ですが、このページの「エラーがないかテスト」にて
sh iplist_check.sh とすると
下記のようにエラーがでます
iplist_check.sh: line 36: mail: command not found
info@example.comは自分のドメインに書き換えてます。
何が問題なのでしょう??
command not foundというエラーはそのまま「コマンドがありません」という意味です。
mailを使えるようにmailxというパッケージをインストールします。
以下のコマンドでインストールしてください。
# yum install mailx
ありがとうございます。メールをインストールしたら大丈夫でした。
さらにこのページで
「syslogを止めてからrsyslogを起動」で下記エラーがでます。
/etc/init.d/syslog stop
-bash: /etc/init.d/syslog: No such file or directory
フォルダの中にsyslogは無いのですが、どうしたらよいでしょう??
ログを記録するためにsyslogではなく、rsyslogを使うという趣旨なので、
元々無いなら停止する必要はありません(というより存在しないので起動しているわけがない)。
そもそもsyslogが実行された状態でrsyslogを実行すると
「Shut down sysklogd before you run rsyslog」というエラーが出て起動が失敗するので、
syslogが既に起動しているかどうかは判断できます。
ということで、rsyslogだけ実行しておいてください。
大変参考にさせて頂いております。
どうしても上手くいかないところがあり質問させていただきます。
AWSのEC2 AMIにてサーバー構築をしていまして、
wget のところでどうしても、wget: unable to resolve host address ‘nami.jp’
というエラーがでてしまいます。
よろしければご教授頂ければと思います。よろしくお願いいたします。
nami.jpは生きているようなので、AWS側の問題ですね。
「/etc/resolv.conf」でネームサーバの設定はしていますか?
無ければ以下の2行を追加してみてください。
お世話になります。
こちらのブログを拝見させていただき、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したりも試してみたのですが、同じ結果になってしまいます。
何か考えられますでしょうか?よろしくお願いいたします
iptableでは、新しいルールを適応する際に全ての接続を遮断します。
そのため、適応に時間のかかるルールの場合、SSHがタイムアウトして切断します。
面倒かもしれませんが、再度接続し直してください。