🐿️

Suricata IPS(NFQUEUE)における誤検知対策とホワイトリスト化の3つの手法

に公開

概要

Suricata を NFQUEUE(iptables / nftables)でインライン動作(IPS)させている際、「正当な通信が誤検知で遮断されてしまう」ケースがあります。
「この通信だけは確実に通したい」「特定の送信元は Suricata のブロック対象にしたくない」といったケースへの対応方法を検討しました。

前提

本記事では、Suricata をインラインIPSとして単一サーバー上で動作させる構成を前提にします。

方法1:dropルールをalertに変更する(SID単位で緩和)

Suricata の各ルールには、以下のように動作種別が定義されています。

  • drop … パケットを破棄し、通信を遮断する
  • alert … ログに記録するが、通信は通す

特定の SID が原因で不要な遮断が発生している場合、
もっとも簡単に制御できるのが 該当SIDのルールをdrop→alertに変更する方法です。
これにより通信は通しつつ、アラートログだけ維持できます。

例:dropルールをalertへ変更

シグネチャのActionをdropからalertに変更します。

drop http any any -> any any (msg:"test drop"; http.uri; content:"/test"; sid:3000001;)

alert http any any -> any any (msg:"test drop"; http.uri; content:"/test"; sid:3000001;)

※記事中では説明のためにルールを直接編集していますがsuricata-update を利用している場合、ルールファイルの直接書き換えは更新時に上書きされるため非推奨です。
恒久的にdrop→alertを適用するにはmodify.confのmodifysid機能等を使用してください

メリット

  • 対応がシンプル(該当SIDのアクションを変えるだけ)
  • 通信を止めずにアラートログだけ残せる

デメリット

  • 本当に危険な通信でもalertのみで通ってしまう

■ 方法2:nftablesで特定IPをNFQUEUEから除外する

社内ネットワークや信頼済みの接続元など、「このIPだけはSuricataの処理を通さず素通りさせたい」場面では、nftables側でNFQUEUEに渡す前にacceptさせる方法が使えます。

通常のNFQUEUE設定

まず、すべてのパケットをSuricataに渡す状態です。

# nft list ruleset
table inet filter {
	chain input {
		type filter hook input priority filter; policy accept;
		queue to 0
	}

	chain output {
		type filter hook output priority filter; policy accept;
		queue to 0
	}
}
# 

特定IPを除外

特定IPの通信をSuricataに渡さず通過させます。

# nft list ruleset(特定 IP を除外した場合)
table inet filter {
	chain input {
		type filter hook input priority filter; policy accept;
		ip saddr 172.30.50.100 accept   # 受信元 IP を除外
		queue to 0
	}

	chain output {
		type filter hook output priority filter; policy accept;
		ip daddr 172.30.50.100 accept   # 送信先 IP を除外(必要なら)
		queue to 0
	}
}

メリット

  • 特定IPのパケットをNFQUEUEに渡さないため、解析処理が減り Suricataの負荷が軽減される
  • シンプルなIP単位の完全な除外が可能

デメリット

  • 許可したIPに関しては監視も検知もされなくなる

■ 方法3:passルールで特定通信を通す

Suricataにはルールの優先順位(action-order)がありsuricata.yamlで次のように定義されています

action-order:
  - pass
  - drop
  - reject
  - alert

passがマッチするとdrop/reject/alertより優先されるため、どんなシグネチャが後ろにあっても通信は通ります。
このため、特定通信を必ず通したい場合はpassルールを使用します。

12.1.6. Action-order

特定IPの両方向全通信を通す例

pass ip 192.0.2.10 any <-> any any (msg:"whitelist 192.0.2.10"; sid:9000010;)

プロトコルをipとすることですべてのプロトコル(TCP/UDP/ICMP など)を対象にできます

メリット

  • IPやポートを柔軟に指定できる
  • SuricataのFlowログ(通信統計)は通常どおり記録される
    ただし、passルールにマッチした通信はアラートログには出力されない
  • マッチ以降の検査がスキップされるため、負荷が低減される

デメリット

  • 許可したIPに関しては監視も検知もされなくなる
  • Suricataの処理負荷はゼロにはならない

■ まとめ

Suricataの誤検知や特定通信への対応方法を整理しました。

方法 特徴 Suricataの負荷 アラートログ 向いているケース
drop→alert 通信は通しつつ検知だけ残す 通常どおり 残る SID単位での誤検知回避
nftablesで除外 Suricata自体を通さない 最小 残らない 信頼IPの完全除外・性能重視
passルール Suricataで条件判定して通す 低減される 残らない※ 複雑な条件で検査を除外したい場合

※ Flowログ(通信記録)は残りますが、アラートログは残りません

Discussion