- NFQUEUE により、Netfilter はフィルタリングとマーキングの決定をユーザー空間プロセスに委任できるようになり、動的な IP ファイアウォールとルーターが可能になります。
- Suricata は、NFQUEUE、AF_PACKET、および Snort および Emerging Threats と互換性のあるルールをサポートするマルチプロセス IDS/IPS エンジンを提供します。
- NFQUEUE を Suricata、データベース、Memcached、または Pfsense と統合すると、無料のソフトウェアで高度なセキュリティおよびルーティング ソリューションを構築できます。
- パフォーマンスはスレッドの設計とユーザー空間のロジックに大きく依存するため、検査するトラフィックを最適化し、慎重に選択することが重要になります。
GNU/Linux(セキュリティとプライバシーに最適なLinuxディストリビューション)上でネットワークを扱っていて、一般的な静的ファイアウォールを超えた機能に興味があるなら、Netfilter、NFQUEUE、Suricataを組み合わせて、高額な専用ハードウェアに費用をかけずに真に柔軟なIDS/IPSを構築する方法に興味があるでしょう。この記事ではまさにその点を探り、低レベル要素(カーネル、キュー、C言語)と高レベルツール(Suricata、ルール、MySQL、Memcached、pfSense)を組み合わせる方法を解説します。
根底にある考え方は非常に強力です。カーネル(Linuxカーネルの最適化方法を参照)がパケットをユーザー空間にキューイングし、カスタムプログラムがそれらをどう処理するかを決定できるという事実を活用するのです。これは、トラフィックフィルタリング(高度なファイアウォール、IPS)、動的ルーティング、またはビジネスロジックの統合(データベース、キャッシュ、Webアプリケーション攻撃検出、VoIPなど)に使用できます。さらに、マルチプロセスIDS/IPSエンジンとしてSuricataを追加すれば、ラボ環境から高トラフィックのデータセンターまで、あらゆる環境に対応できる非常に堅牢な組み合わせが実現します。
NFQUEUE と Netfilter: ファイアウォールをユーザー空間に昇格
一般的なGNU/Linuxシステムでは、Netfilter/iptables(またはnftables)ルールは通常、カーネル空間に完全に存在する静的ポリシーとして使用されます。フロントエンドやアプライアンス(NetfilterやBSDのPacket Filterをベースにした多くのソリューションを含む)は、設定をテキスト、XML、またはSQLiteファイルに保存し、何らかの変更があった場合はルールを再生成して再読み込みします。これは柔軟性がありますが、ロジックはファイアウォールのスナップショットのようなもので、わずかな動的な調整(1秒あたりの接続制限、conntrack、国別マッチング、レイヤー7が利用可能な場合など)が加えられるだけです。
NFQUEUEが提案するのは、まさにゲームチェンジャーです。カーネルが常に最終決定を下すのではなく、その決定をユーザープロセスに委任できるのです。カーネルはパケットを番号付きキューに格納し、libnetfilter_queueライブラリを使用するアプリケーションがそれを取得、分析し、承認、破棄、あるいはポリシールーティングの対象としてマークするなど、判定結果を返します。これは、ファイアウォールの上にC、Python、またはPerlで書かれたプログラム可能な「裁判官」がいるようなものです。
このシステムの素晴らしい点は、カーネルに応答する前に、/dev/urandom、データベース、Webサービス、分散キャッシュ、あるいは高度なアルゴリズムなど、文字通りあらゆる操作をプログラムで実行できることです。アーキテクチャの観点から見ると、ファイアウォールは単なる静的なルールの集合体ではなく、Netfilter、キュー、ユーザーアプリケーションがパズルのピースのように組み合わさるパイプラインへと進化します。
NFQUEUEは2つの部分から構成されています。1つはiptables内のNFQUEUEターゲットで、パケットを特定のキューに送信します。もう1つはlibnetfilter_queueユーザーライブラリで、これらのパケットを読み取って判定を下すことができます。これはtcpdumpのような単純なパケットスニファとは異なり、パケットがたどる経路を直接決定する機能を備えています。
NFQUEUEを使用した基本的なiptables設定
iptablesの観点から見ると、NFQUEUEの使用は非常に簡単です。特定の条件(送信元/宛先IP、ポート、状態、GeoIPやlayer7などの追加モジュールが利用可能な場合など)を満たすパケットをキューに送信するルールを、対象のチェーンに追加します。
たとえば、ホスト自体に到着したすべての ping を NFQUEUE に送信する場合は、次のようにします。
iptables -I 入力 -p icmp -j NFQUEUE
これは、特に指定がない限り、受信した ICMP パケットをキュー 0 に送信します。` --queue-num 3`のように別のキューを指定することもできます。カウンター付きルール一覧 (`iptables -L -n -v -x`) を実行すると、カウンターが増加し、パケットがキューに格納されていることがわかります。重要な詳細として、キューにパケットがあり、ユーザー プロセスがそれらを取得して処理しない場合、デフォルトの動作ではパケットが拒否されるため、設計上、アプリケーションの障害が発生するとトラフィックがブロックされます。
libnetfilter_queue を使ったプログラミング: C言語の「Hello World」
ユーザー空間からキューに参加するには、libnetfilter_queueライブラリを使用します(このライブラリはlibnfnetlinkに依存しています)。Debianなどのディストリビューションでは、開発パッケージをインストールするだけで済みます。
apt-get で libnfnetlink-dev と libnetfilter-queue-dev をインストールします。gcc
常にパケットを受け入れる最小限のプログラムの骨組みは、いくつかの非常に明確な手順で構成されています。ライブラリを開き、既存のハンドラをすべてバインド解除し、AF_INETプロトコルにバインドし、コールバック関数を使用してキューを作成し、コピーモードを定義し、受信ループに入ります。コールバックはキューに入れられた各パケットに対して実行され、IDを抽出して判定結果を返します。
実際の流れは次のようになります。`nfq_open`でハンドルを取得し、`nfq_unbind_pf`でハンドルを解放し、`nfq_bind_pf`でAF_INETに関連付け、`nfq_create_queue`でコールバックをキュー0に登録し、`nfq_set_mode`でメタデータかパケット全体かを指定し、`recv()`でディスクリプタをループ処理し、`nfq_handle_packet`で各パケットを処理します。終了時には、`nfq_destroy_queue`でキューを破棄し、`nfq_close`でハンドルを閉じます。
このタイプの「Hello World」は、NFQUEUEの影響を明確に測定できます。この例を次のようにコンパイルすると、
gcc -o nftest code.c -lnfnetlink -lnetfilter_queue
iperf からトラフィックをキューイングすると (例えば、INPUT と OUTPUT で TCP ポート 5001 を使用)、パケットを単純に受け入れるだけのコードはギガビット ネットワークのパフォーマンスにほとんど影響を与えないことがわかります。ただし、重要な点があります。コールバックで情報を出力する (printf、fflush など) と、スループットが大幅に低下します。これは、画面デバッグありとなしの iperf を比較するとわかります。
高度な NFQUEUE オプション: バイパス、バランス、フェイルオープン
NFQUEUEには、キューのデフォルトの動作を変更する興味深いiptablesオプションがいくつか組み込まれており、ユーザーアプリケーションの障害やキューの満杯の処理方法に影響するため、本番環境や高性能環境に入る前に知っておく必要があります。
`--queue-bypass`コマンドを使用すると、キューをリッスンしているプロセスがない場合でも、パケットが破棄されずに iptables チェーンの次のホップに転送されるように設定できます。これは、ユーザーサービスが利用できない場合にシステムを「フェイルオープン」させたい場合に役立ちますが、セキュリティの観点からは諸刃の剣と言えます。
`--queue-balance`オプションを使用すると、パケットを複数のキュー(たとえば、0~3)に分散させ、各キューから複数の独立したプロセスまたはスレッドがパケットを消費するように設定できます。Netfilter のコードは、同じフローからのパケットが常に同じキューに格納されるように設計されているため、判断ロジックの一貫性を維持するのが非常に簡単になります。
また、 `--fail-open`モードというオプションもあり、これはユーザープロセスの実行速度が遅すぎてキューがいっぱいになった場合の動作を制御します。このオプションを有効にすると、カーネルはパケットを破棄する代わりに直接受け入れるため、大規模なトラフィックの中断を防ぐことができます。ただし、これもセキュリティ上の問題となる可能性があります。なぜなら、ケースバイケースで判断を下したい場合、判断パケットが失われると、その目的を達成できなくなるからです。
キューの状況を監視するために、Netfilter は擬似ファイルシステム/proc/net/netfilter/nfnetlink_queueに情報を公開しており、スクリプトや監視ツールから簡単に照会できます。
ビジネスロジックの統合: Memcached と MySQL を使用したテスト
「ハローワールド」プロセスが制御可能になったら、次の自然なステップは、コールバック関数に外部システムへの呼び出しを追加することです。典型的な実験では、送信元IPアドレスがMySQLデータベースやMemcachedキャッシュなどのバックエンドに存在するかどうかに基づいて、パケットを受け入れるか拒否するかを決定します。
Memcached の場合、デーモンがインストールされ (apt-get install memcached)、たとえばauthorized というキーに目的の IP アドレスがロードされます。これは、簡単な echo と netcat を使用して実行でき、その後 get コマンドで値が正しく保存されていることを確認できます。そこから、NFQUEUE プログラムは、パケット ID を取得するだけでなく、NFQNL_COPY_PACKETを使用してパケット全体を受信し、IP ヘッダー (struct iphdr) を抽出し、inet_ntop を使用して送信元アドレスを文字列に変換します。
パケットごとに接続を開く時間を節約するため、Memcached接続はメインメソッド(memcached_create、memcached_server_list_append、memcached_server_push)で一度だけ初期化され、ハンドラはグローバル変数に格納されます。コールバックでは、目的のキーを使用してmemcached_getが呼び出され、送信元IPアドレスが取得値と比較されます。一致すればNF_ACCEPTが返され、一致しない場合はNF_DROPが返されます。キーが存在しない場合、またはエラーが発生した場合は、保守的なポリシーとしてパケットは破棄されます。
iperf を使用した場合、この戦略ではギガビットネットワーク上でスループットが約 140 Mbit/sに低下し、キューでパケット損失が発生し始めることが確認されています (例えば、コード内の記号で示されています)。言い換えれば、パケットごとにキャッシュサービスを呼び出すだけでもかなりのコストがかかりますが、最適化すれば中程度のトラフィック量であれば実行可能です。
MySQLの場合、手順は似ていますが、より複雑です。サーバーライブラリとクライアントライブラリをインストールし、authorized(ip varchar(50))というシンプルなテーブルを持つデータベース(例えばnfqueue)を作成し、許可されたIPアドレスを挿入します。プログラムでは、起動時に`mysql_init`と`mysql_real_connect`が実行され、コールバック内で`select * from authorized where ip like 'xxxx'`のようなクエリが構築されます。クエリが正常に実行され、行が見つかった場合はパッケージが受け入れられ、そうでない場合は破棄されます。
MySQLのクエリキャッシュを有効にした場合、テスト結果は約188 Mbit/sとなり、クエリキャッシュを無効にすると103 Mbit/sに低下します。これらの数値はギガビットには遠く及びませんが、最も洗練されていないアプローチ(シングルスレッド、最適化なし)であっても、データベース駆動型またはキャッシュベースの判断を用いることで、相当量のトラフィックを処理できることを示しています。
パフォーマンス、マルチスレッド、CPU使用率
iperf、Memcached、MySQL を用いたテストでは、パフォーマンスの上限は NFQUEUE 自体よりも、ユーザー空間に追加するロジックとその実装方法によって大きく左右されることが明確に示されています。NF_ACCEPT を返すだけの実行ファイルであれば、1 ギガビット近いスループットを難なく達成できます。しかし、I/O やネットワーク呼び出しを導入すると、スループットは低下し、NFQUEUE マシン、Memcached デーモン、または MySQL の CPU は限界に達します。
アーキテクチャの観点から見ると、これには2つの意味があります。1つは、トラフィック量が多い場合、ファイアウォールの判断をユーザーアプリケーションに委任することが、各呼び出しの実際のコストを考慮すれば十分に実現可能であることを裏付けています。もう1つは、プラットフォームの最大機能を引き出すには、マルチスレッドまたはマルチプロセッシングを検討する必要があることを示しています。NFQUEUEを使用すると、トラフィックを複数のキューに分散できます。アプリケーションの複数のコピーを起動し、それぞれが異なるキューをリッスンすることで、pthreadsや大規模なフォークの手間をかけずに、複数のコアを活用できます。
もう1つの明らかな最適化は、NFQUEUEを通過するトラフィックを制限することです。テストではiperfフロー全体がキューイングされていましたが、実際のシナリオでは、NEW状態のパケットのみをキューイングし、ESTABLISHED/RELATED状態のパケットは通過させ、高負荷なロジックはログインや疑わしいパターンに限定することができます。
最終的には、CPU の使用率とスレッド設計が鍵となります。ユーザー プロセスが不足すると、キューがいっぱいになり、フェールオープンやドロップの受け入れなどの手段に頼らざるを得なくなり、このアプローチが目指す細かい制御の一部が失われます。
Netfilterブランドのダイナミックルーティング
NFQUEUEは単に「受け入れる」または「破棄する」という指示を出すだけにとどまりません。パケットにNetfilter(fwmark)フラグを適用し、ip ruleやiproute2と組み合わせることで、非常に柔軟で軽量なVRFスタイルの政治的ルーティング方式を構築することも可能です。
手順は、大まかに言うと次のようになります。/etc/iproute2/rt_tables にいくつかのルーティング テーブル (たとえば slow と fast) を定義します。各テーブルに異なるデフォルト ルート (1 つはファイバー経由、もう 1 つはより制限されたリンク経由) を割り当てます。ip ルールを使用して、fwmark 1 のパケットは fast テーブルに、fwmark 2 のパケットは slow テーブルに送られるように指定します。最後に、NFQUEUE を使用してパケットを適切にマークしてから、判定を返します。
コールバックから判定を設定するには、 `nfq_set_verdict2`を使用します。これは `nfq_set_verdict` と同様ですが、`ip rule` が参照する判定値を設定できます。これらすべてを組み合わせることで、偶数/奇数パケットサイズのようなばかげたものから、トラフィック予測アルゴリズム、ソーシャルメディアイベント、監視システムからの信号などの外部入力まで、任意の基準に基づいてルーティング先を決定する IP ルーターを構築できます。
その結果、カーネルは通常の速度でパケットを転送し続けるものの、各フローがたどる正確な経路は外部ソフトウェアに委ねられ、そのソフトウェアは静的なルールに手を加えることなくリアルタイムで変更を行うことができるシステムとなる。
NFQUEUE と Suricata: GNU/Linux の高レベル IPS
上記すべてはC言語で手動でプログラミングできますが、侵入検知やディープパケットインスペクションに関しては、成熟したIDS/IPSエンジンに頼るのが賢明な選択肢となるのが一般的です。そこで登場するのがSuricataです。SuricataはまさにSnortのマルチプロセス版として誕生し、当初からIPS機能を備え、現在利用可能な多数のCPUコアを最大限に活用することに重点を置いています。
Suricataはゼロから開発され、GPLv2ライセンスの下で配布されています。Open Information Security Foundation(OISF)は、エンジンと、ルールやドキュメントを含むかなり包括的なエコシステムの両方を維持管理しています。シングルスレッドのコアを継承し、そこにパッチを適用したSnort 2.xとは異なり、Suricataは、キャプチャ、デコード、検出、出力といった複数のスレッドにワークロードを分散させ、それぞれ異なる負荷分散戦略を用いるように設計されています。
機能面では、SuricataはIPv6、レイヤー7インスペクション(HTPライブラリによる高度なHTTP)、ポートに依存しないプロトコル認識、フロー再構築、および複数のTCP接続にまたがる攻撃のさまざまな段階を関連付けるための非常に強力なセッション変数(フロービット)システムをネイティブにサポートしています。
もう一つの強みは、Snortルールとの互換性、そしてSourcefire VRTとEmerging Threatsのシグネチャセット(無料のET Openと商用のET Pro)の両方を使用できる点です。さらに、SIEM、ELK、Splunkなどのシステムとの連携を容易にするため、イベントを非常に便利な形式(fast.log、eve.json形式のJSON)でエクスポートします。
Linux の IPS としての Suricata: キャプチャモードと NFQUEUE
GNU/Linux 上では、Suricata はトラフィックの傍受方法に応じて、NFQUEUE、AF_PACKET、PF_RING、libpcap、NFLOG、IPFW、DAG、Napatechなど、さまざまなモードで動作できます。それぞれに利点と要件があります。純粋な IPS レベルでは、NFQUEUE と AF_PACKET が最も重要です。
NFQ(NFQUEUE)モードでは、処理の流れは前述のものと同様です。一連のiptablesルールがパケットをキューに送信し、ユーザー空間で動作するSuricataがそのキューからパケットを読み取り、ルールに従って内容を検査し、NF_ACCEPT、NF_DROP、またはNF_REPEATのいずれかの判定をカーネルに返します。3番目のNF_REPEATは、追加のマークや変更を加えた後、パケットを同じiptablesテーブルに再挿入するために使用できます。
このモードは非常に柔軟で、既存のインフラストラクチャに簡単に実装できます。なぜなら、特定の箇所(例えば、FORWARD、INPUT、OUTPUT)のルールを変更するだけで、それ以外はそのままにしておくことができるからです。ただし、NFQUEUEを介してパケットを送受信する際のオーバーヘッドが増加するというデメリットがあり、特にパケット量が非常に多い場合や、ルールがリソースを大量に消費する場合は、前述のような影響が出ます。
AF_PACKETモードでは、Suricataはネットワークインターフェースに近い場所で動作し、AF_PACKETソケット間でパケットをコピーします。これははるかに高速なゼロコピー方式ですが、システムが2つのインターフェースを持つゲートウェイとして機能し、トラフィックのブロックがNIC間の転送レベルで実行される必要があります。つまり、ブロック対象のパケットは入力インターフェースから出力インターフェースに渡されません。
どちらのモードでも、SuricataはNetfilterと組み合わせることができますが、NFQUEUEは、iptablesのロジック(ポリシー、範囲、以前のルール)をすべて再利用し、詳細な検査が必要なトラフィックのみをSuricataに送信したいシナリオに特に適しています。
ソースコードからのSuricataの基本インストール
パッケージを使用する代わりに Suricata をコンパイルすることを好むユーザーの場合、Debian/Ubuntu タイプのディストリビューションでの手順は、まずコンパイル依存関係 (build-essential、libpcre、libpcap-dev、libnet-dev、libyaml-dev、zlib、libcap-ng-dev、libjansson-dev など) をインストールし、公式 Web サイトから tarball をダウンロードし、従来の ./configure、make、make install を実行することです。
設定フェーズでは、スクリプトが有効になっているサポート機能(AF_PACKET 有効/無効、PF_RING、NFQUEUE 有効/無効、NFLOG、IPFW、libnss、libjansson、Prelude、PCRE JIT、Lua、GeoIP など)が表示されます。NFQUEUEモードで作業する場合は、NFQUEUE が有効になっていること、および目的のキャプチャライブラリが見つかることを確認することが重要です。
バイナリをインストールした後、`make install-conf`を実行してデフォルト設定を`/etc/suricata`にデプロイし、`make install-rules`を実行してEmerging Threatsルールセットをダウンロードして`/etc/suricata/rules`に配置することができます。これらのルールセットは、`suricata-update`などのツールを使用して更新できます。
Red Hat/CentOS システムでは、ロジックは同様で、依存関係 (libpcap-devel、pcre-devel、libnet-devel、libyaml-devel、jansson-devel など) には yum または dnf を使用し、同じ手順でコンパイルします。パフォーマンス上の理由から、 ethtool を使用してキャプチャ インターフェイスで LRO/GRO を無効にすることも推奨されます。これらのオフロード機能は、IDS レベルでのパッケージの可視性に影響を与える可能性があるためです。
Suricata の設定: YAML、変数、スレッド
Suricata の主要な設定ファイルは/etc/suricata/suricata.yamlにあります。これは読みやすく、コメントが豊富に記述された YAML ファイルで、ログパスやルールセットから、ターゲットとなるオペレーティングシステムのポリシーやスレッドパラメータまで、あらゆるものが定義されています。
基本的なフィールドの 1 つは`default-log-dir`で、ログ ファイルの保存場所を指定します (デフォルトでは `/var/log/suricata`)。`vars` セクションには、`HOME_NET`、`EXTERNAL_NET`、`HTTP_PORTS`、`SHELLCODE_PORTS`、`SSH_PORTS` などの変数があり、これらはルール内で略語として使用されます。`HOME_NET` は通常、保護したいローカル ネットワークの範囲で設定され、`EXTERNAL_NET` は通常 `!HOME_NET` として定義されます。
もう一つ重要な部分は、ホストOSポリシーです。これは、Suricataがどのオペレーティングシステムで特定のIPアドレス範囲を実行するかを指示するものです。これにより、TCPの再構築方法や特定のネットワークスタックの動作の解釈方法を調整できるため、スタック間の違い(WindowsとLinuxなど)に基づいてプロトコルを回避することが難しくなります。特定の範囲は、Windows、Linux、BSD、Vista、Windows 2003などのカテゴリに割り当てることができます。
スレッド処理に関しては、スレッド処理セクションでCPUアフィニティと検出スレッド数を細かく調整できます。デフォルトでは、`set-cpu-affinity`は通常無効になっており、システムスケジューラがスレッドをコア全体に分散します。`detect -thread-ratio`パラメータは、使用可能なコアごとに作成される検出スレッドの数を示します。8コアのマシンで`detect-thread-ratio: 1.5`を指定すると、Suricataは12個の検出スレッドに加え、キャプチャスレッドと管理スレッドを生成します。
このモデル全体は、デーモンの起動時に出力に反映されます。キャプチャスレッド(例えばpcap)と複数の検出スレッドに加え、フローマネージャと統計マネージャが表示されます。このマルチプロセスアーキテクチャにより、Suricataは10/40 Gbit/sのリンク環境において、シングルスレッドエンジンよりもはるかに優れたスケーラビリティを実現できます。
Suricataのルールと署名の更新
Suricataは、ルールセットに基づいて攻撃パターン、異常な動作、プロトコルの悪用を検出します。Snort形式のルールを受け入れることに加え、最も一般的なエコシステムはEmerging Threats(ET Open(無料)とET Pro(商用))であり、これらのルールは最新の脅威に対応しています。
多くの最新のディストリビューションには、ルール管理を簡素化する`suricata-update`ツールが含まれています。このツールは、ソースを更新し、特定のプロバイダーを有効または無効にし、最新バージョンのシグネチャ セットをダウンロードします。一般的なワークフローとしては、`suricata-update` をインストールし(たとえば、pip 経由)、最初の `suricata-update` を実行して ET Open をダウンロードし、`suricata-update list-sources` でソースを一覧表示し、`ptresearch/attackdetection`、`oisf/trafficid`、`sslbl/ssl-fp-blacklist` などの追加のソースを有効にし、再度 `suricata-update` を実行してルール ファイルを再生成します。
suricata.yaml ファイルを調整して正しいルールパスを指定すると、Suricata はアラート イベントを発生させ、fast.log (高速で読みやすいテキスト) と eve.json (非常に詳細な情報を含む構造化 JSON)にログを記録します。後者の形式は、ダッシュボード、相関システム、またはカスタム スクリプトへのデータ供給に特に役立ちます。
Suricataは署名に加えて、複数のプロトコル用のデコーダーとパーサーを組み込んでいるため、ポートへの依存度が低くなっています。非標準ポートを経由するHTTPトラフィックを識別したり、異なるポートやカプセル化レベル(IPv4/IPv6混在トンネルを含む)を介したSSH、TLS、DNSなどを検出したりできます。
実用:Webエクスプロイトの検出から自動ブロックまで
ホスティング環境やデータセンターにおいて最も求められているユースケースの一つは、Webアプリケーション(WordPressとそのプラグインなど)の脆弱性を悪用しようとする試みをリアルタイムで検知し、ファイアウォールで送信元IPアドレスをブロックまたはブラックリストに登録するなどして自動的に対応することです。
最新のルールに基づいて動作するSuricataは、URL、パラメータ、HTTPペイロード、さらには既知の脆弱性に一致するリクエストシーケンスに対する特定の攻撃パターンを認識することができます。IDSは、スイッチポート(SPAN)からのミラーリングを介してトラフィックを受信するパッシブモードで動作できますが、IPSとして機能して攻撃をブロックするには、転送プレーンに統合する必要があります。
一般的なアプローチは 2 つあります。1 つは IDS をオンライン ブリッジとして設定し、トラフィックが物理的にマシンを通過するようにする方法(プラットフォームに応じて iptables、AF_PACKET、または PF を使用) です。もう 1 つは、トポロジーはそのままにして、ミラーリングとAPI、スクリプト、または NFQUEUE を介した中央ファイアウォールでのアクションを組み合わせる方法です。最初のアプローチは、ネットワークの「中間」に別の要素を追加するという代償を伴いますが、検出からブロックまでの遅延を最小限に抑えます。2 番目のアプローチは、より高い柔軟性と回復力を提供しますが、オーケストレーションがより複雑になります。
侵入検知システム(IDS)が、脆弱性のあるWordPressプラグインを悪用しようとする試みを検知し、直接または関連コンポーネントを介して、攻撃者のIPアドレスをiptablesブラックリストに追加することは十分に可能です。これは、SuricataのJSON出力とiptables/nftablesを呼び出すスクリプトを使用するか、ロジックの一部をNFQUEUEに委任することで実現できます。NFQUEUEでは、エンジン自体または関連プロセスが、外部リストの更新を待たずにその場で判断を下します。
これにより、多くの状況ではそれ自体は心配する必要がない基本的なポート スキャンなどのバックグラウンド ノイズを無視したり、単にログに記録したりして、本当に重要な脅威 (エクスプロイト、エスカレーションの試み、非常に積極的なスキャン) に集中できるようになります。
Pfsense 上の Suricata: IDS/IPS を統合したオープンソースファイアウォール
誰もがPalo Altoのようなハイエンドの独自ファイアウォールを購入できるわけではありませんし、購入したいとも思わない人もいます。多くの環境では、pfSenseとSuricataを使ったオープンソースソリューションを導入する方が魅力的です。これらは、高度なファイアウォール機能(マルチWAN、VLAN、VPN、NATなど)とIDS/IPSの両方をカバーしています。
FreeBSDとPacket Filterをベースとするpfsenseは、仮想化環境(Proxmox、KVMなど)で特に優れた動作を発揮しますが、負荷がかかった状態でのパフォーマンスの問題やクラッシュを回避するには、KVMマシンではVirtioの代わりにE1000カードを使用することをお勧めします。ただし、Netgateの推奨事項(システム > 詳細設定 > ネットワークでハードウェアチェックサムオフロードを無効にして再起動する。ただし、負荷が非常に高い場合はこれだけでは不十分な場合があることに注意)を適用すれば、この限りではありません。
PfSense上でSuricataを使用するラボの最小ハードウェア要件は控えめなもの(1つのCPU 500MHz、1GB RAM、4GBディスク)ですが、本格的な使用には、少なくとも2つのCPU、4GBのRAM、16GBのストレージが推奨されます。また、複数のネットワークインターフェース(WAN用、LAN用、複数のWANや複雑なVLANが必要な場合はさらに多く)を用意することも忘れないでください。
pfSenseのインストール自体は非常に簡単です。ISOから起動し、ライセンスに同意し、インストールを選択し、言語とキーボードレイアウトを選択し、パーティション設定を自動(ディスク全体を使用する場合はAuto UFS)のままにしておくだけで、数分でシステムの初回起動準備が完了します。コンソールには、インターフェースの割り当て、再起動、シェルの起動などを行うメニューが用意されています。
ラボ環境、例えばVirtualBoxでは、 WAN経由でWebインターフェースにアクセスするためにコンソールからpfctl -dコマンドを使用してPfsenseファイアウォールを一時的に無効にし(ユーザー名admin、パスワードpfsense)、初期ウィザード(一般データ、NTPサーバー、WAN構成(ラボ環境では通常DHCPで十分)、LAN、管理者パスワードの変更、構成の適用)を完了するのが一般的です。
アクセスが安定したら、WANファイアウォールに、任意の送信元からpfsenseのIPアドレスへのHTTPS接続を許可するルールを作成し、ルールを視覚的に整理するために説明的な区切り文字(例:「ファイアウォールアクセス」)を追加できます。RFC1918アドレスを使用するテスト環境の場合は、`pfctl -d`を頻繁に使用する必要がないように、 WAN上のプライベートネットワークをブロックするオプションを無効にすることをお勧めします。
pfSense への Suricata のインストールと概要
pfSenseのベースシステムが稼働していれば、Suricataのインストールは簡単です。システム > パッケージマネージャ > 利用可能なパッケージに移動し、Suricataを検索してパッケージをインストールするだけです。このプロセスでは複数のファイルがダウンロードされるため、ハードウェアによっては時間がかかる場合がありますが、Webインターフェースから完全にサポートされます。
インストールが完了すると、「サービス」タブにSuricataのエントリが表示され、そこでインターフェース(WAN、LAN、VLANなど)ごとにインスタンスを設定したり、使用するルールセットを選択したり、IDSまたはIPSモードを有効にしたり、パフォーマンスとログパラメータを調整したりできます。オプションの範囲は非常に広く(設定だけでも記事が書けるほどです)、Linuxでは手動でYAMLを編集する必要がある多くのタスクが、ここではフォームとチェックボックスで処理できるという利点があります。
重要な注意点:ラボ環境ではpfSenseの管理画面をインターネットに直接公開したくなるかもしれませんが、本番環境ではアクセスを静的IPアドレスに制限し、リモート管理にはVPNを使用し、Webコンソールを外部に公開したままにしないことが非常に重要です。pfSenseは非常に柔軟性がありますが、同時に重要な要素として扱う必要があります。
pfSenseでSuricataを有効にすると、トラフィックはファイアウォールとNATのためにpfSenseを通過し、 Suricataは独自のルールに従ってトラフィックを検査し、IPSモードでブロックできる環境が実現します。この組み合わせは単一のWebインターフェースから管理できるため、中小規模ネットワークにおけるDPI保護の導入が大幅に簡素化されます。
多くの導入では、Pfsense/Suricata を SIEM または集中ログ プラットフォームに接続することでこれが補完され、構造化された出力形式を利用してイベントを相関させ、より広範なキャンペーンを検出します。
Suricata でのイベント監視とログ例
Suricataが起動すると、イベントはdefault-log-dirで定義されたパス(通常は/var/log/suricata)にログとして記録されます。fast.logファイルは、タイムスタンプ、ルールID、分類、優先度などの情報を含むコンパクトなテキスト形式を使用しており、ターミナル(tail -f)から簡単に確認できます。
例えば、TCPチェックサムが正しくないトラフィックに遭遇した場合、次のような行が表示されることがあります。日付と時刻のタイムスタンプ、ルール識別子(例:1:2200074:1)、メッセージ「SURICATA TCPv4 invalid checksum」、分類、優先度、送信元と宛先のIPアドレス/ポート番号のペア。このようなアラートにより、パケットの整合性の問題や回避の試みを迅速に特定できます。
eve.json ファイルには、タイムスタンプ、イベントタイプ、送信元 IP アドレス、宛先 IP アドレス、送信元ポート、宛先ポート、プロトコルなどのフィールドを含む JSON 形式のイベント情報と、アクション、グループ ID、署名 ID、リビジョン、署名、カテゴリ、重大度などの情報を含むアラート サブファイルが格納されています。この形式は、Logstash、Fluentd、Filebeat、またはその他のログ エージェントに簡単に取り込むことができ、プレーン テキストを使用する場合よりもはるかに高度な分析が可能になります。
マルチコアサーバー(例えば8コア)にSuricataをデプロイすると、スレッドモードのhtopなどのツールでスレッド圧縮が容易に確認できます。1つ以上のキャプチャスレッド(pcap、AF_PACKET、またはNFQ)と、コア全体に分散された多数の検出スレッドが表示されます。トラフィック量がプラットフォームの限界に近づくと、検出スレッド比率とCPUアフィニティを調整することで、スループットとレイテンシに大きな影響を与える可能性があります。
本番環境にデプロイする前に、どのルールセットを有効にするかを微調整する時間をかけることをお勧めします。そうすることで、正当なトラフィックをブロックしたり、ログを乱雑にしたりする誤検知が大量に発生するのを防ぐことができます。Suricata-updateを使用すると、カテゴリ全体または個々のルールを無効にして、感度と使いやすさの適切なバランスを見つけることができます。
特殊アプリケーション: VoIP、オーディオ分析、クリエイティブNFQUEUE
NetfilterとNFQUEUEの組み合わせは、従来の用途(Webサービス保護、マルウェア検出、DDoS攻撃分析など)にとどまらず、VoIPなどの分野で非常に独創的なソリューションを可能にします。例えば、アンチSPIT(IP電話スパム)フィルタや、RTPストリーム内の不適切な言葉を検閲するシステムを構築できます。
そのアイデアは、ポートまたはプロトコル認識によってRTPトラフィックを識別し、NFQUEUEに送信すること、そしてユーザーアプリケーションからlibrtpのようなライブラリを使用してRTPストリームを再構築し、WAV形式のオーディオを抽出して、サードパーティが提供する合成ライブラリや認識ライブラリなどのキーワード認識エンジン(ワードスポッティング)に渡すことです。
検出された単語に基づいて、NFQUEUEプロセスは再生を許可、ブロック、あるいはストリームにビープ音を挿入することで再生を変更することさえ可能です。ただし、後者の場合、RTCP、パケットシーケンス、タイミングを非常に精密に制御する必要があり、ほぼ中間者攻撃に近い手法となります。これは容易ではありませんが、理論的には同じキューと判定システムを活用することで完全に実現可能です。
確かに、この処理の一部は、データを外部プロセッサに送信するシンプルなスニファを使用し、SIPシグナリングまたはSBC(Asterisk、Kamailioなど)を介して実行することも可能です。NFQUEUEを使用する場合との違いは、複数のコンポーネントを調整したり、シグナリング層が通話を完了するのを待ったりすることなく、 RTPフローに対する処理を即座に直接実行できる点です。
これらのシナリオは、GNU/Linux + Netfilter + Suricata + サードパーティライブラリの組み合わせの可能性を明確に示しています。単にポートやIPアドレスをブロックするだけでなく、 100%フリーソフトウェアのエコシステムを使用して、複雑なトラフィックの決定をリアルタイムで調整できるのです。
常にパケットを受け入れる小さな C プログラムから、NFQUEUE、Pfsense、データベース、キャッシュが統合されたマルチプロセスの Suricata 展開まで、このプロセス全体を見ると、このテクノロジ スタックが提供する柔軟性がわかります。この柔軟性により、単純な動的ファイアウォールからデータ センター規模の IDS/IPS アーキテクチャまで、あらゆるものを構築できます。また、実際の詳細な検査機能と、ますます複雑化する攻撃への自動応答も備えています。