以前、中国や韓国からの不正アクセスがめったやたらとあってログローテートがとんでもないことになっているとか、それにともなってこれらの国々からのアクセスを自動的に排除するようにスクリプトを組むとかやりましたが、あっちこっちで調べたり悩んだりした結果、自分なりに理解した上でなんとか「firewall.sh」というスクリプトを完成させることができました。
もちろんよそ様で公開されている手順を参照しながらやったわけですからオリジナルでもなんでも無いのですが、このスクリプトは大変よくできていて、これはもう自動実行させるしか無い!と思い、実際にこのスクリプトを定期的に走らせてiptablesを一定期間ごとに更新させていました。
その機能の実現に利用したのが、cron。
で、新しくなったサーバでも当然にcronでこのスクリプトを走らせようと思い、同じように/var/spool/cron/rootに設定を記述しました。
# vi /var/spool/cron/root
00 4 * * * /etc/init.d/httpsd restart
00 0 * * * /sbin/ntpdate ntp.nict.jp 1>/dev/null 2>/dev/null
00 2 * * * /foo/bar/firewall.sh
このように時間を指定してあげればOK。
この例ならば、毎日午前2時に組み上げたfirewall.shが実行され(もちろん/foo/bar/firewall.shは755で実行権限が付与されています)、iptablesが自動的に更新されることになります。
そう、なるはずだったのです。ですが。
おかしいな、と思い始めたのはWordPressのダッシュボードで、妙にスパム投稿が増えていたこと。
もちろんakismetがきちんとそれらを弾いてくれているのですが、そもそもこうした投稿ができるはずが無いんです。少なくとも、firewall.shで指定した国コードを持つコンピュータからは。それなのに、それがある。
となると考えられる理由は一つ。iptablesがうまく更新されていない、ということ(あるいは設定されていないということ)。
実際確認してみたところ、その時はなんとiptablesは空白でした。
スクリプト本体に問題が無いことはこのあとすぐに確認しました(手動でfirewall.shを走らせてiptablesが機能することを確認できたので)。
しかし手動でiptablesを設定したその後もなぜかスパム投稿が少しずつですが増えていく傾向が。
こうなってくると、やっぱりcronがfirewall.shを実行できていない可能性が疑われます(IPアドレスの割り当てが一定期間で更新されていくが、その更新情報が反映されていないということだから)。
でも、これまでと同じ設定ですし、特に問題になる部分は無いはず。
そんなおり、偶然仮想端末からサーバをいじっていたら、root宛(/var/spool/mail/root)にメールが来た、とメッセージが表示されました。
なんだろうと思って確認してみると。
# less /var/spool/mail/root
・
・
・
/foo/bar/firewall.sh: line 10: iptables: command not found
/foo/bar/firewall.sh: line 11: iptables: command not found
/foo/bar/firewall.sh: line 16: iptables: command not found
/foo/bar/firewall.sh: line 17: iptables: command not found
/foo/bar/firewall.sh: line 18: iptables: command not found
/foo/bar/firewall.sh: line 23: iptables: command not found
/foo/bar/firewall.sh: line 45: iptables: command not found
/foo/bar/firewall.sh: line 32: iptables: command not found
/foo/bar/firewall.sh: line 32: iptables: command not found
/foo/bar/firewall.sh: line 32: iptables: command not found
/foo/bar/firewall.sh: line 32: iptables: command not found
/foo/bar/firewall.sh: line 32: iptables: command not found
/foo/bar/firewall.sh: line 32: iptables: command not found
/foo/bar/firewall.sh: line 32: iptables: command not found
/foo/bar/firewall.sh: line 32: iptables: command not found
・
・
・
という具合に、なんとfirewall.sh内で使用しているiptablesコマンドが見つかっていなかったのです。
でも、それはおかしい。だってiptablesは普通にコマンドでは実行できるのですから。
最初、firewall.shへのアクセス権を疑って、アクセス設定をしてみたりselinuxの設定を確認したりしたのですが、よく考えればそれならfirewall.shにアクセスできない旨のメッセージがきそうなもんです。
そうではなくてiptablesが見つからない、といってきているということは、つまりiptablesへのパスが見つからないということなのでしょう。
なら手っ取り早く、firewall.sh内のiptablesコマンドを全てフルパス(/sbin/iptables)に変えてしまえばいいのでは。
で、そのようにしてみたのですが、結論から言うと状況は変わらず。相変わらずiptablesが見つからないというメールが届いてしまい、firewall.shは正しく実行されない状況が続きました。
で、いろいろ調べてみたところ、可能性の芽が見つかりました。どうも、cronが実行される時は普通にコマンドラインからコマンドを打つ時と環境変数が異なるらしいのです。
そこで先ほどの/var/spool/cron/rootに環境変数を指定して、cronでfirewall.shを実行させてみました。
# vi /var/spool/cron/root
PATH=/sbin:/bin:/usr/bin
00 4 * * * /etc/init.d/httpsd restart
00 0 * * * /sbin/ntpdate ntp.nict.jp 1>/dev/null 2>/dev/null
00 4 * * * /foo/bar/firewall.sh
はじめはiptablesのある/sbinだけ追加して実行させ、先ほどの「/foo/bar/firewall.sh: line 32: iptables: command not found」が出なくなることを確認。その後、都度見つからないコマンドのパスを追加してあげて、上記の形に落ち着きました。
試しに実行してみたところ、cron経由できちんとiptablesが設定されました。
というわけで、これで一件落着。でも、前のサーバに設定した時には、cronに環境変数なんか設定しなかったんだけどなぁ〜・・・(~_~;;