(注意) stateに対応したという情報が流れた後に一時的に「stateの文法が通るようになったが実際は動作しない」という時期があった。5/12日現在においては、一旦rebootすることで正常にstateが動作するようになるので、この記事の内容を試す前に一旦rebootすることをおすすめする。
これからやること
まず、簡単にstateを利用したルールの作り方を書くと、
- ESTABLISHED, RELATEDというstateな通信を許可するルールを設定
- その後ろにサービス提供したいport宛のNEWというstateな通信を許可するルールを設定
- 最後にすべてDROPする
失敗すると怖いので...
さて、ServersMan@VPSはroot権限はあるが、リモート環境(ssh等でアクセスする必要がある)であり、しかもコンソールアクセスが提供されているわけでもないので、iptablesの設定に失敗してsshでアクセスできなくなったりすると、サポートにお願いしてiptables設定を解除してもらう必要がある。こうなってしまうと少なくとも1日は無駄にしてしまうので、可能な限りiptables設定の失敗は避けたい。
そこで、一旦安全なルールを設定し、stateによる動作を確認した後に厳密なルールを投入するという方法を解説する。(完璧じゃぁないが、だいぶ失敗は防げると思う)
ポリシー決定
提供したいサービスをもとに許可ポリシーを決定する。例として、Webサーバとメールサーバをたてて運用する場合を考えると、以下のようなポリシーになる。
- HTTP, HTTPS: 不特定多数の人にWebサーバを公開するつもりなので、すべてのIPアドレスからの接続を許可する。
- SMTP: 自分のドメインのメールを受け取るメールサーバにするつもりなので、すべてのIPアドレスからの接続を許可する。
- SSH: 管理用に必須なので許可する。自宅、会社、出先などいろいろなところからアクセスする必要があるので、すべてのIPアドレスからの接続を許可する
- 前回の解説にも書いたが、ローカル通信は当然許可する。また、icmpも許可。ident(auth)はtcp resetで拒否、その他のすべての通信はDROPで拒否する。
ポリシーから動作確認用ルールを作成
上記のポリシーからiptablesのルールを作成すると以下のようになる。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# これは確認用のルール(結局全部の通信を許可するルール)なので注意すること | |
*filter | |
:INPUT ACCEPT [0:0] | |
:FORWARD ACCEPT [0:0] | |
:OUTPUT ACCEPT [0:0] | |
-N MYCHAIN | |
-A MYCHAIN -m state --state ESTABLISHED,RELATED -j ACCEPT | |
-A MYCHAIN -p icmp -j ACCEPT | |
-A MYCHAIN -s 127.0.0.0/8 -d 127.0.0.0/8 -j ACCEPT | |
-A MYCHAIN -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT | |
-A MYCHAIN -m state --state NEW -m tcp -p tcp --dport 25 -j ACCEPT | |
-A MYCHAIN -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT | |
-A MYCHAIN -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT | |
-A MYCHAIN -m tcp -p tcp --dport 113 -j REJECT --reject-with tcp-reset | |
-A MYCHAIN -j ACCEPT | |
-A INPUT -j MYCHAIN | |
COMMIT |
これは /etc/sysconfig/iptables にそのまま使える形式(iptables-save(8)の出力)で書いてある。
1行目〜4行目はおまじない。
5行目はMYCHAINという名前のチェイン(ルールの集合)を作成している。こうしておくことで作成したルールの再利用性が高まる。(あんまり再利用する機会もないけど)
6行目は前述の「ESTABLISHED, RELATEDというstateな通信を許可するルールを設定」だ。
7行目はicmpの許可
8行目はローカル通信の許可
9〜12行目は各種提供サービスの許可。ここで --state NEW としているが、これは接続開始要求のパケット(SYNパケット)のみ許可するという意味になる。--state NEW をつけない場合は、SYNフラグがたっていないパケット(ESTABLISHEDを偽装したパケット等)を受け付けることになるので --state NEW をつけた方がよい。
13行目はident宛の通信を拒否している。ただし、DROPのように無視するのではなく、tcp reset を送信して拒否することを明示的に相手に知らせている。詳しくは前回の記事参照。
14行目は本来DROPとするはずだが、動作確認用にACCEPTにしている。こうしておけば仮に上のルールが間違っていたとしても完全にロックアウトされることはない。動作確認の方法については後述。
15行目はINPUTチェインですべてのパケットをMYCHAINチェインに飛ばしている。
16行目はおまじない。
動作確認
上記の設定をファイルに落としたら、iptablesのサービスが再起動時に自動的にあがらないようにしたうえで、iptables-restore(8)を使ってルールを反映させる。
iptables.txt というファイルにセーブしているとすると、以下のようなコマンドになる。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
root@bangasa# chkconfig iptables off | |
root@bangasa# chkconfig iptables --list | |
iptables 0:off 1:off 2:off 3:off 4:off 5:off 6:off | |
root@bangasa# cat iptables.txt | iptables-restore |
無事通信が継続できたら反映されたルールを確認する。
もしロックアウトされてしまった場合はServersManのアカウントのページからrebootさせればよい。iptablesサービスをoffにしておけば、ルールが勝手にセーブされたり起動時に間違ったルールが自動的に適用されることを防げるはずだ。ルールの確認は /etc/init.d/iptables status でもいいが、ここでは iptables -L -nv を使う。このコマンドを使うことで、どのルールにどれだけのパケットがマッチしたかを確認することができるからだ。
なお、VPSサーバからDNSを引けない場合、SSHでアクセスしたときにログインするまでに時間がかかることがあるので、SSHでアクセスして反応がなくてもしばらく待ってみた方が良い。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
root@bangasa# iptables -L -nv | |
Chain INPUT (policy ACCEPT 0 packets, 0 bytes) | |
pkts bytes target prot opt in out source destination | |
211 24430 MYCHAIN all -- * * 0.0.0.0/0 0.0.0.0/0 | |
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) | |
pkts bytes target prot opt in out source destination | |
Chain OUTPUT (policy ACCEPT 194 packets, 30144 bytes) | |
pkts bytes target prot opt in out source destination | |
Chain MYCHAIN (1 references) | |
pkts bytes target prot opt in out source destination | |
207 24214 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED | |
0 0 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 | |
0 0 ACCEPT all -- * * 127.0.0.0/8 127.0.0.0/8 | |
4 216 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22 | |
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:25 | |
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:80 | |
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:443 | |
0 0 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:113 reject-with tcp-reset | |
0 0 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 |
ここで、ESTABLISHED のルールと SSHのルール(dpt:22)の行の一番左のカラム(pkts)の数値をみると、カウントアップされていることがわかる。この数値はそのルールにマッチしたパケットの数を示している。もし許可したルールに該当するはずの通信を行っても、ここがカウントアップされていない場合は、そのルールにマッチしていない(=何かが間違っている)ということなので、ルールを見直す。
例えばSSHを許可しているが、新たにSSHで接続しても最後の全ACCEPTのカウントばかりあがっていくようならば、最後のACCEPTをこのあとDROPに変更したときに通信できなくなってしまうはずだ。
意図した通りに動くようになるまで、ルール作成と動作確認を繰り返す。
動作確認用ルールから厳密なルールを作成
これは簡単。最後のACCEPTをDROPに変更するだけだ。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
*filter | |
:INPUT ACCEPT [0:0] | |
:FORWARD ACCEPT [0:0] | |
:OUTPUT ACCEPT [0:0] | |
-N MYCHAIN | |
-A MYCHAIN -m state --state ESTABLISHED,RELATED -j ACCEPT | |
-A MYCHAIN -p icmp -j ACCEPT | |
-A MYCHAIN -s 127.0.0.0/8 -d 127.0.0.0/8 -j ACCEPT | |
-A MYCHAIN -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT | |
-A MYCHAIN -m state --state NEW -m tcp -p tcp --dport 25 -j ACCEPT | |
-A MYCHAIN -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT | |
-A MYCHAIN -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT | |
-A MYCHAIN -m tcp -p tcp --dport 113 -j REJECT --reject-with tcp-reset | |
-A MYCHAIN -j DROP | |
-A INPUT -j MYCHAIN | |
COMMIT |
ルール投入
前述の用に iptables-restore でルールを投入し、問題なければ内容を /etc/sysconfig/iptables に保存し、iptablesサービスを有効化する。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
root@bangasa# cp iptables.txt /etc/sysconfig/iptables | |
root@bangasa# chkconfig iptables on | |
root@bangasa# /etc/init.d/iptables start | |
Flushing firewall rules: [ OK ] | |
Setting chains to policy ACCEPT: mangle filter [ OK ] | |
Unloading iptables modules: [ OK ] | |
Applying iptables firewall rules: [ OK ] |
まとめ
今回の要点は以下の通り。
- stateをつかったルールは、「ESTABLISHED, RELATED許可」→「提供サービスのNEWを許可」→「ほかはDROP」が基本形
- iptables -L -nv で意図したルールにマッチしているか確認してから最後のDROPを有効化する
通りすがりです。
返信削除SM@VPSでstateが使えるようになったってマジですか!
サービスイン初期の時点でそれに気づいて運営へ問い合わせたんですが、「機能提供してません」の一点張りで愕然としてました。
再起動すれば使えるようになっているとのことなので、試してみます。
マジです。要望が多かったので対応したみたいです。
返信削除http://twitter.com/serversman_vps/status/12294223127
http://twitter.com/serversman_vps/status/12554243240
http://dream.jp/vps/faq_08.html
ぜひ試してみてください。この記事が参考になれば幸いです。
ありがとうございました。このまま参考にしました。本当は,そのような(私のような)レベルの者がServersMan@VPSに手を出すべきではないのかもしれませんが,単なる興味本位で手を出しているのではなく,やりたいことがあるのです。人はそれぞれ専門分野が違うので,門外漢の敷居を下げてくれる情報提供に感謝します。
返信削除コメントどうもです。
返信削除この記事があなたのやりたいことの役に立ったのであれば私も嬉しく思います。