SS-Infra ← ポータルに戻る

iptables

1. iptablesの概要と目的

iptables(アイピーテーブルズ)は、Linuxでパケットの通過・遮断を制御するための設定ツールです。

サーバーを構築すると、「SSHは特定のIPアドレスからのみ許可したい」「Webの80番と443番以外は閉じたい」といった要件が必ず出てきます。iptablesを使うと、こうしたルールをサーバー自身に設定し、不要な通信を入口の段階で遮断できます。

この章では、iptablesがどのようなものなのか、また、なぜ知っておく必要があるのかを確認します。

iptablesとは?

iptablesとは、Linuxカーネルに組み込まれたパケット処理の仕組み「netfilter」を操作するためのコマンドです。Linux 2.4で導入され、長年にわたってLinuxサーバーのファイアウォール設定の標準的な手段として使われてきました。

iptablesで設定するルールは、次の要素の組み合わせで表現されます。

「どの通信」に対して「何をするか」
(例)TCPの22番ポート宛の通信 → 許可する

実際のコマンドでは、次のように記述します。

# TCPの22番ポート(SSH)宛の通信を許可する
iptables -A INPUT -p tcp --dport 22 -j ACCEPT

ここで重要なのは、iptablesのルールが上から順に評価され、最初に一致したルールが適用されるという点です。

ルール1:22番ポートを許可    ← ここで一致したら、以降は評価されない
ルール2:すべて破棄

同じルールを並べ替えるだけで結果が正反対になるため、「何を書いたか」だけでなく「どの順で書いたか」が設定の成否を決めます。

このように、通信の条件と処理を一覧として定義し、順番に照合していく点がiptablesの大きな特徴です。

なお、現在の多くのディストリビューションでは、後継の nftables が標準となっています。ただし iptables コマンドは互換層を通じて引き続き利用でき、既存の資料や運用手順も大量に残っているため、理解しておく価値は変わりません。

iptablesはどのような場面で登場するのか?

iptablesは、主にLinuxサーバーの構築時やセキュリティ対策の場面で登場します。

例えば、次のような場面が代表的な利用例です。

インフラ担当者にとって、iptablesはサーバーを公開するうえで最初に向き合う防御の層です。

2. iptablesの仕組み・規格・主な特徴

iptablesは、「テーブル」「チェイン」「ルール」という3階層でパケットの扱いを定義します。

パケットがサーバーに届くと、その役割に応じて決まった順序でチェインを通過し、各チェイン内のルールが上から順に照合されます。

ここでは、テーブルとチェインの構成や、実際の記述例を確認します。

テーブルとチェインの違いと特徴

iptablesのテーブルは、目的ごとに分かれています。主なものは次の3つです。

それぞれのテーブルには、パケットの流れに応じた「チェイン」が用意されています。filterテーブルの場合は次の3つです。

ルールの末尾で指定する処理(ターゲット)には、主に次のものがあります。

パケットが届いてから処理が決まるまでの流れを追うと、次のようになります。

  1. 受信したパケットが、natテーブルの PREROUTING チェインなどを通過する。
  2. 宛先がこのサーバー自身であれば INPUT、別の宛先への転送であれば FORWARD へ振り分けられる。
  3. そのチェインに登録されたルールを、上から順に照合する。
  4. 一致したルールのターゲット(ACCEPT や DROP)が適用され、評価が終了する。
  5. どのルールにも一致しなかった場合、そのチェインに設定された既定の処理(ポリシー)が適用される。

この5のポリシーを DROP にしておくことで、「明示的に許可したものだけを通す」という設計になります。これがファイアウォール設定の基本的な考え方です。

ルールの記述

実際の設定は、コマンドを順番に実行して組み立てます。

例えば、次のような記述になります。

【記述・構造の具体例】

必要な通信だけを許可する、最小構成のルールを設定する例です。

# 既存のルールを初期化する
iptables -F INPUT

# 確立済みの通信と、サーバー内部の通信を先に許可する
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT

# 必要なサービスを許可する
iptables -A INPUT -p tcp --dport 22 -j ACCEPT    # SSH
iptables -A INPUT -p tcp --dport 80 -j ACCEPT    # HTTP
iptables -A INPUT -p tcp --dport 443 -j ACCEPT   # HTTPS

# どのルールにも一致しなかったものを破棄する
iptables -P INPUT DROP
iptables -P FORWARD DROP

この構成で押さえておきたい点が3つあります。

1つ目は、確立済みの通信を許可するルールを最初に置くことです。サーバーから外部へ接続した際の応答パケットは、このルールがないと破棄されてしまいます。ソフトウェアの更新やDNSの問い合わせができなくなる原因になります。

2つ目は、ループバック(lo)を許可することです。サーバー内部のプロセス同士の通信もINPUTチェインを通るため、これを閉じるとデータベース接続などが動かなくなります。

3つ目は、ポリシーの変更を最後に行うことです。先にポリシーを DROP にしてしまうと、許可ルールを追加する前の時点でSSHの接続が切断され、作業が続けられなくなります。

なお、ルールを追加するオプションには -A(末尾に追加)と -I(先頭に挿入)があります。評価は上から順に行われるため、どちらを使うかで結果が変わります。既存の設定へ割り込ませたい場合は -I を使用します。

3. iptablesが使われる理由・メリットと活用シーン

iptablesが使われる理由は、OSのカーネルレベルで通信を遮断できるため、アプリケーションに到達する前に不要な通信を排除できることにあります。

アプリケーション側で接続元を制限する実装を用意しなくても、サーバー全体に一律の方針を適用できます。

iptablesを使うメリット

アプリケーションごとにアクセス制限を実装すると、設定が分散し、漏れが生じやすくなります。

iptablesを適切に使用することで、次のようなメリットが生まれます。

ただし、iptablesはIPアドレスやポート番号といった情報で判断する仕組みです。通信の中身を見て攻撃を判定するわけではないため、SQLインジェクションのようなアプリケーション層の攻撃は防げません。WAFなど別の層の対策と組み合わせる必要があります。

サーバー構築や運用で活用する

実際のサーバー運用では、以下のような場面で活用されます。

このように、「誰に、どのサービスを見せるか」を定める場面で中心的な役割を果たします。

iptablesの設定の確認方法

現在のルールは、コマンドで確認できます。

# filterテーブルのルールを、行番号とヒット数つきで確認する
sudo iptables -L -n -v --line-numbers

# natテーブルのルールを確認する
sudo iptables -t nat -L -n -v

# 設定全体を、復元可能な形式で出力する
sudo iptables-save

# IPv6側のルールも確認する
sudo ip6tables -L -n -v

ここで -n を付けるのは、IPアドレスをホスト名に逆引きさせないためです。付けない場合、名前解決の待ち時間で表示が極端に遅くなることがあります。

また、-v を付けると各ルールが処理したパケット数が表示されます。意図したルールが実際に使われているかを確かめるうえで有効です。許可ルールを追加したのにヒット数が0のままであれば、そのルールまで到達していない(手前のルールで処理されている)ことを示します。

接続を試して確認する場合は、拒否のされ方にも注目してください。即座に「接続拒否」が返る場合は REJECT か、そもそもサービスが起動していない状態です。一方、応答がなく時間切れになる場合は DROP で破棄されている可能性が高く、ファイアウォールの設定を疑うべき状況です。

Web上の確認ツールを利用すれば、外部のネットワークから自分のサーバーのポートが開いているかを確認できます。設定したつもりのルールが実際に効いているかは、サーバーの内側からは判断できないため、外部からの確認が欠かせません。

関連技術・関連用語との違い

iptablesと混同されやすい関連用語として、次のようなものがあります。

iptablesが「サーバー自身に設定する防御」であるのに対し、セキュリティグループは「サーバーの手前に置く防御」です。

両方を使っている環境では、通信がどちらで遮断されているのかを切り分ける必要があります。クラウド環境では、まずセキュリティグループを確認するほうが早いケースも多くあります。

4. iptablesの導入・運用時の注意点と課題

iptablesは強力な反面、設定を誤るとサーバーへ接続できなくなる、あるいは意図せず外部へ公開されてしまうという両方向のリスクがあります。

特に、設定が即座に反映される一方で、再起動すると消えてしまうという性質が事故につながりやすい点です。

ここでは、実務上注意すべきポイントを説明します。

よくあるミス・設定ミス

よくある問題の一つが、ルールの順序を誤り、追加したはずの許可ルールが評価されないことです。

# 悪い例:すべてを破棄するルールが先にある
iptables -A INPUT -j DROP
iptables -A INPUT -p tcp --dport 80 -j ACCEPT   # ここへは到達しない

この設定では、1行目ですべてのパケットが破棄されるため、2行目は永久に評価されません。「許可ルールを追加したのに通らない」という症状の多くは、この順序の問題です。iptables -L -n -v でヒット数を確認すると、該当ルールが0件のままであることから判断できます。

また、次のようなミスも頻出します。

運用・セキュリティ上の注意点

近年特に注意が必要なのが、コンテナ環境との組み合わせです。

【よくある失敗・注意点の例】

iptablesでポートを閉じたはずなのに、Dockerコンテナのポートが外部から接続できてしまう例です。

閉じたつもりの設定

Chain INPUT (policy DROP)
target     prot opt source               destination
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:80
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:443

ところが、外部から接続できてしまう

# コンテナのポートを公開する
docker run -d -p 3306:3306 mysql
$ nc -zv server.example.com 3306
Connection to server.example.com 3306 port [tcp/*] succeeded!

この例では、INPUT チェインで3306番を許可していないにもかかわらず、外部から接続できてしまっています。

原因は、Dockerがコンテナのポートを公開する際に、自らnatテーブルへ変換ルールを追加するためです。公開ポート宛の通信は宛先が書き換えられてコンテナへ転送されるため、INPUT チェインではなく FORWARD チェインを通ります。その結果、INPUT に書いた制限が適用されません。

FORWARD のポリシーを DROP にしていても防げません。Dockerは FORWARD チェインの先頭に自身の許可ルールを挿入するため、ポリシーが評価される前に通過してしまいます。

対処方法は主に次の2つです。

1つは、公開時に待ち受けアドレスを限定することです。-p 127.0.0.1:3306:3306 のように指定すれば、サーバー内部からのみ接続できる形になります。

もう1つは、Dockerが用意している DOCKER-USER チェインにルールを記述することです。このチェインはDocker自身のルールより先に評価されるため、ここでの制限が有効に働きます。

# 3306番への接続を、特定のネットワークからのみ許可する
iptables -I DOCKER-USER -i eth0 ! -s 192.0.2.0/24 -p tcp --dport 3306 -j DROP

-i には外部と接している実際のインターフェース名を指定します。また、ここでの --dport は宛先変換後のコンテナ側のポート番号を指す点に注意してください。公開ポートとコンテナ側のポートが異なる場合は、後者を指定します。

そのほか、運用面では次の点にも注意が必要です。

安全に利用するための対策

iptablesを適切に運用するためには、以下の対策が有効です。

特に、遠隔で作業する場合のロックアウト対策は欠かせません。次の手順で、万一接続が切れても自動的に復旧できる状態を作ってから作業を始めます。

# 1. 復旧用のバックアップを取得する
sudo iptables-save > /root/iptables.backup

# 2. atコマンドが使える状態かを確認する(atdが停止していると予約は実行されない)
systemctl is-active atd

# 3. 10分後に設定を元に戻す予約を入れる
echo "iptables-restore < /root/iptables.backup" | sudo at now + 10 minutes

# 4. 作業と動作確認を行う

# 5. 問題がなければ、予約を取り消す
sudo atq                # 予約の一覧とジョブ番号を確認する
sudo atrm <ジョブ番号>    # 該当の予約を削除する

手順5を忘れると、作業が無事に終わって永続化まで済ませた後に復元が実行され、設定が巻き戻ってしまいます。予約の取り消しまでを一連の手順として覚えておいてください。

なお、at は最小構成のイメージでは導入されていない場合があります。利用できない環境では、sleep と組み合わせたバックグラウンド実行や、クラウドのコンソール接続といった代替手段を事前に用意しておきます。

5. まとめと関連ツールのご案内

ここまで解説したiptablesについて、重要なポイントを振り返ります。

【お役立ちツールのご案内】

ここまで解説したiptablesの設定が、外部のネットワークから見て実際に効いているかを確認したい場合は、当サイトの TCPポート開放確認ツール をぜひご活用ください。

ホスト名とポート番号を入力するだけで、外部から接続できるかどうかを確認できます。遮断したつもりのポートが開いていないか、必要なポートが誤って閉じていないかの点検にお役立てください。