序章

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

このガイドでは、より複雑なルールセットの基礎となるファイアウォールを構築する方法を学習します。 このファイアウォールは、主に合理的なデフォルトを提供し、拡張性を促進するフレームワークを確立することに重点を置いています。

前提条件

このチュートリアルを完了するには、root以外のユーザーが設定されたUbuntu20.04サーバーにアクセスする必要があります。 sudo 特権。 このチュートリアルではファイアウォールを設定するため、手順4 を除き、Ubuntu20.04初期サーバー設定ガイドで概説されているすべての手順に従うことでこれを行うことができます。

さらに、実装するファイアウォールポリシーを確認することをお勧めします。 このガイドに従って、何を考慮すべきかをよりよく理解することができます。

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

ローカルパッケージキャッシュを更新することから始めます。

  1. sudo apt update

今すぐインストールします iptables-persistent パッケージ。 これにより、ルールセットを保存し、起動時に自動的に適用することができます。

  1. sudo apt install iptables-persistent

インストール中に、現在のルールを保存するかどうかを尋ねられます。 。 を実行することに注意してください netfilter-persistent を実行するコマンド iptables 永続的なファイアウォールサービス。 次に、生成されたルールファイルを編集します。

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

始める前に、IPv4とIPv6について簡単に説明します。 The iptables コマンドはIPv4トラフィックのみを処理します。 IPv6トラフィックの場合、別のコンパニオンツールと呼ばれる ip6tables 使用されている。 ルールは別々のテーブルとチェーンに保存されます。 のために netfilter-persistent コマンドを実行すると、IPv4ルールの書き込みと読み取りが行われます。 /etc/iptables/rules.v4、およびIPv6ルールはに格納されます /etc/iptables/rules.v6.

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

基本的なファイアウォールポリシーの実装(クイックウェイ)

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

ファイアウォールポリシーとフレームワークを実装するには、 /etc/iptables/rules.v4/etc/iptables/rules.v6 ファイル。 を開きます rules.v4 お好みのテキストエディタでファイルします。 ここでは、 nano:

  1. sudo nano /etc/iptables/rules.v4

内部には、ファイルに次の内容が含まれます。

/etc/iptables/rules.v4
# Generated by iptables-save v1.8.4 on Tue Mar  1 19:03:10 2022
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT
# Completed on Tue Mar  1 19:03:10 2022

これらのコンテンツを削除し、次のように置き換えます。

/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

ファイルを保存して閉じます。 使用している場合 nano、を押すことでこれを行うことができます CTRL + X、 それから YENTER.

次のコマンドを実行して、ファイルの構文エラーをテストできます。 次のいずれかが発生した場合は、構文エラーを修正してください。

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

次に、 /etc/iptables/rules.v6 IPv6ルールを変更するファイル:

  1. sudo nano /etc/iptables/rules.v6

このファイルの内容は次のとおりです。

/etc/iptables/rules.v6
# Generated by ip6tables-save v1.8.4 on Tue Mar  1 19:03:10 2022
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT
# Completed on Tue Mar  1 19:03:10 2022

ファイルの内容を次の構成に置き換えることで、すべての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

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

このファイルの構文エラーをテストするには、 ip6tables-restore とのコマンド -t オプション:

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

両方のルールファイルで構文エラーが報告されていない場合は、次のコマンドを実行して設定したルールを適用できます。

  1. sudo service netfilter-persistent reload
Output
* Loading netfilter rules... run-parts: executing /usr/share/netfilter-persistent/plugins.d/15-ip4tables start run-parts: executing /usr/share/netfilter-persistent/plugins.d/25-ip6tables start [ OK ]

これにより、ファイルに概説されているポリシーがすぐに実装されます。 これを確認するには、 iptables 現在使用されているルール。 IPv4の最初のチェック:

  1. sudo iptables -S
Output
-P INPUT DROP -P FORWARD DROP -P OUTPUT ACCEPT -N ICMP -N TCP -N UDP -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A INPUT -i lo -j ACCEPT -A INPUT -m conntrack --ctstate INVALID -j DROP -A INPUT -p udp -m conntrack --ctstate NEW -j UDP -A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NEW -j TCP -A INPUT -p icmp -m conntrack --ctstate NEW -j ICMP -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 -A TCP -p tcp -m tcp --dport 22 -j ACCEPT

次に、現在のIPv6ルールを確認します。

  1. sudo ip6tables -S
Output
-P INPUT DROP -P FORWARD DROP -P OUTPUT DROP

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

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

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

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

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

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

プロトコル固有のチェーンの一般的なルールまたはサービスルールと一致しないトラフィックは、 INPUT 鎖。 デフォルトのポリシーをに設定しました DROP ルールを通過するパケットを拒否するファイアウォールの場合。 ただし、最後のルール INPUT チェーンはパケットを拒否し、そのポートでサービスが実行されていない場合にサーバーがどのように応答するかを模倣したメッセージをクライアントに送信します。

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

を使用してファイアウォールを実装する iptables 指示

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

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

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

  1. sudo service netfilter-persistent flush

次に、ルールがリセットされていることを確認します。

  1. sudo iptables -S

のルールを示す出力が必要です filter テーブルがなくなり、デフォルトのポリシーがに設定されている ACCEPT すべてのチェーンで:

Output
-P INPUT ACCEPT -P FORWARD ACCEPT -P OUTPUT ACCEPT

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

次に、プロトコル固有のチェーンをすべて作成します。 これらは、公開するサービスの拒否ポリシーに対する例外を作成するルールを保持するために使用されます。 のために作成します UDP トラフィック:

  1. sudo iptables -N UDP

その後、別のもの TCP:

  1. sudo iptables -N TCP

そしてもう1つ ICMP:

  1. sudo iptables -N ICMP

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

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

TCPサービスを追加する場合は、ポート番号を置き換えてコマンドを繰り返すことで、ここで追加できます。

汎用の承認および拒否ルールの作成

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

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

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

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

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

  1. sudo iptables -A INPUT -i lo -j ACCEPT

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

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

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

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

今、あなたはトラフィックを向ける必要があります INPUT 適切なプロトコル固有のチェーンにチェーンします。 プロトコルタイプを照合して、正しいチェーンに送信できます。 また、パケットが新しい接続を表していることを確認してください(確立された接続または関連する接続はすべて以前に処理されている必要があります)。 皮切りに UDP トラフィック:

  1. sudo iptables -A INPUT -p udp -m conntrack --ctstate NEW -j UDP

次に、次のコマンドを実行します TCP トラフィック。 TCPパケットでは、パケットが SYN パケットであるという追加要件が追加されることに注意してください。これは、TCP接続を開始するための唯一の有効なタイプです。

  1. sudo iptables -A INPUT -p tcp --syn -m conntrack --ctstate NEW -j TCP

次に、以下を実行します ICMP トラフィック:

  1. sudo iptables -A INPUT -p icmp -m conntrack --ctstate NEW -j ICMP

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

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

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

クローズに到達しようとしています UDP ポートは結果として ICMP 「ポートに到達できません」というメッセージ。 次のコマンドを実行することで、これを模倣できます。

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

確立しようとしています TCP 閉じたポートで接続すると、TCPRST応答が発生します。

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

他のすべてのパケットについては、 ICMP サーバーがそのタイプのパケットに応答しないことを示す「protocolunreachable」メッセージ:

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

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

追加した最後の3つのルールは、 INPUT 鎖。 ただし、デフォルトのポリシーを次のように設定する必要があります DROP 予防措置として、次のように:

  1. sudo iptables -P INPUT DROP

このポリシーは、 FORWARD このサーバーが他のマシンへのルーターとして構成されていない場合は、チェーンします。

  1. sudo iptables -P FORWARD DROP

警告:ポリシーを次のように設定します DROP、あなたがあなたをクリアした場合 iptablessudo iptables -F、現在のSSH接続は切断されます! でフラッシング sudo netfilter-persistent flush デフォルトのポリシーもリセットされるため、ルールをクリアするためのより良い方法です。

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

  1. sudo ip6tables -P INPUT DROP

次に、以下を実行します FORWARD:

  1. sudo ip6tables -P FORWARD DROP

のポリシーを設定して終了します OUTPUT:

  1. sudo ip6tables -P OUTPUT DROP

これにより、ルールセットがかなり厳密に複製されます。

保存 iptables ルール

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

次のコマンドを実行して、現在のルール(IPv4とIPv6の両方)を保存します。

  1. sudo service netfilter-persistent save

これはあなたの /etc/iptables/rules.v4/etc/iptables/rules.v6 コマンドラインで作成したポリシーを含むファイル。

結論

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

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