前回は、ホストへの通信を制限する方針を設計し、iptables/ip6tables を利用することに決めた。今回は、iptables/ip6tables の設定を行う。
対象
内部用サーバー
外部用サーバー
OS
CentOS release 5.10
iptables の設定
前回説明したように、iptables は起動スクリプト「/etc/init.d/iptables」によって起動時に有効になる。起動スクリプトは「/etc/sysconfig/iptables」ファイルを参照するので、ファイルを編集することにする。サンプルファイルは、以下の通りだ。
*filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] :RH-Firewall-1-INPUT - [0:0] -A INPUT -j RH-Firewall-1-INPUT -A FORWARD -j RH-Firewall-1-INPUT -A RH-Firewall-1-INPUT -i lo -j ACCEPT -A RH-Firewall-1-INPUT -p icmp --icmp-type any -j ACCEPT -A RH-Firewall-1-INPUT -p 50 -j ACCEPT -A RH-Firewall-1-INPUT -p 51 -j ACCEPT -A RH-Firewall-1-INPUT -p udp --dport 5353 -d 224.0.0.251 -j ACCEPT -A RH-Firewall-1-INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport [port] -j ACCEPT -A RH-Firewall-1-INPUT -j REJECT --reject-with icmp-host-prohibited COMMIT
設定内容を、順に説明していく。
チェインの設定
以下の設定は、INPUT、FORWARD、OUPUT の各チェインのデフォルトの動作を指定している。セキュリティの考え方では、デフォルトは拒否、必要なもののみ許可するべきだが、デフォルトの設定は許可(ACCEPT)になっている。INPUT と FORWARD のチェインは、最後にすべてを拒否するというルールを追加するので、考え方はデフォルト拒否と同じになる。
:INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0]
以下の3行は、「RH-Firewall-1-INPUT」という独自のチェインを作成し、INPUT と FORWARD は独自のチェインに飛ばすように設定している。「RH-Firewall-1-INPUT」というチェインで設定した内容は、INPUT と FORWARD の両方に適用されるようになる。一般的に、ホストに入ってくるパケット(INPUT)と通過するパケット(FORWARD)は同じルールを記述することになるので、独自のチェインを作成して記述を簡略化している。
:RH-Firewall-1-INPUT - [0:0] -A INPUT -j RH-Firewall-1-INPUT -A FORWARD -j RH-Firewall-1-INPUT
ルールの記述
ルールの記述に先だって、オプションを少し解説する。すべてのオプションを知りたい場合は、日本語のman ページを参照するとよいだろう。
「-i」オプションは、インターフェースの指定だ。iptables は、INPUT、FORWARD、PREROUTING のチェインでインターフェースを指定できるようになっている。一般的な環境では、もっぱら自分自身を表すループバックインターフェースの通信を許可するときしか使わないが、複数のインターフェースを持つホストでは利用することもある。なお、OUTPUT チェインでは利用できない。
「-j」オプションは、指定したターゲットに飛ばす設定だ。ACCEPT(許可)、DROP(拒否)、QUEUE(ユーザースペースへ)、RETURN(呼び出し元チェインの次のルールから再開する)のいずれかを指定する。
「-p」オプションはプロトコルの指定、「-s」「-d」は送信元・宛先アドレスの指定、「–sport」「–dport」はプロトコルが TCP/UDP の場合の送信元・宛先ポートの指定になる。
なお、ルールは記述された順に評価される。
最初は、ループバックインターフェースの通信を許可するルールだ。ループバックインターフェースでは外部との通信を行わないので、すべて許可にしている。
-A RH-Firewall-1-INPUT -i lo -j ACCEPT
次は、ICMP のパケットをすべて許可するルールだ。一部の ICMP を制限する、たとえば ping に応答しないように ECHO/REPLY を制限することもできるが、最近はポートスキャンを行うのが一般的なので、セキュアにはならない。ICMP は TCP/IP の通信において重要な情報を伝達する役割を担っているので、すべて許可にしている。
-A RH-Firewall-1-INPUT -p icmp --icmp-type any -j ACCEPT
次の3つのルールは、順に「ESP」「AH」(ともに IPSec で利用)と、「マルチキャスト DNS」を許可している。
-A RH-Firewall-1-INPUT -p 50 -j ACCEPT -A RH-Firewall-1-INPUT -p 51 -j ACCEPT -A RH-Firewall-1-INPUT -p udp --dport 5353 -d 224.0.0.251 -j ACCEPT
次のルールは、パケットが特定の状態の場合に通信を許可する設定だ。ここでは、ESTABLISHED(双方向のトラフィックが検出されている状態)、RELATED(別のコネクションと関連する状態)を許可している。このルールはポート番号を指定していないが、新規に送られてきたパケットを許可していないので問題ない。
-A RH-Firewall-1-INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
次のルールは、SSH の通信を許可するためのものだ([port]は sshd の待ち受けポート番号)。パケットの状態が NEW(コネクションの要求を行うパケット)だけ許可している。このルールだけでは SSH の通信は行えないが、前のルールによりコネクションが張られた後の通信が許可されているので通信できる。
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport [port] -j ACCEPT
最後のルールは、ここまでのルールにマッチしなかったパケットを破棄するルールだ。「icmp-host-prohibited」は調査してもなかなかよい情報が見つからないが、ICMP の到達不能メッセージで CODE10(Destination host administratively prohibited – 宛先ホスト設定によりアクセス拒否)を表しているようだ。
-A RH-Firewall-1-INPUT -j REJECT --reject-with icmp-host-prohibited
適用
上記の内容をコピーしてファイルに書き込み、iptables をリスタートする。
[root@server ~]# su - [root@server ~]# vi /etc/sysconfig/iptables [root@server ~]# /etc/init.d/iptables restart
エラーが出なければ、iptables の設定は完了だ。
OUTPUT チェインの定義
今回ホストから出て行くパケットの制御は行わない。データベース専用サーバーなど、外部との通信が不要な場合は定義することもあるが、今回のサーバーは、Web アプリケーションを動作させるため、外部へのさまざまな通信が発生する可能性がある。サーバーからの通信が限定できる場合は OUTPUT チェインを定義してもよいかもしれないが、パッケージのアップデートを行うサーバーに接続できないなど、問題が発生することもある。
ip6tables の設定
借りているさくらインターネットの VPS の IPv6の設定を調べたところ、リンクローカルアドレスが割り当てられていた。残念ながら外部からはアクセスできないが、念のため設定しておく。
前回説明したように、iptables は起動スクリプト「/etc/init.d/ip6tables」によって起動時に有効になる。起動スクリプトは「/etc/sysconfig/ip6tables」ファイルを参照するので、ファイルを編集することにする。サンプルファイルは、以下の通りだ。
*filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] :RH-Firewall-1-INPUT - [0:0] -A INPUT -j RH-Firewall-1-INPUT -A FORWARD -j RH-Firewall-1-INPUT -A RH-Firewall-1-INPUT -i lo -j ACCEPT -A RH-Firewall-1-INPUT -p icmpv6 -j ACCEPT -A RH-Firewall-1-INPUT -p 50 -j ACCEPT -A RH-Firewall-1-INPUT -p 51 -j ACCEPT -A RH-Firewall-1-INPUT -p udp --dport 5353 -d ff02::fb -j ACCEPT -A RH-Firewall-1-INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport [port] -j ACCEPT -A RH-Firewall-1-INPUT -j REJECT --reject-with icmp6-adm-prohibited COMMIT
IPv4と異なるのは ICMP と IP アドレスに関わる以下の3行だけだ。IP のバージョンが異なるだけなので、IP とは異なる層のプロトコルである TCP や UDP の定義などは特に変更の必要がない。
-A RH-Firewall-1-INPUT -p icmpv6 -j ACCEPT -A RH-Firewall-1-INPUT -p udp --dport 5353 -d ff02::fb -j ACCEPT -A RH-Firewall-1-INPUT -j REJECT --reject-with icmp6-adm-prohibited
上記の内容をコピーしてファイルに書き込み、ip6tables をリスタートする。
[root@server ~]# su - [root@server ~]# vi /etc/sysconfig/ip6tables [root@server ~]# /etc/init.d/ip6tables restart
エラーが出なければ、ip6tables の設定も完了だ。
ピンバック: サーバーへの DoS 攻撃を軽減する | UB Lab.