「iptables」で「ファイアウォール」を設定します。
「iptables」は、Linuxに実装されたパケットフィルタリングおよびネットワークアドレス変換 (NAT) 機能であるNetfilterを操作するコマンドです。
ここではLinuxマシンの基本的なファイアウォールを設定してみます。
基本(まず覚えること)
iptablesの基本は「テーブル」「チェーン」「ルール」「ポリシー」の4個です。
テーブル(Tables)
iptablesは4つの主要なテーブルをサポートしており、それぞれ異なる種類のルールを管理します。
テーブル名 | 用途 | 備考 |
---|---|---|
filter | パケットのフィルタリングとアクセス制御に使用します。 | 省略時のデフォルト |
nat | ネットワークアドレス変換(NAT)ルールを管理します。 | |
mangle | パケットのヘッダ情報を変更するためのルールを管理します。 | |
raw | 特殊な目的のルールを管理します。 |
ファイアウォールで使うのが「パケットフィルタリング」を操作する「filter」テーブルです。
チェイン(Chains)
テーブルはチェインで構成されています。
「filter」テーブル内には以下のチェインが含まれます。
チェインは順番に並べられたルールのリストです。
チェーン名 | 適用 |
---|---|
INPUT | パケットがシステムに到達する前に適用されるルール。 |
OUTPUT | システムから出ていくパケットに適用されるルール。 |
FORWARD | システムを通過する(ルーティングされる)パケットに適用されるルール。 |
ルール(Rules)
ルールは特定の条件に一致するパケットに対するアクションを指定します。以下は一般的なルールの要素です。
マッチ条件 | ルールが一致する条件を定義します。 例えば、特定のポート、IPアドレス、プロトコルなどが含まれます。 |
アクション | ルールに一致するパケットに対するアクションを指定します。 |
「アクション」には以下のものがあります。
アクション名 | アクション |
---|---|
ACCEPT | パケットを許可します。 |
DROP | パケットを破棄します。 |
REJECT | パケットを破棄し、送信元に拒否応答を返します。 |
LOG | パケットに関するログを記録します。 |
「iptables」でチェインの中にルールを並べていきます。
パケットは上から順番にルールを通り抜けて、条件にマッチするとアクションにジャンプします。
ポリシー(Policy)
チェインにはポリシーが関連付けられており、ルールに一致しないパケットに対するデフォルトのアクションを定義します。一般的なポリシーは「ACCEPT」または「DROP」です。
ポリシー | 挙動 |
---|---|
ACCEPT | チェイン内のルールに「一致しない」パケットを「許可」 |
DROP | チェイン内のルールに「一致しない」パケットを「拒否」 |
インターフェイスとデータが流れる方向
ネットワークインターフェースは、コンピュータやネットワークデバイスが外部のネットワークと通信するための物理的または仮想的な接続点です。
イーサネットポート、Wi-Fiアダプタ、仮想ネットワークインターフェースなどがあります。
「eth0」「eth1」のような物理的なインターフェース以外に「ループバック インターフェース(lo)」などもあります。
ファイアウォールのフィルター設定では、このネットワークインターフェースを通じてデータが流れる「方向」が重要になります。
データの流れる方向は「-i」「-o」で表します。
コマンド | 意味 |
---|---|
-i | 「システム」に「入ってくる(input)」トラフィック |
-o | 「システム」から「出ていく(output)」トラフィック |
「lo」インターフェイスにおいては「-o」でシステムから出ていくデータがそのまま「-i」でシステムに入ってくるデータということになります。
基本構文
ルールを定義する基本的な構文は以下の通りです。
「INPUT」「OUTPUT」「FORWARD」などのチェーンに、特定のポート、IPアドレス、プロトコルなどの条件にマッチするアクションを定義します。
iptables -t テーブル名 -A チェーン名 [条件] -j アクション
ルールを追加(-A)
インターフェイス「eth0」に到達するパケットを全て許可するルールの追加は次のようになります。
iptables -t filter -A INPUT -i eth0 -j ACCEPT
テーブルを省略したときは「filter」が適用されるので、以下は同じ意味になります。
iptables -A INPUT -i eth0 -j ACCEPT
ルールの削除(-D)
ルールを削除するのは「-D」オプションです。
iptables -D INPUT -i eth0 -j ACCEPT
全てのルールを削除する(-F)
設定されている全てのルールを削除するには次のようにします。
ただしポリシーは変更されません。
ポリシーが「DROP」のシステムでこのコマンドを実行するとすべてのネットワーク接続が遮断されます。
iptables -F
ポリシーを変更する
Debianのポリシーは初期状態で「INPUT」「OUTPUT」「FORWARD」全てで「ACCEPT」です。
Debianではルールにマッチしないパケットは許可されます。
例えば「INPUT」のポリシーを「DROP」にするには以下のようにします。
「INPUT」テーブルに許可ルールがない場合「ssh」接続もDROPされるので注意してください。
iptables -P INPUT DROP
ポリシーの設定は「iptables -F」で初期化されません。
ポリシーが「ACCEPT」か「DROP」かによって設定するルールを考える必要があります。
順序
チェインごとに設定した順序でルールがパケットに適用されていきます。
条件がマッチするとアクションが適用されて終了します。
マッチするものが無ければ「ポリシー」が適用されます。
具体的な設定例
具体的な設定を見ていきましょう。
送信元192.168.1.0/24からeth0宛のssh接続だけを許可
ポリシーが「ACCEPT」か「DROP」かによって設定が変わります。
「ACCEPT」ポリシーで設定する
次のようになります。
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -A INPUT -i eth0 -m state --state NEW -p tcp --dport 22 -s 192.168.1.0/24 -j ACCEPT
iptables -A INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -i eth0 -j DROP
詳しく見ていきます。
まずポリシーを設定します。Debianのように初期状態が「ACCEPT」なら必要ありません。
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
オプション | 由来 | 挙動 |
---|---|---|
-P | Policy | ポリシーを設定します。 |
次にプロトコルが「tcp」、宛先ポートが「22」、送信元が「192.168.1.0/24」の「新しい接続の要求」が「eth0」インターフェースに到達するのを許可します。
iptables -A INPUT -i eth0 -m state --state NEW -p tcp --dport 22 -s 192.168.1.0/24 -j ACCEPT
オプション | 由来 | 挙動 |
---|---|---|
-A | Add | ルールを追加する。 |
-i | input Interface | 受信インターフェースを指定する。 |
-m | module | アクションを拡張するために使用するモジュールを指定する。 |
-p | protocol | プロトコル(例: tcp、udp、icmpなど)を指定する。 |
–dport | destination port | 宛先ポートを指定する。 |
-s | source | 送信元を指定する。 |
-j | jump | アクション(例: ACCEPT、DROPなど)を指定する。 |
「-m state」は状態追跡(state tracking)を提供し、TCPやUDPのセッション状態に基づいてパケットをフィルタリングできるようにします。
つまり「-m state –state NEW」は状態を監視して通信の始まりを検知します。
続いて確立済みのセッションを許可します。
iptables -A INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
「RELATED」は既存の接続に関連するトラフィックを示します。
たとえば、FTPデータ通信において、制御コネクション(FTP制御接続)を介して確立された接続に関連するデータトラフィック(FTPデータ接続)を指します。
他にもDNSクエリに対するDNS応答や、ICMPエコーリクエストに対するエコーリプライなどが関連トラフィックとして扱われます。
最後に「eth0」インターフェースに到達するすべてのパケットを拒否します。
iptables -A INPUT -i eth0 -j DROP
システムから出ていくパケットは「ACCEPT」ポリシーによって全て許可されます。
ルールは設定の順に適用されるので順番が変わると意図した動作になりません。
「ACCEPT」ポリシーは簡易的に接続を制限する場合に便利ですが、本格的なセキュリティーを確保するなら「DROP」ポリシーを採用するべきです。
「DROP」ポリシーで設定する
特定のインターフェースを指定せずに、すべてのインターフェースに対して設定してみます。
ルールにインターフェイスを指定しなければ全てのインターフェースに設定されます。
インターフェース無指定であればループバック インターフェース「lo」にもルールが適用されますので注意してください。
ルールは以下のようになります。
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
iptables -A INPUT -m state --state NEW -p tcp --dport 22 -s 192.168.1.0/24 -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
詳しく見ていきます。
まずポリシーを設定します。Debianのように初期状態が「ACCEPT」なら設定します。
ルールで許可されていない通信はすべて遮断されます。
sshなどでリモートから設定する場合は通信が遮断されるので注意が必要です。
iptables -P INPUT DROP
iptables -P OUTPUT DROP
「DROP」ポリシーでは「ループバック インターフェース(lo)」と「システム」間の通信も遮断される可能性があります。
まずプロセス間通信や、ローカルホスト上で実行されているサービスから「lo」経由でシステムに入ってくるパケットを許可します。
iptables -A INPUT -i lo -j ACCEPT
オプション | 由来 | 挙動 |
---|---|---|
-i | input Interface | 受信インターフェースを指定する。 |
システムから「lo」経由でプロセス間通信や、ローカルホスト上で実行されているサービスに出ていくパケットを許可します。
iptables -A OUTPUT -o lo -j ACCEPT
オプション | 由来 | 挙動 |
---|---|---|
-o | output Interface | 送信インターフェースを指定する。 |
プロトコルが「tcp」、宛先ポートが「22」、送信元が「192.168.1.0/24」の「新しい接続の要求」を許可します。
iptables -A INPUT -m state --state NEW -p tcp --dport 22 -s 192.168.1.0/24 -j ACCEPT
続いて、確立済みセッションを「INPUT」「OUTPUT」ともに許可します。
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
これ以降は「192.168.1.0/24」からの「ssh」接続以外はすべて遮断されます。
システムから出ていくDNSやNTPの問い合わせもすべてできなくなります。
尋常でなく反応が悪くなる場合があるのはこのためです。
最低限必要な外部問い合わせを許可(DROPポリシー)
「ACCEPT」ポリシーでは「OUTPUT」は全て許可されているのでDNSやNTPに支障はありません。
「DROP」ポリシーでは「DNS」「NTP」「APT」問い合わせで不具合が発生します。
「DROP」ポリシーでは必要な通信はすべてルールによって「ひとつひとつ」許可しなければなりません。
手間の見返りとしてセキュリティーが向上します。
DNS問い合わせを許可
プロトコル「tcp」「udp」のそれぞれで、システムからの外部DNSへの「新しい接続の要求」を許可します。
DNS問い合わせの宛先ポートは「53」です。
iptables -A OUTPUT -p udp -m state --state NEW --dport 53 -j ACCEPT
iptables -A OUTPUT -p tcp -m state --state NEW --dport 53 -j ACCEPT
「ESTABLISHED」と「RELATED」は「INPUT」「OUTPUT」の双方向で許可済みなのでこのルールの追加だけでOKです。
NTP問い合わせを許可
プロトコル「udp」でNTPの「123」ポートを許可します。
iptables -A OUTPUT -p udp -m state --state NEW --dport 123 -j ACCEPT
これだけでOKです。
「systemd-timesyncd」は一度ブロックされると死んでしまうので、ルール追加後に再起動が必要です。
systemctl status systemd-timesyncd.service
APTを許可
システムによっては定期的にアップデートを確認するものがあります。
必要に応じて許可しておくとよいでしょう。
「APT」は「http」「https」を使うので宛先ポート「80」「443」への「新しい接続の要求」を許可します。
iptables -A OUTPUT -p tcp -m state --state NEW --dport 80 -j ACCEPT
iptables -A OUTPUT -p tcp -m state --state NEW --dport 443 -j ACCEPT
ICMPを許可する
「ping」「traceroute」を送信できるか、あるいは応答するかを決定します。
インターネットにされされているわけではないのですべてのタイプの「icmp」の送信と受信を許可しても問題はないと思いますが、下記のように設定してみました。
iptables -A OUTPUT -m state --state NEW -p icmp --icmp-type echo-request -j ACCEPT
iptables -A INPUT -m state --state NEW -p icmp --icmp-type echo-request -s 192.168.1.0/24 -j ACCEPT
詳しく見ていきます。
まず「echo request」の送信開始を許可します。
「リプライ」は「RELATED」で許可されていますのでINPUTのルールは必要ありません。
iptables -A OUTPUT -m state --state NEW -p icmp --icmp-type echo-request -j ACCEPT
つづいて「ローカルアドレス」からの「echo request」の受信開始を許可します。
iptables -A INPUT -m state --state NEW -p icmp --icmp-type echo-request -s 192.168.1.0/24 -j ACCEPT
icmpを使った「攻撃」は送信元アドレスを詐称しているのが普通なのでソースを指定しても効果は小さいかもしれません。
通常はNATルーターの背後に置かれているわけですから、インターネットからicmpが届くことはありません。
icmpが宛先への到達確認以外にも多くの情報を知らせてくれることを勘案すると、ローカルネットワークではすべてのicmpを許可した方が利便がいいかもしれません。
つまり「INPUT」については次のようにすべてのICMPを受け入れることにします。
iptables -A INPUT -m state --state NEW -p icmp -j ACCEPT
これも「リプライは」「RELATED」で許可されていますのでOUTPUTのルールは必要ありません。
まとめ
「DROP」ポリシーを使う最低必要なファイアウォール ルールは次のようになります。
ルーターモードを有効にしていない単独ホストは「FORWARD」が無効になっていますが「iptables -P FORWARD DROP」も設定しておきます。
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# SSH
iptables -A INPUT -m state --state NEW -p tcp --dport 22 -s 192.168.1.0/24 -j ACCEPT
# DNS
iptables -A OUTPUT -p udp -m state --state NEW --dport 53 -j ACCEPT
iptables -A OUTPUT -p tcp -m state --state NEW --dport 53 -j ACCEPT
# NTP
iptables -A OUTPUT -p udp -m state --state NEW --dport 123 -j ACCEPT
# APT
iptables -A OUTPUT -p tcp -m state --state NEW --dport 80 -j ACCEPT
iptables -A OUTPUT -p tcp -m state --state NEW --dport 443 -j ACCEPT
# ICMP
iptables -A OUTPUT -m state --state NEW -p icmp --icmp-type echo-request -j ACCEPT
iptables -A INPUT -m state --state NEW -p icmp -j ACCEPT
設定状況の詳細を確認するばあいは、コマンドは「iptables -vL」です。
# iptables -vL
Chain INPUT (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT all -- lo any anywhere anywhere
73 5464 ACCEPT all -- any any anywhere anywhere state RELATED,ESTABLISHED
0 0 ACCEPT tcp -- any any 192.168.1.0/24 anywhere state NEW tcp dpt:ssh
0 0 ACCEPT icmp -- any any anywhere anywhere state NEW
Chain FORWARD (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT all -- any lo anywhere anywhere
39 3548 ACCEPT all -- any any anywhere anywhere state RELATED,ESTABLISHED
0 0 ACCEPT udp -- any any anywhere anywhere state NEW udp dpt:domain
0 0 ACCEPT tcp -- any any anywhere anywhere state NEW tcp dpt:domain
0 0 ACCEPT udp -- any any anywhere anywhere state NEW udp dpt:ntp
0 0 ACCEPT tcp -- any any anywhere anywhere state NEW tcp dpt:http
0 0 ACCEPT tcp -- any any anywhere anywhere state NEW tcp dpt:https
0 0 ACCEPT icmp -- any any anywhere anywhere state NEW icmp echo-request
これらの設定はOSを再起動すると初期化されます。
DebianでOS起動時にiptablesの設定を自動的に有効にするには次のような方法があります。
- 「iptables-persistent」を使う
- 上記のコマンドをスクリプトファイルにして「/etc/network/interfaces」ファイルの「up」ディレクティブによってインターフェイスが有効になった直後に設定を実行する
「iptables」は、Linuxに実装されたパケットフィルタリングおよびネットワークアドレス変換 (NAT) 機能であるNetfilterを操作するコマンドです。
今回は「iptables」の「filter」テーブルのみを使ってスタンドアローン システムの「ファイアウォール」を設定してみました。