Ubuntu 14.04でIptablesを使用して基本的なファイアウォールテンプレートを実装する方法

前書き

ファイアウォールの実装は、サーバーを保護するための重要なステップです。 その大部分は、ネットワークへのトラフィック制限を実施する個々のルールとポリシーを決定することです。 `+ iptables +`のようなファイアウォールでは、ルールが適用される構造的なフレームワークについて発言することもできます。

このガイドでは、より複雑なルールセットの基礎となるファイアウォールを構築します。 このファイアウォールは、合理的なデフォルトの提供と、容易な拡張性を促進するフレームワークの確立に主に焦点を合わせます。 これをUbuntu 14.04サーバーで実演します。

前提条件

開始する前に、実装するファイアウォールポリシーの基本的な考え方が必要です。 https://www.digitalocean.com/community/tutorials/how-to-choose-an-effective-firewall-policy-to-secure-your-servers [このガイド]に従って、いくつかのより良いアイデアを得ることができます。考えるべきこと。

従うには、Ubuntu 14.04サーバーにアクセスする必要があります。 このガイドでは、 `+ sudo +`特権で設定された非rootユーザーを使用します。 このタイプのユーザーの構成方法については、https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-14-04 [Ubuntu 14.04初期サーバーセットアップガイド]をご覧ください。

終了したら、以下に進みます。

持続的ファイアウォールサービスのインストール

開始するには、まだインストールしていない場合は、 `+ iptables-persistent +`パッケージをインストールする必要があります。 これにより、ルールセットを保存し、ブート時にそれらを自動的に適用できます。

sudo apt-get update
sudo apt-get install iptables-persistent

インストール中に、現在のルールを保存するかどうかを尋ねられます。 ここで「はい」と言います。 生成されたルールファイルを一時的に編集します。

このガイドのIPv6に関する注意

始める前に、IPv4とIPv6について簡単に説明する必要があります。 `+ iptables `コマンドはIPv4トラフィックのみを処理します。 IPv6トラフィックの場合、「 ip6tables 」と呼ばれる別のコンパニオンツールが使用されます。 ルールは別々のテーブルとチェーンに保存されます。 「 iptables-persistent 」の場合、IPv4ルールは「 / etc / iptables / rules.v4 」に読み書きされ、IPv6ルールは「 / etc / iptables / rules.v6 +」に保持されます。

このガイドでは、サーバーでIPv6を積極的に使用していないことを前提としています。 サービスでIPv6を利用しない場合、この記事で行うように、アクセスを完全にブロックする方が安全です。

基本的なファイアウォールポリシーの実装(簡単な方法)

できるだけ早く起動して実行するために、ルールファイルを直接編集して、完成したファイアウォールポリシーをコピーして貼り付ける方法を紹介します。 その後、一般的な戦略を説明し、ファイルを変更する代わりに `+ iptables +`コマンドを使用してこれらのルールを実装する方法を示します。

ファイアウォールポリシーとフレームワークを実装するために、 `+ / etc / iptables / rules.v4 `および ` / etc / iptables / rules.v6 `ファイルを編集します。 テキストエディタで ` sudo `権限で ` rules.v4 +`ファイルを開きます。

sudo nano /etc/iptables/rules.v4

内部には、次のようなファイルが表示されます。

/etc/iptables/rules.v4

# Generated by iptables-save v1.4.21 on Tue Jul 28 13:29:56 2015
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT
# Completed on Tue Jul 28 13:29:56 2015

内容を次のものに置き換えます。

/etc/iptables/rules.v4

*filter
# Allow all outgoing, but drop incoming and forwarding packets by default
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]

# Custom per-protocol chains
:UDP - [0:0]
:TCP - [0:0]
:ICMP - [0:0]

# Acceptable UDP traffic

# Acceptable TCP traffic
-A TCP -p tcp --dport 22 -j ACCEPT

# Acceptable ICMP traffic

# Boilerplate acceptance policy
-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
-A INPUT -i lo -j ACCEPT

# Drop invalid packets
-A INPUT -m conntrack --ctstate INVALID -j DROP

# Pass traffic to protocol-specific chains
## Only allow new connections (established and related should already be handled)
## For TCP, additionally only allow new SYN packets since that is the only valid
## method for establishing a new TCP connection
-A INPUT -p udp -m conntrack --ctstate NEW -j UDP
-A INPUT -p tcp --syn -m conntrack --ctstate NEW -j TCP
-A INPUT -p icmp -m conntrack --ctstate NEW -j ICMP

# Reject anything that's fallen through to this point
## Try to be protocol-specific w/ rejection message
-A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
-A INPUT -p tcp -j REJECT --reject-with tcp-reset
-A INPUT -j REJECT --reject-with icmp-proto-unreachable

# Commit the changes
COMMIT

*raw
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT

*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT

*security
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT

*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT

ファイルを保存して閉じます。

このコマンドを入力して、ファイルの構文エラーをテストできます。 続行する前に、これにより明らかになる構文エラーを修正します。

sudo iptables-restore -t /etc/iptables/rules.v4

次に、 `+ / etc / iptables / rules.v6 +`ファイルを開いて、IPv6ルールを変更します。

sudo nano /etc/iptables/rules.v6

ファイルの内容を以下の構成に置き換えることにより、すべてのIPv6トラフィックをブロックできます。

/etc/iptables/rules.v6

*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
COMMIT

*raw
:PREROUTING DROP [0:0]
:OUTPUT DROP [0:0]
COMMIT

*nat
:PREROUTING DROP [0:0]
:INPUT DROP [0:0]
:OUTPUT DROP [0:0]
:POSTROUTING DROP [0:0]
COMMIT

*security
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
COMMIT

*mangle
:PREROUTING DROP [0:0]
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
:POSTROUTING DROP [0:0]
COMMIT

ファイルを保存して閉じます。

このファイルの構文エラーをテストするには、 `+ -t `オプションを指定した ` ip6tables-restore +`コマンドを使用できます。

sudo ip6tables-restore -t /etc/iptables/rules.v6

両方のルールファイルで構文エラーが報告されない場合は、次のように入力してルールを適用できます。

sudo service iptables-persistent reload

これにより、ファイルに記載されているポリシーがすぐに実装されます。 これを確認するには、現在使用中の `+ iptables +`ルールをリストします:

sudo iptables -S
sudo ip6tables -S

これらのファイアウォールルールは、起動するたびに再適用されます。 ログインして、他のすべてのアクセスがブロックされていることを確認してください。

一般的なファイアウォール戦略の説明

上記のルールを使用して構築した基本的なファイアウォールでは、ルールを追加または削除するために簡単に調整できる拡張可能なフレームワークを作成しました。 IPv4トラフィックでは、主に「+ filter on」テーブル内の「+ INPUT」チェーンに関心があります。 このチェーンは、サーバー宛てのすべてのパケットを処理します。 また、すべての発信トラフィックを許可し、すべてのパケット転送を拒否しました。これは、このサーバーが他のホストのルーターとして機能している場合にのみ適切です。 このガイドではパケットのフィルタリングのみを目的としているため、他のすべてのテーブルでパケットを受け入れます。

一般に、私たちのルールは、デフォルトで着信トラフィックを拒否するファイアウォールを設定します。 次に、このポリシーから除外するサービスとトラフィックタイプの例外を作成します。

メインの「+ INPUT +」チェーンに、常に同じ方法で処理されると確信しているトラフィックの一般的なルールを追加しました。 たとえば、「無効」と見なされるパケットを常に拒否し、ローカルループバックインターフェイス上のトラフィックと確立された接続に関連付けられたデータを常に許可します。

その後、使用しているプロトコルに基づいてトラフィックを照合し、プロトコル固有のチェーンにシャッフルします。 これらのプロトコル固有のチェーンは、特定のサービスのトラフィックに一致して許可するルールを保持するためのものです。 この例では、許可するサービスは「+ TCP +」チェーンのSSHのみです。 HTTP(S)サーバーなどの別のサービスを提供している場合、ここにも例外を追加できます。 これらのチェーンは、ほとんどのカスタマイズの焦点になります。

プロトコル固有の汎用ルールまたはサービスルールと一致しないトラフィックは、 `+ INPUT `チェーンの最後のいくつかのルールによって処理されます。 ファイアウォールのデフォルトポリシーを「 DROP 」に設定しました。これにより、ルールに該当するパケットが拒否されます。 ただし、 ` INPUT +`チェーンの最後にあるルールはパケットを拒否し、そのポートでサービスが実行されていない場合のサーバーの応答を模倣するメッセージをクライアントに送信します。

IPv6トラフィックの場合、単にすべてのトラフィックをドロップします。 サーバーはこのプロトコルを使用していないため、トラフィックにまったく関与しないことが最も安全です。

(オプション)ネームサーバーの更新

すべてのIPv6トラフィックをブロックすると、サーバーがインターネット上の問題を解決する方法に干渉する可能性があります。 たとえば、これはAPTの使用方法に影響を与える可能性があります。

`+ apt-get update`を実行しようとしたときに次のようなエラーが発生した場合:

エラー

Err http://security.ubuntu.com trusty-security InRelease

Err http://security.ubuntu.com trusty-security Release.gpg
 Could not resolve 'security.ubuntu.com'

. . .

APTを再び機能させるには、このセクションに従ってください。

まず、ネームサーバーを外部のネームサーバーに設定します。 この例では、Googleのネームサーバーを使用しています。 編集のために `+ / etc / network / interfaces`を開きます:

sudo nano /etc/network/interfaces

次のように `+ dns-nameservers +`行を更新します。

/ etc / network / interfaces

. . .
iface eth0 inet6 static
       address 2604:A880:0800:0010:0000:0000:00B2:0001
       netmask 64
       gateway 2604:A880:0800:0010:0000:0000:0000:0001
       autoconf 0
       dns-nameservers

ネットワーク設定を更新します。

sudo ifdown eth0 && sudo ifup eth0

予想される出力は次のとおりです。

出力

RTNETLINK answers: No such process
Waiting for DAD... Done

次に、使用可能な場合にIPv4を強制する新しいファイアウォールルールを作成します。 この新しいファイルを作成します。

sudo nano /etc/apt/apt.conf.d/99force-ipv4

この単一行をファイルに追加します。

/etc/apt/apt.conf.d/99force-ipv4

Acquire::ForceIPv4 "true";

ファイルを保存して閉じます。 これで、APTを使用できるはずです。

IPTablesコマンドを使用したファイアウォールの実装

作成したポリシーの背後にある一般的な考え方を理解したので、 `+ iptables`コマンドを使用してこれらのルールを作成する方法について説明します。 上記で指定したルールと同じルールになりますが、ルールを繰り返し追加してポリシーを作成します。 `+ iptables +`は各ルールをすぐに適用するため、ルールの順序は非常に重要です(パケットを拒否するルールは最後まで残します)。

ファイアウォールをリセットする

まず、ファイアウォールルールをリセットして、コマンドラインからポリシーを構築する方法を確認します。 次のように入力して、すべてのルールをフラッシュできます。

sudo service iptables-persistent flush

次のように入力して、ルールがリセットされたことを確認できます。

sudo iptables -S

`+ filter `テーブルのルールがなくなり、すべてのチェーンでデフォルトポリシーが ` ACCEPT +`に設定されていることがわかります。

output-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT

プロトコル固有のチェーンを作成する

プロトコル固有のチェーンをすべて作成することから始めます。 これらは、公開するサービスの拒否ポリシーの例外を作成するルールを保持するために使用されます。 「+ UDP」トラフィック用、「+ TCP」用、および「+ ICMP」用に作成します。

sudo iptables -N UDP
sudo iptables -N TCP
sudo iptables -N ICMP

先に進んで、SSHトラフィックの例外を追加できます。 SSHはTCPを使用するため、ポート22宛てのTCPトラフィックをTCPチェーンに受け入れるルールを追加します。

sudo iptables -A TCP -p tcp --dport 22 -j ACCEPT

TCPサービスを追加したい場合は、ポート番号を置き換えてコマンドを繰り返すことにより、これを実行できます。

汎用の受け入れルールと拒否ルールを作成する

すべての着信トラフィックがフィルタリングを開始する「+ INPUT +」チェーンでは、汎用ルールを追加する必要があります。 これらは、低リスクのトラフィック(ローカルトラフィックおよび既に確認した接続に関連付けられているトラフィック)を受け入れ、明らかに役に立たないトラフィック(無効なパケット)を受け入れることにより、ファイアウォールのベースラインを設定する常識ルールです。

最初に、確立された接続の一部であるか、確立された接続に関連するすべてのトラフィックを受け入れる例外を作成します。

sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

このルールは、内部追跡を提供する「+ conntrack 」拡張機能を使用します。これにより、「 iptables +」は、個別の無関係なパケットのストリームとしてではなく、より大きな接続の一部としてパケットを評価するために必要なコンテキストを持ちます。 TCPは接続ベースのプロトコルであるため、確立された接続はかなり明確に定義されています。 UDPおよびその他のコネクションレスプロトコルの場合、確立された接続とは、応答を見たトラフィックを指します(元のパケットのソースが応答パケットの宛先になり、逆も同様です)。 関連する接続とは、既存の接続に関連して開始された新しい接続を指します。 ここでの古典的な例は、FTPデータ転送接続です。これは、すでに確立されているFTP制御接続に関連しています。

また、ローカルループバックインターフェイスから発信されるすべてのトラフィックを許可します。 これは、サーバーによって生成され、サーバー宛てのトラフィックです。 ホスト上のサービスが相互に通信するために使用します。

sudo iptables -A INPUT -i lo -j ACCEPT

最後に、無効なパケットをすべて拒否します。 パケットはいくつかの理由で無効になる可能性があります。 存在しない接続を参照する場合もあれば、存在しないインターフェイス、アドレス、またはポートを宛先とする場合もあれば、単に不正な形式である場合もあります。 いずれにしても、無効なパケットを処理する適切な方法がなく、悪意のあるアクティビティを表す可能性があるため、すべての無効なパケットをドロップします。

sudo iptables -A INPUT -m conntrack --ctstate INVALID -j DROP

プロトコル固有のチェーンへのジャンプルールの作成

これまで、 `+ INPUT `チェーンのいくつかの一般的なルールと、プロトコル固有のチェーン内の特定の受け入れ可能なサービスのいくつかのルールを作成しました。 ただし、現在、トラフィックは「 INPUT +」チェーンに入り、プロトコル固有のチェーンに到達する方法がありません。

`+ INPUT +`チェーンのトラフィックを適切なプロトコル固有のチェーンに転送する必要があります。 プロトコルタイプを照合して、正しいチェーンに送信できます。 また、パケットが新しい接続を表していることを確認します(確立された接続または関連する接続は、すでに早く処理されている必要があります)。 TCPパケットの場合、TCP接続を開始するための唯一の有効なタイプであるSYNパケットであるという追加の要件を追加します。

sudo iptables -A INPUT -p udp -m conntrack --ctstate NEW -j UDP
sudo iptables -A INPUT -p tcp --syn -m conntrack --ctstate NEW -j TCP
sudo iptables -A INPUT -p icmp -m conntrack --ctstate NEW -j ICMP

残りのトラフィックをすべて拒否

プロトコル固有のチェーンに渡されたパケットが内部のどのルールとも一致しなかった場合、制御は `+ INPUT +`チェーンに戻されます。 このポイントに達するものはすべて、ファイアウォールで許可されるべきではありません。

クライアントに応答メッセージを送信する `+ REJECT +`ターゲットを使用してトラフィックを拒否します。 これにより、クライアントが通常の閉じたポートにパケットを送信しようとした場合に与えられる応答を模倣できるように、アウトバウンドメッセージングを指定できます。 応答は、クライアントが使用するプロトコルに依存します。

閉じたUDPポートに到達しようとすると、ICMPの「ポート到達不能」メッセージが表示されます。 次のように入力して、これを模倣できます。

sudo iptables -A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable

閉じたポートでTCP接続を確立しようとすると、TCP RST応答が返されます。

sudo iptables -A INPUT -p tcp -j REJECT --reject-with tcp-reset

他のすべてのパケットについては、ICMP「プロトコル到達不能」メッセージを送信して、サーバーがそのタイプのパケットに応答しないことを示すことができます。

sudo iptables -A INPUT -j REJECT --reject-with icmp-proto-unreachable

デフォルトポリシーの調整

追加した最後の3つのルールは、 `+ INPUT `チェーンの残りのすべてのトラフィックを処理する必要があります。 ただし、予防策としてデフォルトのポリシーを「 DROP 」に設定する必要があります。 このサーバーが他のマシンへのルーターとして設定されていない場合は、このポリシーを ` FORWARD +`チェーンに設定する必要もあります。

sudo iptables -P INPUT DROP
sudo iptables -P FORWARD DROP

警告

すべてのトラフィックをドロップするというIPv6ポリシーに一致させるために、次の `+ ip6tables`コマンドを使用できます。

sudo ip6tables -P INPUT DROP
sudo ip6tables -P FORWARD DROP
sudo ip6tables -P OUTPUT DROP

これにより、ルールセットをかなり厳密に複製する必要があります。

IPTablesルールの保存

この時点で、ファイアウォールルールをテストし、通常のアクセスを妨げずに、禁止するトラフィックのブロックをカバーすることを確認する必要があります。 ルールが正しく動作していることに満足したら、それらを保存して、ブート時にシステムに自動的に適用されるようにすることができます。

次のように入力して、現在のルール(IPv4とIPv6の両方)を保存します。

sudo service iptables-persistent save

これにより、 `+ / etc / iptables / rules.v4 `および ` / etc / iptables / rules.v6 +`ファイルがコマンドラインで作成したポリシーで上書きされます。

結論

ファイアウォールルールを構成ファイルに直接貼り付けるか、コマンドラインで手動で適用して保存することにより、このガイドに従うことで、適切な開始ファイアウォール構成を作成できました。 使用可能にするサービスへのアクセスを許可するには、個々のルールを追加する必要があります。

このガイドで確立されたフレームワークにより、簡単に調整でき、既存のポリシーを明確にすることができます。 人気のあるサービスでファイアウォールポリシーを構築する方法については、他のガイドをご覧ください。

Related