開発者ドキュメント

FreeBSD12.1でパケットフィルタ(PF)を設定する方法

序章

ファイアウォールは、間違いなくサイバー攻撃に対する最も重要な防御線の1つです。 ファイアウォールを最初から構成する機能は、管理者がネットワークを制御できるようにするスキルを強化します。

Packet Filter(PF)は、セキュリティ主導のOpenBSDプロジェクトによってアップストリームで維持されている有名なファイアウォールアプリケーションです。 パケットフィルタリングツールとしてより正確に表現されているため、この名前が付けられており、シンプルな構文、使いやすさ、豊富な機能で知られています。 PFはデフォルトでステートフルファイアウォールであり、分析目的でアクセスできる状態テーブルに接続に関する情報を格納します。 PFはFreeBSDベースシステムの一部であり、強力な開発者コミュニティによってサポートされています。 カーネルアーキテクチャに関連するPFのFreeBSDバージョンとOpenBSDバージョンの間には違いがありますが、一般的にそれらの構文は似ています。 複雑さに応じて、一般的なルールセットを変更して、比較的少ない労力でどちらのディストリビューションでも機能するようにすることができます。

このチュートリアルでは、PFを備えたFreeBSD12.1サーバー上でファイアウォールをゼロから構築します。 将来のプロジェクトのテンプレートとして使用できる基本ルールセットを設計します。 また、パケットの衛生管理、ブルートフォース防止、監視とロギング、その他のサードパーティツールなど、PFの高度な機能のいくつかについても説明します。

Note: As of July 1, 2022, DigitalOcean no longer supports the creation of new FreeBSD Droplets through the Control Panel or API. However, you can still spin up FreeBSD Droplets using a custom image. Learn how to import a custom image to DigitalOcean by following our product documentation.

前提条件

このチュートリアルを開始する前に、次のものが必要です。

ステップ1—予備的なルールセットを構築する

このチュートリアルは、基本的な保護とインターネットからの重要なサービスへのアクセスを提供する予備的なルールセットを作成することから始めます。 この時点で、アクティブなクラウドファイアウォールを備えたFreeBSD12.1サーバーが実行されています。

ファイアウォールを構築するには、デフォルトの拒否デフォルトの許可の2つのアプローチがあります。 デフォルトの拒否アプローチはすべてのトラフィックをブロックし、ルールで指定されたものだけを許可します。 デフォルトの許可アプローチは正反対です。すべてのトラフィックを通過させ、ルールで指定されたものだけをブロックします。 デフォルトの拒否アプローチを使用します。

PFルールセットは、という名前の構成ファイルに書き込まれます /etc/pf.conf、これはデフォルトの場所でもあります。 このファイルは、で指定されている限り、別の場所に保存してもかまいません。 /etc/rc.conf 構成ファイル。 このチュートリアルでは、デフォルトの場所を使用します。

root以外のユーザーでサーバーにログインします。

  1. ssh freebsd@your_server_ip

次に、 /etc/pf.conf ファイル:

  1. sudo vi /etc/pf.conf

注:チュートリアルの任意の時点で完全な基本ルールセットを確認したい場合は、ステップ4またはステップ8の例を参照してください。

PFは、次の3つのコアアクションに従ってパケットをフィルタリングします。 block, pass、 と match. 他のオプションと組み合わせると、ルールが形成されます。 パケットがルールで指定された基準を満たすと、アクションが実行されます。 ご想像のとおり、 passblock ルールは passblock トラフィック。 A match ルールは、一致する基準を見つけるとパケットに対してアクションを実行しますが、それを通過またはブロックしません。 たとえば、一致するパケットに対してネットワークアドレス変換(NAT)を渡すこともブロックすることもせずに実行でき、別のルールにルーティングするなど、別のルールで何かを行うように指示するまでそこに留まります。マシンまたはゲートウェイ。

次に、最初のルールを /etc/pf.conf ファイル:

/etc/pf.conf
block all

このルールは、あらゆる方向のあらゆる形態のトラフィックをブロックします。 方向を指定しないため、デフォルトでは両方になります inout. このルールは、世界から隔離する必要があるローカルワークステーションには有効ですが、ほとんど実用的ではなく、SSHトラフィックを許可しないため、リモートサーバーでは機能しません。 実際、PFを有効にした場合は、サーバーから自分自身をロックアウトしていたでしょう。

あなたの /etc/pf.conf 次の強調表示された行でSSHトラフィックを許可するファイル:

/etc/pf.conf
block all
pass in proto tcp to port 22

注:または、プロトコルの名前を使用することもできます。

/etc/pf.conf
block all
pass in proto tcp to port ssh

一貫性を保つために、正当な理由がない限り、ポート番号を使用します。 プロトコルとそれぞれのポート番号の詳細なリストは、 /etc/services ファイル。表示することをお勧めします。

PFはルールを上から下に順番に処理するため、現在のルールセットは最初にすべてのトラフィックをブロックしますが、次の行の基準(この場合はSSHトラフィック)が一致すると、ルールセットを渡します。

これでサーバーにSSHで接続できますが、それでもすべての形式のアウトバウンドトラフィックをブロックしています。 これは、インターネットから重要なサービスにアクセスしてパッケージをインストールしたり、時間設定を更新したりすることができないため、問題があります。

これに対処するには、次の強調表示されたルールを最後に追加します /etc/pf.conf ファイル:

/etc/pf.conf
block all
pass in proto tcp to port { 22 }
pass out proto { tcp udp } to port { 22 53 80 123 443 }

ルールセットは、アウトバウンド SSH DNS HTTP NTP 、およびHTTPSトラフィックを許可し、すべてのインワードトラフィックをブロックするようになりました。 SSHを除く)。 ポート番号とプロトコルを中括弧内に配置します。これにより、PF構文のリストが形成され、必要に応じてポート番号を追加できます。 ポートのUDPプロトコルのパスアウトルールも追加します 53123 DNSとNTPは、TCPプロトコルとUDPプロトコルの両方を切り替えることが多いためです。 予備のルールセットはほぼ完成しました。基本的な機能を実現するには、いくつかのルールを追加するだけです。

強調表示されたルールを使用して予備ルールセットを完成させます。

予備ルールセット/etc/pf.conf
set skip on lo0
block all
pass in proto tcp to port { 22 }
pass out proto { tcp udp } to port { 22 53 80 123 443 }
pass out inet proto icmp icmp-type { echoreq }

ファイルを保存して終了します。

あなたは set skip トラフィックをフィルタリングする必要がなく、サーバーをクロールする可能性があるため、ループバックデバイスのルール。 追加します pass out inet ICMP プロトコルのルール。これにより、 ping(8)ユーティリティを使用してトラブルシューティングを行うことができます。 The inet オプションは、IPv4アドレスファミリを表します。

ICMPは、さまざまなタイプの通信のためにネットワークデバイスによって使用される多目的メッセージングプロトコルです。 たとえば、pingユーティリティは、 echo request と呼ばれるタイプのメッセージを使用します。これは、ユーザーに追加したものです。 icmp_type リスト。 予防措置として、歓迎されないデバイスがサーバーに接続するのを防ぐために必要なメッセージタイプのみを許可します。 ニーズが増えるにつれて、リストにメッセージタイプを追加できます。

これで、ほとんどのマシンに基本的な機能を提供する実用的なルールセットができました。 次のセクションでは、PFを有効にして予備のルールセットをテストすることにより、すべてが正しく機能していることを確認しましょう。

ステップ2—予備ルールセットをテストする

このステップでは、予備のルールセットをテストし、クラウドファイアウォールからPFファイアウォールに移行して、PFが完全に引き継ぐことができるようにします。 ルールセットは、PFの組み込みコマンドラインツールである pfctl ユーティリティ、およびPFとのインターフェイスの主要な方法を使用してアクティブ化します。

PFルールセットはテキストファイルにすぎません。つまり、新しいルールセットのロードに伴う繊細な手順はありません。 新しいルールセットをロードでき、古いルールセットはなくなります。 既存のルールセットをフラッシュする必要はほとんどありません。

FreeBSDは、 rcシステムと呼ばれるシェルスクリプトのWebを使用して、起動時にサービスを開始する方法を管理します。 これらのサービスをさまざまな形で指定します rc 構成ファイル。 PFなどのグローバルサービスの場合は、 /etc/rc.conf ファイル。 以来 rc ファイルはFreeBSDシステムの幸福にとって重要であり、直接編集しないでください。 代わりに、FreeBSDはとして知られているコマンドラインユーティリティを提供します sysrc これらのファイルを安全に編集できるように設計されています。

を使用してPFを有効にしましょう sysrc コマンドラインユーティリティ:

  1. sudo sysrc pf_enable="YES"
  2. sudo sysrc pflog_enable="YES"

の内容を印刷して、これらの変更を確認します /etc/rc.conf ファイル:

  1. sudo cat /etc/rc.conf

次の出力が表示されます。

Output
pf_enable="YES" pflog_enable="YES"

また、 pflog サービスは、順番に、 pflogd daemon for logging in PF. (You’ll work with logging in a later step.)

で2つのグローバルサービスを指定します /etc/rc.conf ファイルですが、サーバーを再起動するか手動で起動するまで初期化されません。 サーバーを再起動して、SSHアクセスもテストできるようにします。

サーバーを再起動してPFを開始します。

  1. sudo reboot

接続が切断されます。 更新するのに数分かかります。

次に、SSHでサーバーに戻ります。

  1. ssh freebsd@your_server_ip

PFサービスを初期化しましたが、実際にはロードしていません /etc/pf.conf ルールセット。これは、ファイアウォールがまだアクティブになっていないことを意味します。

ルールセットをロードする pfctl:

  1. sudo pfctl -f /etc/pf.conf

エラーやメッセージがない場合は、ルールセットにエラーがなく、ファイアウォールがアクティブになっていることを意味します。

PFが実行されたので、サーバーをクラウドファイアウォールから切り離すことができます。 Refer to your cloud provider to ensure that whatever you are using for temporary protection is disabled. サーバーで2つの異なるファイアウォールを実行すると、ほぼ確実に問題が発生します。

適切な方法として、サーバーを再起動します。

  1. sudo reboot

数分後、SSHでサーバーに戻ります。

  1. ssh freebsd@your_server_ip

これで、PFがファイアウォールとして機能します。 pfctlユーティリティーを使用していくつかのデータにアクセスすることにより、それが実行されていることを確認できます。

でいくつかの統計とカウンターを見てみましょう pfctl -si:

  1. sudo pfctl -si

あなたは合格します -si showinfoを表すフラグ。 これは、ファイアウォールアクティビティに関するデータを解析するためにpfctlで使用できる多くのフィルターパラメーターの組み合わせの1つです。

次の表形式のデータが表示されます(値はマシンごとに異なります)。

Output
Status: Enabled for 0 days 00:01:53 Debug: Urgent State Table Total Rate current entries 5 searches 144 1.3/s inserts 11 0.1/s removals 6 0.1/s Counters match 23 0.2/s bad-offset 0 0.0/s fragment 0 0.0/s short 0 0.0/s normalize 0 0.0/s memory 0 0.0/s bad-timestamp 0 0.0/s congestion 0 0.0/s ip-option 0 0.0/s proto-cksum 0 0.0/s state-insert 0 0.0/s state-limit 0 0.0/s src-limit 0 0.0/s synproxy 0 0.0/s map-failed 0 0.0/s

ルールセットをアクティブ化したばかりなので、まだ多くの情報は表示されません。 ただし、この出力は、PFがすでに23の一致したルールを記録したことを示しています。これは、ルールセットの基準が23回一致したことを意味します。 出力は、ファイアウォールが機能していることも確認します。

ルールセットは、pingユーティリティを含むインターネットからのいくつかの重要なサービスにアウトバウンドトラフィックがアクセスすることも許可します。

pingを使用してインターネット接続とDNSサービスを確認しましょう google.com:

  1. ping -c 3 google.com

カウントフラグを実行したので -c 3、3つの成功した接続応答が表示されます。

Output
PING google.com (172.217.0.46): 56 data bytes 64 bytes from 172.217.0.46: icmp_seq=0 ttl=56 time=2.088 ms 64 bytes from 172.217.0.46: icmp_seq=1 ttl=56 time=1.469 ms 64 bytes from 172.217.0.46: icmp_seq=2 ttl=56 time=1.466 ms --- google.com ping statistics --- 3 packets transmitted, 3 packets received, 0.0% packet loss round-trip min/avg/max/stddev = 1.466/1.674/2.088/0.293 ms

次のコマンドを使用して、pkgsリポジトリにアクセスできることを確認します。

  1. sudo pkg upgrade

アップグレードするパッケージがある場合は、先に進んでアップグレードしてください。

これらのサービスの両方が機能している場合は、ファイアウォールが機能していることを意味し、続行できます。 予備のルールセットは保護と機能を提供しますが、それでも基本的なルールセットであり、いくつかの拡張機能を使用できます。 残りのセクションでは、基本ルールセットを完成させ、PFの高度な機能のいくつかを使用します。

ステップ3—基本ルールセットを完成させる

このステップでは、予備ルールセットを構築して、基本ルールセットを完成させます。 ルールの一部を再編成し、より高度な概念で作業します。

マクロとテーブルの組み込み

予備のルールセットでは、すべてのパラメーターを各ルール、つまりリストを構成するポート番号にハードコーディングしました。 ネットワークの性質によっては、これは将来管理できなくなる可能性があります。 組織的な目的で、PFにはマクロリスト、およびテーブルが含まれています。 すでにルールに直接リストを含めていますが、それらをルールから分離し、マクロを使用して変数に割り当てることもできます。

ファイルを開いて、パラメータの一部をマクロに転送します。

  1. sudo vi /etc/pf.conf

次に、ルールセットの最上部に次のコンテンツを追加します。

/etc/pf.conf
vtnet0 = "vtnet0"
icmp_types = "{ echoreq }"
. . .

以前のSSHおよびICMPルールを新しい変数で変更します。

/etc/pf.conf
. . .
pass in on $vtnet0 proto tcp to port { 22 }
. . .
pass inet proto icmp icmp-type $icmp_types
. . .

以前のSSHおよびICMPルールはマクロを使用するようになりました。 変数名は、PFのドル記号構文で示されます。 あなたはあなたを割り当てます vtnet0 正式なものと同じ名前の変数へのインターフェース。これにより、必要に応じて将来名前を変更することができます。 公開インターフェースのその他の一般的な変数名には、次のものがあります。 $pub_if また $ext_if.

次に、 table を実装します。これは、 macro に似ていますが、IPアドレスのグループを保持するように設計されています。 サービス拒否攻撃(DOS)でしばしば役割を果たす、ルーティング不可能なIPアドレスのテーブルを作成しましょう。 RFC6890 で指定されたIPアドレスを使用できます。これは、専用のIPアドレスレジストリを定義します。 サーバーは、公開インターフェースを介してこれらのアドレスとの間でパケットを送受信しないでください。

次のコンテンツをすぐ下に追加して、このテーブルを作成します。 icmp_types 大きい:

/etc/pf.conf
. . .
table <rfc6890> { 0.0.0.0/8 10.0.0.0/8 100.64.0.0/10 127.0.0.0/8 169.254.0.0/16          \
                  172.16.0.0/12 192.0.0.0/24 192.0.0.0/29 192.0.2.0/24 192.88.99.0/24    \
                  192.168.0.0/16 198.18.0.0/15 198.51.100.0/24 203.0.113.0/24            \
                  240.0.0.0/4 255.255.255.255/32 }
. . .

次に、のルールを追加します <rfc6890> 下のテーブル set skip on lo0 ルール:

/etc/pf.conf
. . .
set skip on lo0
block in quick on egress from <rfc6890>
block return out quick on egress to <rfc6890>
. . .

ここで紹介します return あなたを補完するオプション block out ルール。 これにより、パケットがドロップされ、RSTメッセージがそれらの接続を試みたホストに送信されます。これはホストアクティビティの分析に役立ちます。 次に、 egress キーワード。任意のインターフェイスでデフォルトルートを自動的に検索します。 これは通常、特に複雑なネットワークでは、デフォルトルートを見つけるためのよりクリーンな方法です。 The quick キーワードは、残りのルールセットを考慮せずにルールをすぐに実行します。 たとえば、非論理的なIPアドレスを持つパケットがサーバーに接続しようとした場合、接続をすぐに切断する必要があり、そのパケットを残りのルールセットで実行する理由はありません。

SSHポートの保護

SSHポートは一般に公開されているため、悪用される可能性があります。 攻撃者のより明白な警告サインの1つは、大量のログイン試行です。 たとえば、同じIPアドレスが1秒間に10回サーバーにログインしようとした場合、それは人間の手ではなく、ログインパスワードを解読しようとしたコンピューターソフトウェアを使用して行われたと見なすことができます。 これらのタイプの体系的なエクスプロイトは、ブルートフォース攻撃と呼ばれることが多く、通常、サーバーのパスワードが弱い場合に成功します。

警告:すべてのサーバーで公開鍵認証を使用することを強くお勧めします。 キーベースの認証に関するDigitalOceanのチュートリアルを参照してください。

PFには、ブルートフォースやその他の同様の攻撃を処理するための機能が組み込まれています。 PFを使用すると、単一のホストで許可される同時接続試行の数を制限できます。 ホストがこれらの制限を超えると、接続が切断され、サーバーからの接続が禁止されます。 これを実現するには、禁止されているIPアドレスのテーブルを維持するPFのオーバーロードメカニズムを使用します。

次のように、以前のSSHルールを変更して、単一のホストからの同時接続の数を制限します。

/etc/pf.conf
. . .
pass in on $vtnet0 proto tcp to port { 22 } \
    keep state (max-src-conn 15, max-src-conn-rate 3/1, \
        overload <bruteforce> flush global)
. . .

追加します keep state 過負荷テーブルの状態基準を定義できるオプション。 あなたは合格します max-src-conn 1秒あたりの単一ホストから許可される同時接続の数を指定するパラメーター。 max-src-conn-rate 1秒あたりの単一ホストから許可される新しい接続の数を指定するパラメーター。 指定します 15 の接続 max-src-conn、 と 3 の接続 max-src-conn-rate. ホストがこれらの制限を超えた場合、 overload メカニズムはソースIPをに追加します <bruteforce> サーバーからそれらを禁止するテーブル。 最後に、 flush global オプションはすぐに接続を切断します。

SSHルールでオーバーロードテーブルを定義しましたが、ルールセットでそのテーブルを宣言していません。

追加します <bruteforce> 下のテーブル icmp_types 大きい:

/etc/pf.conf
. . .
icmp_types = "{ echoreq }"
table <bruteforce> persist
. . .

The persist キーワードを使用すると、ルールセットに空のテーブルを含めることができます。 これがないと、PFはテーブルにIPアドレスがないと文句を言います。

これらの対策により、SSHポートが強力なセキュリティメカニズムによって確実に保護されます。 PFを使用すると、悲惨な形の悪用から保護するための迅速なソリューションを構成できます。 次のセクションでは、パケットがサーバーに到着したときにパケットをクリーンアップする手順を実行します。

トラフィックのサニタイズ

注:次のセクションでは、TCP/IPプロトコルスイートの基本的な基本事項について説明します。 Webアプリケーションまたはネットワークの構築を計画している場合は、これらの概念を習得することが最も重要です。 DigitalOceanのネットワーク用語、インターフェイス、およびプロトコルの概要チュートリアルをご覧ください。

TCP / IPプロトコルスイートの複雑さと悪意のある攻撃者の忍耐力により、パケットは、IPフラグメントの重複、偽のIPアドレスなどの不一致やあいまいさを伴って到着することがよくあります。 トラフィックがシステムに入る前に、トラフィックをサニタイズすることが不可欠です。 このプロセスの専門用語は、正規化です。

データがインターネットを通過するとき、データは通常、ソースで小さなフラグメントに分割され、ターゲットホストの送信パラメータに対応し、完全なパケットに再構成されます。 残念ながら、侵入者はこのチュートリアルの範囲を超えるさまざまな方法でこのプロセスを乗っ取る可能性があります。 ただし、PFを使用すると、1つのルールで断片化を管理できます。 PFには scrub パケットを正規化するキーワード。

追加します scrub 直前のキーワード block all ルール:

/etc/pf.conf
. . .
set skip on lo0
scrub in all fragment reassemble max-mss 1440
block all
. . .

このルールは、すべての着信トラフィックにスクラビングを適用します。 あなたは fragment reassemble フラグメントがシステムに入るのを防ぐオプション。 代わりに、完全なパケットに再アセンブルされるまでメモリにキャッシュされます。つまり、フィルタルールは均一なパケットとのみ競合する必要があります。 また、 max-mss 1440 オプション。これは、ペイロードとも呼ばれる、再構成されたTCPパケットの最大セグメントサイズを表します。 サイズとパフォーマンスのバランスを取り、ヘッダー用に十分なスペースを残して、1440バイトの値を指定します。

断片化のもう1つの重要な側面は、最大伝送ユニット(MTU)として知られる用語です。 TCP / IPプロトコルを使用すると、デバイスは接続を確立するためにパケットサイズをネゴシエートできます。 ターゲットホストはICMPメッセージを使用して、ソースIPにMTUを通知します。これは、MTUパス検出と呼ばれるプロセスです。 特定のICMPメッセージタイプは、宛先到達不能です。 MTUパス探索を有効にするには、 unreach あなたへのメッセージタイプ icmp_types リスト。

サーバーのデフォルトのMTUである1500バイトを使用します。これは、 ifconfig 指図:

  1. ifconfig

現在のMTUを含む次の出力が表示されます。

Output
vtnet0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500 options=6c07bb<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,JUMBO_MTU,VLAN_HWCSUM,TSO4,TSO6,LRO,VLAN_HWTSO,LINKSTATE,RXCSUM_IPV6,TXCSUM_IPV6> . . .

を更新します icmp_types destination unreachable メッセージタイプを含めるリスト:

/etc/pf.conf
vtnet0 = "vtnet0"
icmp_types = "{ echoreq unreach}"
. . .

断片化を処理するためのポリシーが設定されたので、システムに入るパケットは均一で一貫性があります。 インターネットを介してデータを交換するデバイスが非常に多いため、これは望ましいことです。

ここで、IPスプーフィングと呼ばれる別のセキュリティ上の懸念を防ぐために作業します。 攻撃者は、ソースIPを変更して、組織内の信頼できるノードに存在するように見せかけることがよくあります。 PFには、スプーフィングされたソースIPを処理するためのantispoofingディレクティブが含まれています。 特定のインターフェイスに適用されると、スプーフィング防止は、そのインターフェイスのネットワークからのすべてのトラフィックをブロックします(そのインターフェイスから発信された場合を除く)。 たとえば、次の場所にあるインターフェイスにスプーフィング防止を適用する場合 5.5.5.1/24、からのすべてのトラフィック 5.5.5.0/24 ネットワークは、そのインターフェースから発信されていない限り、システムと通信できません。

次のハイライトされたコンテンツを追加して、スプーフィング防止を vtnet0 インターフェース:

/etc/pf.conf
. . .
set skip on lo0
scrub in
antispoof quick for $vtnet0
block all
. . .

ファイルを保存して終了します。

このなりすまし防止ルールは、 vtnet0のネットワークは、 vtnet0 インターフェイス、またはそれはすぐにドロップされます quick キーワード。 悪役は隠れることができなくなります vtnet0のネットワークと他のノードとの通信。

なりすまし防止ルールを示すために、ルールセットを詳細な形式で画面に印刷します。 PFのルールは通常、短縮形で記述されますが、冗長形式で記述されることもあります。 この方法でルールを作成することは一般的に実用的ではありませんが、テストの目的で役立つ場合があります。

の内容を印刷する /etc/pf.conf を使用して pfctl 次のコマンドを使用します。

  1. sudo pfctl -nvf /etc/pf.conf

これ pfctl コマンドは -nvf ルールセットを出力し、実際には何もロードせずにテストするフラグ。ドライランとも呼ばれます。 これで、の内容全体が表示されます。 /etc/pf.conf その冗長な形で。

なりすまし防止部分には、次のような出力が表示されます。

Output
. . . block drop in quick on ! vtnet0 inet from your_server_ip/20 to any block drop in quick on ! vtnet0 inet from network_address/16 to any block drop in quick inet from your_server_ip to any block drop in quick inet from network_address to any block drop in quick on vtnet0 inet6 from your_IPv6_address to any . . .

あなたのなりすまし防止ルールは、それがの一部であることを発見しました your_server_ip/20 通信網。 また、(このチュートリアルの例では)サーバーが network_address/16 ネットワーク、および追加のIPv6アドレスがあります。 スプーフィング防止は、トラフィックがシステムを通過しない限り、これらすべてのネットワークがシステムと通信するのをブロックします。 vtnet0 インターフェース。

なりすまし防止ルールは、基本ルールセットへの最後の追加です。 次のステップでは、これらの変更を開始し、いくつかのテストを実行します。

ステップ4—基本ルールセットをテストする

このステップでは、基本ルールセットを確認およびテストして、すべてが正しく機能していることを確認します。 テストせずに一度に多くのルールを実装することは避けるのが最善です。 ベストプラクティスは、基本事項から始めて、段階的に拡張し、構成を変更しながら作業をバックアップすることです。

完全な基本ルールセットは次のとおりです。

基本ルールセット/etc/pf.conf
vtnet0 = "vtnet0"
icmp_types = "{ echoreq unreach }"
table <bruteforce> persist
table <rfc6890> { 0.0.0.0/8 10.0.0.0/8 100.64.0.0/10 127.0.0.0/8 169.254.0.0/16          \
                  172.16.0.0/12 192.0.0.0/24 192.0.0.0/29 192.0.2.0/24 192.88.99.0/24    \
                  192.168.0.0/16 198.18.0.0/15 198.51.100.0/24 203.0.113.0/24            \
                  240.0.0.0/4 255.255.255.255/32 }

set skip on lo0
scrub in all fragment reassemble max-mss 1440
antispoof quick for $vtnet0
block in quick on $vtnet0 from <rfc6890>
block return out quick on egress to <rfc6890>
block all
pass in on $vtnet0 proto tcp to port { 22 } \
    keep state (max-src-conn 15, max-src-conn-rate 3/1, \
        overload <bruteforce> flush global)
pass out proto { tcp udp } to port { 22 53 80 123 443 }
pass inet proto icmp icmp-type $icmp_types

あなたの /etc/pf.conf 続行する前のファイルは、ここにある完全な基本ルールセットと同じです。 次に、ファイルを保存して終了します。

完全な基本ルールセットは、次のものを提供します。

次を実行します pfctl ドライランを実行するコマンド:

  1. sudo pfctl -nf /etc/pf.conf

あなたは合格します -nf 伝えるフラグ pfctl ルールセットをロードせずに実行します。これにより、何か問題がある場合にエラーがスローされます。

ここで、エラーが発生することなく、ルールセットをロードします。

  1. sudo pfctl -f /etc/pf.conf

エラーがない場合は、基本ルールセットがアクティブであり、正しく機能していることを意味します。 チュートリアルの前半と同様に、ルールセットに対していくつかのテストを実行します。

インターネット接続とDNSサービスの最初のテスト:

  1. ping -c 3 google.com

次の出力が表示されます。

Output
PING google.com (172.217.0.46): 56 data bytes 64 bytes from 172.217.0.46: icmp_seq=0 ttl=56 time=2.088 ms 64 bytes from 172.217.0.46: icmp_seq=1 ttl=56 time=1.469 ms 64 bytes from 172.217.0.46: icmp_seq=2 ttl=56 time=1.466 ms --- google.com ping statistics --- 3 packets transmitted, 3 packets received, 0.0% packet loss round-trip min/avg/max/stddev = 1.466/1.674/2.088/0.293 ms

次に、に到達することを確認します pkgs リポジトリ:

  1. sudo pkg upgrade

もう一度、必要に応じてパッケージをアップグレードします。

最後に、サーバーを再起動します。

  1. sudo reboot

サーバーを数分待ってから再起動します。 基本ルールセットを完成させて実装しました。これは、進捗状況の観点から重要なステップです。 これで、PFの高度な機能のいくつかを探索する準備が整いました。 次のステップでは、ブルートフォース攻撃を引き続き防止します。

ステップ5—過負荷テーブルの管理

時間の経過とともに <bruteforce> 過負荷テーブルは悪意のあるIPアドレスでいっぱいになり、定期的にクリアする必要があります。 攻撃者が同じIPアドレスを使用し続ける可能性は低いため、それらを過負荷テーブルに長期間保存することは直感に反します。

使用します pfctl 次のコマンドを使用して、過負荷テーブルに48時間以上保存されているIPアドレスを手動でクリアします。

  1. sudo pfctl -t bruteforce -T expire 172800

次のような出力が表示されます。

Output
0/0 addresses expired.

あなたは合格します -t bruteforce table bruteforce を表すフラグ、および -T フラグ。いくつかの組み込みコマンドを実行できます。 この場合、 expire からすべてのエントリをクリアするコマンド -t bruteforce 秒単位で表される時間値を使用します。 新しいサーバーで作業しているため、過負荷テーブルにはまだIPアドレスがない可能性があります。

このルールは迅速な修正に有効ですが、より堅牢な解決策は、FreeBSDのジョブスケジューラであるcronを使用してプロセスを自動化することです。 代わりに、このコマンドシーケンスを実行するシェルスクリプトを作成しましょう。

でシェルスクリプトファイルを作成します /usr/local/bin ディレクトリ:

  1. sudo vi /usr/local/bin/clear_overload.sh

次のコンテンツをシェルスクリプトに追加します。

/usr/local/bin/clear_overload.sh
#!/bin/sh

pfctl -t bruteforce -T expire 172800

次のコマンドを使用してファイルを実行可能にします。

  1. sudo chmod 755 /usr/local/bin/clear_overload.sh

次に、cronジョブを作成します。 これらは、指定した時間に従って繰り返し実行されるジョブです。 これらは通常、バックアップ、または毎日同時に実行する必要のあるプロセスに使用されます。 crontabファイルを使用してcronジョブを作成します。 cron(8)および crontab(5)の詳細については、マニュアルページを参照してください。

次のコマンドを使用して、rootユーザーのcrontabファイルを作成します。

  1. sudo crontab -e

次に、次の内容をcrontabファイルに追加します。

crontab
# minute	hour	mday	month	wday	command

  *				0     *       *     *	  /usr/local/bin/clear_overload.sh

ファイルを保存して終了します。

注:コンテンツを追加するときに物事が正しく整列しない場合は、読みやすくするために、すべての値を対応するテーブルエントリに整列させてください。

このcronジョブclear_overload.sh 毎日深夜にスクリプトを作成し、オーバーロードテーブルから48時間前のIPアドレスを削除します <bruteforce>. 次に、ルールセットにアンカーを追加します。

ステップ6—ルールセットにアンカーを導入する

このステップでは、アンカーを紹介します。これは、手動または外部テキストファイルからメインルールセットにルールをソーシングするために使用されます。 アンカーには、ルールスニペット、テーブル、さらにはネストされたアンカーと呼ばれる他のアンカーを含めることができます。 テーブルを外部ファイルに追加し、それを基本ルールセットにソースすることによって、アンカーがどのように機能するかを示しましょう。 テーブルには、外部への接続を防止する内部ホストのグループが含まれます。

名前の付いたファイルを作成します /etc/blocked-hosts-anchor:

  1. sudo vi /etc/blocked-hosts-anchor

次の内容をファイルに追加します。

/ etc /blocked-hosts-anchor
table <blocked-hosts> { 192.168.47.1 192.168.47.2 192.168.47.3 }

block return out quick on egress from <blocked-hosts>

ファイルを保存して終了します。

これらのルールは、 <blocked-hosts> テーブルを作成し、次のすべてのIPアドレスを防止します。 <blocked-hosts> 外の世界からサービスにアクセスすることからのテーブル。 あなたは egress インターネットへのデフォルトルートまたは出口を見つけるための好ましい方法としてのキーワード。

あなたはまだあなたの中でアンカーを宣言する必要があります /etc/pf.conf ファイル:

  1. sudo vi /etc/pf.conf

次に、次のアンカールールを追加します。 block all ルール:

/etc/pf.conf
. . .
block all
anchor blocked_hosts
load anchor blocked_hosts from "/etc/blocked-hosts-anchor"
. . .

ファイルを保存して終了します。

これらのルールは、 blocked_hosts からアンカールールをメインルールセットにロードします /etc/blocked-hosts-anchor ファイル。

次に、ルールセットをでリロードして、これらの変更を開始します。 pfctl:

  1. sudo pfctl -f /etc/pf.conf

エラーがない場合は、ルールセットにエラーがなく、変更がアクティブであることを意味します。

使用する pfctl アンカーが実行されていることを確認するには:

  1. sudo pfctl -s Anchors

The -s Anchors フラグは「アンカーの表示」を表します。 次の出力が表示されます。

Output
blocked_hosts

The pfctl ユーティリティは、アンカーの特定のルールを解析することもできます。 -a-s フラグ:

  1. sudo pfctl -a blocked_hosts -s rules

次の出力が表示されます。

Output
block return out quick on egress from <blocked-hosts> to any

アンカーのもう1つの機能は、ルールセットをリロードしなくても、オンデマンドでルールを追加できることです。 これは、テスト、クイックフィックス、緊急事態などに役立ちます。 たとえば、内部ホストが特殊な動作をしていて、外部接続をブロックしたい場合は、コマンドラインからすばやく介入できるアンカーを配置できます。

開けましょう /etc/pf.conf そして別のアンカーを追加します:

  1. sudo vi /etc/pf.conf

アンカーに名前を付けます rogue_hosts、そしてそれを block all ルール:

/etc/pf.conf
. . .
block all
anchor rogue_hosts
. . .

ファイルを保存して終了します。

これらの変更を開始するには、ルールセットを次のようにリロードします。 pfctl:

  1. sudo pfctl -f /etc/pf.conf

もう一度、使用します pfctl アンカーが実行されていることを確認するには:

  1. sudo pfctl -s Anchors

これにより、次の出力が生成されます。

Output
blocked_hosts rogue_hosts

アンカーが実行されているので、いつでもアンカーにルールを追加できます。 次のルールを追加して、これをテストします。

  1. sudo sh -c 'echo "block return out quick on egress from 192.168.47.4" | pfctl -a rogue_hosts -f -'

これにより、 echo コマンドとその文字列の内容は、 pfctl ユーティリティと | シンボル。アンカールールに処理されます。 で別のシェルセッションを開きます sh -c 指図。 これは、2つのプロセス間にパイプを確立するためですが、 sudo コマンドシーケンス全体を通して持続する特権。 これを解決するには複数の方法があります。 ここでは、を使用してsudo権限で追加のシェルプロセスを開きます sudo sh -c.

今、使用します pfctl これらのルールがアクティブであることを再度確認するには、次のようにします。

  1. sudo pfctl -a rogue_hosts -s rules

これにより、次の出力が生成されます。

Output
block return out quick on egress inet from 192.168.47.4 to any

アンカーの使用は完全に状況に応じて行われ、多くの場合主観的です。 他の機能と同様に、アンカーを使用することには賛否両論があります。 blacklistd などの一部のアプリケーションは、設計上アンカーとインターフェースします。 次に、ネットワークセキュリティの重要な側面であるPFを使用したロギングに焦点を当てます。 ファイアウォールが何をしているのかがわからない場合、ファイアウォールは役に立ちません。

ステップ7—ファイアウォールのアクティビティをログに記録する

このステップでは、PFロギングを使用します。これは、という名前の疑似インターフェイスによって管理されます。 pflog. 追加することにより、起動時にロギングが有効になります pflog_enabled=YES/etc/rc.conf 手順2で行ったファイル。 これにより、pflogdデーモンが有効になります。 pflog0 ログをバイナリ形式でという名前のファイルに書き込みます /var/log/pflog. ログは、インターフェイスからリアルタイムで解析するか、 /var/log/pflog tcpdump(8)ユーティリティを使用したファイル。

まず、からいくつかのログにアクセスします /var/log/pflog ファイル:

  1. sudo tcpdump -ner /var/log/pflog

あなたは合格します -ner 読みやすくするために出力をフォーマットし、読み取るファイルを指定するフラグ。この場合は次のようになります。 /var/log/pflog.

次の出力が表示されます。

Output
reading from file /var/log/pflog, link-type PFLOG (OpenBSD pflog file)

これらの初期段階では、データがない可能性があります /var/log/pflog ファイル。 短期間で、ログファイルが大きくなり始めます。

からリアルタイムでログを表示することもできます pflog0 次のコマンドを使用してインターフェイスします。

  1. sudo tcpdump -nei pflog0

あなたは合格します -nei フラグ。読みやすくするために出力もフォーマットしますが、今回はインターフェースを指定します。 pflog0.

次の出力が表示されます。

Output
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on pflog0, link-type PFLOG (OpenBSD pflog file), capture size 262144 bytes

これで、接続がリアルタイムで表示されます。 可能であれば、リモートマシンからサーバーにpingを実行すると、接続が発生していることがわかります。 サーバーを終了するまで、サーバーはこの状態のままになります。

この状態を終了してコマンドラインヒットに戻るには CTRL + Z.

tcpdump(8)については、公式の Webサイトを含め、インターネット上に豊富な情報があります。

pftopを使用したログファイルへのアクセス

The pftop ユーティリティは、ファイアウォールのアクティビティをリアルタイムですばやく表示するためのツールです。 その名前は有名なUnixの影響を受けています top 効用。

使用するには、をインストールする必要があります pftop パッケージ:

  1. sudo pkg install pftop

今実行します pftop バイナリ:

  1. sudo pftop

これにより、次の出力が生成されます(IPは異なります)。

Output
PR DIR SRC DEST STATE AGE EXP PKTS BYTES tcp In 251.155.237.90:27537 157.225.173.58:22 ESTABLISHED:ESTABLISHED 00:12:35 23:59:55 1890 265K tcp In 222.186.42.15:25884 157.225.173.58:22 TIME_WAIT:TIME_WAIT 00:01:25 00:00:06 22 3801 udp Out 157.245.171.59:4699 67.203.62.5:53 MULTIPLE:SINGLE 00:00:14 00:00:16 2 227

追加のログインターフェイスの作成

他のインターフェースと同様に、複数のログインターフェースを作成し、 /etc/hostname ファイル。 これは、特定の種類のアクティビティを個別にログに記録する場合など、組織的な目的に役立つ場合があります。

名前の付いた追加のログインターフェイスを作成します pflog1:

  1. sudo vi /etc/hostname.pflog1

次の内容をに追加します /etc/hostname.pflog1 ファイル:

/etc/hostname.pflog1
up

次に、起動時にデバイスを有効にします /etc/rc.conf ファイル:

  1. sudo sysrc pflog1_enable="YES"

これで、ファイアウォールアクティビティを監視およびログに記録できます。 これにより、サーバーに接続しているユーザーと接続の種類を確認できます。

このチュートリアル全体を通して、いくつかの高度な概念をPFルールセットに組み込んでいます。 必要に応じて高度な機能を実装するだけで済みます。 そうは言っても、次のステップでは、基本ルールセットに戻ります。

ステップ8—基本ルールセットに戻す

この最後のセクションでは、基本ルールセットに戻ります。 これは、機能の最小限の状態に戻るための簡単な手順です。

次のコマンドで基本ルールセットを開きます。

  1. sudo vi /etc/pf.conf

ファイル内の現在のルールセットを削除し、次の基本ルールセットに置き換えます。

/etc/pf.conf
vtnet0 = "vtnet0"
icmp_types = "{ echoreq unreach }"
table <bruteforce> persist
table <rfc6890> { 0.0.0.0/8 10.0.0.0/8 100.64.0.0/10 127.0.0.0/8 169.254.0.0/16          \
                  172.16.0.0/12 192.0.0.0/24 192.0.0.0/29 192.0.2.0/24 192.88.99.0/24    \
                  192.168.0.0/16 198.18.0.0/15 198.51.100.0/24 203.0.113.0/24            \
                  240.0.0.0/4 255.255.255.255/32 }

set skip on lo0
scrub in all fragment reassemble max-mss 1440
antispoof quick for $vtnet0
block in quick on $vtnet0 from <rfc6890>
block return out quick on egress to <rfc6890>
block all
pass in on $vtnet0 proto tcp to port { 22 } \
    keep state (max-src-conn 15, max-src-conn-rate 3/1, \
        overload <bruteforce> flush global)
pass out proto { tcp udp } to port { 22 53 80 123 443 }
pass inet proto icmp icmp-type $icmp_types

ファイルを保存して終了します。

ルールセットをリロードします。

  1. sudo pfctl -f /etc/pf.conf

コマンドからのエラーがない場合、ルールセットにエラーはなく、ファイアウォールは正しく機能しています。

また、を無効にする必要があります pflog1 作成したインターフェース。 まだ必要かどうかわからない場合があるため、無効にすることができます pflog1 とともに sysrc 効用:

  1. sudo sysrc pflog1_enable="NO"

次に、 /etc/hostname.pflog1 からのファイル /etc ディレクトリ:

  1. sudo rm /etc/hostname.pflog1

サインオフする前に、サーバーをもう一度再起動して、すべての変更がアクティブで永続的であることを確認します。

  1. sudo reboot

サーバーにログインする前に、数分待ちます。

オプションで、WebサーバーでPFを実装する場合、このシナリオのルールセットは次のとおりです。 このルールセットは、ほとんどのWebアプリケーションにとって十分な出発点です。

シンプルなWebサーバールールセット
vtnet0 = "vtnet0"
icmp_types = "{ echoreq unreach }"
table <bruteforce> persist
table <webcrawlers> persist
table <rfc6890> { 0.0.0.0/8 10.0.0.0/8 100.64.0.0/10 127.0.0.0/8 169.254.0.0/16          \
                  172.16.0.0/12 192.0.0.0/24 192.0.0.0/29 192.0.2.0/24 192.88.99.0/24    \
                  192.168.0.0/16 198.18.0.0/15 198.51.100.0/24 203.0.113.0/24            \
                  240.0.0.0/4 255.255.255.255/32 }

set skip on lo0
scrub in all fragment reassemble max-mss 1440
antispoof quick for $vtnet0
block in quick on $vtnet0 from <rfc6890>
block return out quick on egress to <rfc6890>
block all
pass in on $vtnet0 proto tcp to port { 22 } \
    keep state (max-src-conn 15, max-src-conn-rate 3/1, \
        overload <bruteforce> flush global)
pass in on $vtnet0 proto tcp to port { 80 443 } \
    keep state (max-src-conn 45, max-src-conn-rate 9/1, \
        overload <webcrawlers> flush global)
pass out proto { tcp udp } to port { 22 53 80 123 443 }
pass inet proto icmp icmp-type $icmp_types

これにより、という名前のオーバーロードテーブルが作成されます <webcrawlers>、の値に基づいて、SSHポートよりも寛大な過負荷ポリシーがあります max-src-conn 45max-src-conn-rate. これは、すべてのオーバーロードが悪意のあるアクターによるものではないためです。 また、悪意のないネットボットから発生する可能性があるため、ポートでの過度のセキュリティ対策を回避できます 80443. Webサーバーのルールセットを実装する場合は、 <webcrawlers> テーブルに /etc/pf.conf、および定期的にテーブルからIPをクリアします。 これについては、ステップ5を参照してください。

結論

このチュートリアルでは、FreeBSD12.1でPFを設定しました。 これで、すべてのFreeBSDプロジェクトの開始点として機能できる基本ルールセットができました。 PFの詳細については、 pf.conf(5)のマニュアルページを参照してください。

私たちをご覧ください FreeBSDトピックページその他のチュートリアルとQ&Aについては。

モバイルバージョンを終了