Suricata with Raspberry Piで遊ぼう!【環境構築&動作デモ編】

概要

Suricataと呼ばれるオープンソースのIDS(侵入検知システム) / IPS(侵入防止システム)をRaspberry Piに導入します。
今回はIDSとして構築し、カスタムルールを作成してそのルールに基づくパケットを検知するところまで。

前提

環境

  • Raspberry Pi 4 Model B [RAM 4GB, Raspberry Pi OS LIte (64-bit)]
    $ uname -a
    Linux rasp4-1 6.1.21-v8+ #1642 SMP PREEMPT Mon Apr 3 17:24:16 BST 2023 aarch64 GNU/Linux
  • 適当なPC (お好きなOS。今回はWindowsを使う)
  • Suricata 6.0.13

ネットワーク構成

ネットワーク構成
とても簡単なネットワーク構成です。
(実際の弊宅のネットワーク構成はもう少しごちゃってます。)

  • Raspberry PI
    eth0 : 192.168.120.5
    wlan0 : 192.168.1.6 (SSH接続でも使う)
  • PC
    nic1 : 192.168.120.3
    nic2 : 192.168.1.9

操作

apt更新

ひとまずaptパッケージの更新をします。

$ sudo apt update
$ sudo apt upgrade
$ sudo apt dist-upgrade

前提パッケージのインストール

Suricataに必要なパッケージ群をインストールします。

$ sudo apt install -y libpcre3 libpcre3-dbg libpcre3-dev \
build-essential autoconf automake libtool libpcap-dev libnet1-dev \
libyaml-0-2 libyaml-dev zlib1g zlib1g-dev libmagic-dev libcap-ng-dev \
libjansson-dev pkg-config python3-yaml rustc cargo

Suricataビルド&インストール

Suricataをラズパイにダウンロードして、解凍します。

$ wget https://www.openinfosecfoundation.org/download/suricata-6.0.13.tar.gz
$ tar -xvf suricata-6.0.13.tar.gz

解凍した展開されたディレクトリに移動して、ビルドとインストールを行います。

$ cd suricata-6.0.13
$ ./configure
$ make
$ sudo make install-full
$ sudo ldconfig

ビルドには約10分程かかります。
sudo make install-fullのinstall-fullは必要なディレクトリや設定ファイルの生成、利用可能なルールセットのダウンロードなど、すぐ使える状態にセットアップしてくれます。
(詳細: https://redmine.openinfosecfoundation.org/projects/suricata/wiki/Debian_Installation#Auto-setup)

備考: configureのオプション
他の文献でよくみるオプションの軽い説明を書いときます。

今回はデフォルトの配置場所で問題ないと思っているので未指定です。また、--enable-nfqueueはIPSとして動かすときに必要で、別途前提パッケージのインストールが必要です。
(詳細: https://docs.suricata.io/en/suricata-6.0.13/install.html#common-configure-options)

--prefix : バイナリの配置場所 (デフォルト: /usr/local)
--sysconfdir : 構成ファイルの配置場所 (デフォルト: /usr/local/etc)
--localstatedir : ログファイルの配置場所 (デフォルト: /usr/local/var/log/suricata)
--enable-nfqueue : IPSとして動かすときに必要なオプション

カスタムルールの追加

設定ファイルであるsuricata.yamlを編集します。一応、編集前にオリジナルのsuricata.yamlのバックアップを取っておきます。

$ sudo cp /usr/local/etc/suricata/suricata.yaml /usr/local/etc/suricata/suricata.yaml.org
$ sudo vi /usr/local/etc/suricata/suricata.yaml

rule-files:という文字列を探して、以下のように任意のrulesファイル名を追記します。

##
## Configure Suricata to load Suricata-Update managed rules.
##
default-rule-path: /usr/local/var/lib/suricata/rules
rule-files:
- suricata.rules
- user_custom.rules # add

rule-filesに列挙したファイル名は、default-rule-path内に存在する必要があります。

ということで、rulesファイルを下のようにして作成します。

$ sudo vi /usr/local/var/lib/suricata/rules/user_custom.rules

user_custom.rulesに下のようなルールを書きます。

alert icmp any any -> any any (msg: "ICMP ping detected"; sid: 100001; rev: 1;)
alert http any any -> any any (msg: "Access to himazin331.com"; http.host; content: "himazin331.com"; sid: 100002; rev: 1;)

このルールについては後ほど説明しますので一旦先に進んで、suricata-updateでルールを適用します。

$ sudo suricata-update
1/7/2023 -- 03:32:57 - <Info> -- Using data-directory /usr/local/var/lib/suricata.
1/7/2023 -- 03:32:57 - <Info> -- Using Suricata configuration /usr/local/etc/suricata/suricata.yaml
1/7/2023 -- 03:32:57 - <Info> -- Using /usr/local/share/suricata/rules for Suricata provided rules.
1/7/2023 -- 03:32:57 - <Info> -- Found Suricata version 6.0.13 at /usr/local/bin/suricata.
1/7/2023 -- 03:32:57 - <Info> -- Loading /usr/local/etc/suricata/suricata.yaml
1/7/2023 -- 03:32:57 - <Info> -- Disabling rules for protocol http2
1/7/2023 -- 03:32:57 - <Info> -- Disabling rules for protocol modbus
1/7/2023 -- 03:32:57 - <Info> -- Disabling rules for protocol dnp3
1/7/2023 -- 03:32:57 - <Info> -- Disabling rules for protocol enip
1/7/2023 -- 03:32:57 - <Info> -- No sources configured, will use Emerging Threats Open
1/7/2023 -- 03:32:57 - <Info> -- Last download less than 15 minutes ago. Not downloading https://rules.emergingthreats.net/open/suricata-6.0.13/emerging.rules.tar.gz.
1/7/2023 -- 03:32:57 - <Info> -- Loading distribution rule file /usr/local/share/suricata/rules/app-layer-events.rules
1/7/2023 -- 03:32:57 - <Info> -- Loading distribution rule file /usr/local/share/suricata/rules/decoder-events.rules
1/7/2023 -- 03:32:57 - <Info> -- Loading distribution rule file /usr/local/share/suricata/rules/dhcp-events.rules
1/7/2023 -- 03:32:57 - <Info> -- Loading distribution rule file /usr/local/share/suricata/rules/dnp3-events.rules
1/7/2023 -- 03:32:57 - <Info> -- Loading distribution rule file /usr/local/share/suricata/rules/dns-events.rules
1/7/2023 -- 03:32:57 - <Info> -- Loading distribution rule file /usr/local/share/suricata/rules/files.rules
1/7/2023 -- 03:32:57 - <Info> -- Loading distribution rule file /usr/local/share/suricata/rules/http-events.rules
1/7/2023 -- 03:32:57 - <Info> -- Loading distribution rule file /usr/local/share/suricata/rules/ipsec-events.rules
1/7/2023 -- 03:32:57 - <Info> -- Loading distribution rule file /usr/local/share/suricata/rules/kerberos-events.rules
1/7/2023 -- 03:32:57 - <Info> -- Loading distribution rule file /usr/local/share/suricata/rules/modbus-events.rules
1/7/2023 -- 03:32:57 - <Info> -- Loading distribution rule file /usr/local/share/suricata/rules/nfs-events.rules
1/7/2023 -- 03:32:57 - <Info> -- Loading distribution rule file /usr/local/share/suricata/rules/ntp-events.rules
1/7/2023 -- 03:32:57 - <Info> -- Loading distribution rule file /usr/local/share/suricata/rules/smb-events.rules
1/7/2023 -- 03:32:57 - <Info> -- Loading distribution rule file /usr/local/share/suricata/rules/smtp-events.rules
1/7/2023 -- 03:32:57 - <Info> -- Loading distribution rule file /usr/local/share/suricata/rules/stream-events.rules
1/7/2023 -- 03:32:57 - <Info> -- Loading distribution rule file /usr/local/share/suricata/rules/tls-events.rules
1/7/2023 -- 03:32:58 - <Info> -- Ignoring file rules/emerging-deleted.rules
1/7/2023 -- 03:33:05 - <Info> -- Loaded 43403 rules.
1/7/2023 -- 03:33:05 - <Warning> -- Disabling ja3 rules as Suricata is built without libnss.
1/7/2023 -- 03:33:05 - <Info> -- 116 ja3_hash rules disabled.
1/7/2023 -- 03:33:06 - <Info> -- Disabled 130 rules.
1/7/2023 -- 03:33:06 - <Info> -- Enabled 0 rules.
1/7/2023 -- 03:33:06 - <Info> -- Modified 0 rules.
1/7/2023 -- 03:33:06 - <Info> -- Dropped 0 rules.
1/7/2023 -- 03:33:07 - <Info> -- Enabled 131 rules for flowbit dependencies.
1/7/2023 -- 03:33:07 - <Info> -- Backing up current rules.
1/7/2023 -- 03:33:16 - <Info> -- Writing rules to /usr/local/var/lib/suricata/rules/suricata.rules: total: 43403; enabled: 34466; added: 0; removed 1; modified: 0
1/7/2023 -- 03:33:16 - <Info> -- Writing /usr/local/var/lib/suricata/rules/classification.config
1/7/2023 -- 03:33:17 - <Info> -- Testing with suricata -T.
1/7/2023 -- 03:33:30 - <Info> -- Done.

suricata-updateは自身が定義したルールを適用する他、Emerging Threats Open rulesetのダウンロード・更新もします。
Emerging Threats Open rulesetはセキュリティ情報共有コミュニティであるEmerging Threatsが提供するオープンソースのルールセットです。

ルール構文

ルールにはaction, header, optionsの3つのセクションに分かれています。

actionは次にも説明しますが、ルールに該当するパケットの処理を記述します。
headerは通信プロトコルと送信側/受信側IPアドレスとポート、通信の方向を記述します。TCP/IPのインターネット層とトランスポート層にあたる情報ですね。
optionsはシグネチャ情報やパケットの詳細なルール(TCP/IPのアプリケーション層にあたる情報)を記述します。

シグネチャとは、脅威を特定・判別するために用いられる識別情報です。

| alert | icmp any any -> any any | (msg: "ICMP ping detected"; sid: 100001; rev: 1;) |
| ↑ | ↑ ↑ ↑ ↑ ↑ ↑ | ↑ ↑ ↑ |
| 処理形式 |プロトコル src-ip src-port direction dst-ip dst-port | シグネチャメッセージ シグネチャID リビジョン |
|---------|----------------------------------------------------|---------------------------------------------------|
| action | header | options |

ここでは簡単に最小限の説明にとどめます。


actionもとい、処理形式はそのルールに該当する場合、そのパケットをどう処理するかを指定します。種類は下のとおりです。

種類説明
alertアラートを発報
passパケット解析を中止(通信の許可)
dropパケットをドロップしてアラートを発報
rejectパケット送信者にRST/ICMP 到達不能エラーを送信
rejectsrcrejectと同じ
rejectdstパケット受信者にRST/ICMP 到達不能エラーを送信
rejectbothパケット送信者/受信者にRST/ICMP 到達不能エラーを送信

headerについて説明します。

  • 通信プロトコル
    • プロトコルを指定します。
    • 主に使用される基本的なプロトコル群
      tcp, udp, icmp, ip
      もちろん、下のようなプロトコルも対応しています。
      http, ftp, tls(*1), smb, dns, dcerpc, ssh, smtp, imap, nfs, ikev2, krb5, ntp,
      dhcp, rfb, rdp, snmp, tftp, sip, http2, modbus(*2), dnp3(*2), enip(*2)
      *1. sslも含む
      *2. デフォルトで無効になっているため、suricata.yamlで要有効化
  • src/dst ip
    • IPアドレスやネットワークアドレス、変数($HOME_NET/$EXTERNAL_NET)、any(全てのIPアドレス)を指定します。
      • $HOME_NET/$EXTERNAL_NETはsuricata.yamlで定義できます。
    • また、カッコ[ ]を使ってIPアドレスを複数列挙できるほか、not演算子!を使って除外もできます。
    • 以下はいずれも有効な指定方法です。
      any
      192.168.1.2
      192.168.1.0/24
      $HOME_NET
      $EXTERNAL_NET
      [192.168.1.2, 192.168.1.3]
      ![192.168.1.2, 192.168.1.3]
      [$HOME_NET, 192.168.1.2]
      [192.168.1.0/24, !192.168.1.2]
      [192.168.1.0/24, ![192.168.1.2, 192.168.1.3]]
  • src/dst port
    • ポート番号を指定します。
    • コロン:を使ってポート番号を範囲指定できるほか、IPアドレスの指定同様カッコ[ ]による複数列挙とnot演算子!による除外もできます。
    • 以下はいずれも有効な指定方法です。
      any
      80
      [80, 81, 82]
      [80: 82]
      [1024: ]
      !8080
      [80:100, !99]
      [1:80, ![2,4]]
  • direction
    • 通信の方向を記述します。
    • 大抵は->ですが、双方向通信を示す<>を指定することもあるようです。
      • <-は存在しないっぽいです。(要らないですし)

optionsについて説明します。

  • シグネチャメッセージ msg
    • そのシグネチャがどのようなものなのかを簡潔に書きます。
    • 慣習的にoptionsの先頭に書くっぽいです。
  • シグネチャID sid
    • シグネチャ識別IDです。
    • sidは整数値のみ認められ、一意である必要があります。
    • 慣習的にrevの前、最後から2番めに書くっぽいです。
    • シグネチャIDにはある程度、割当領域があり、ユーザによるカスタムルールは1000000-1999999の範囲を使います。
  • リビジョン rev
    • バージョンです。
    • そのルールの更新のたびに値を増分させます。
    • revは整数値のみ認められます。
    • 慣習的にoptionsの最後に書くっぽいです。

上で挙げた情報はいずれもルールに関わる情報で、メタキーワードと呼ばれます。
他にもいくつかのメタキーワードがありますので、詳細は7.2. Meta Keywords — Suricata 6.0.13 documentationを確認してください。

また、TCP/IPのアプリケーション層にあたる情報についても大量にあるので、
7. Suricata Rules — Suricata 6.0.13 documentationから各プロトコルごとのキーワードを確認して指定してください。


簡単にルール構文の説明をしたところで、user_custom.rulesに書いたルールを説明すると...

alert icmp any any -> any any (msg: "ICMP ping detected"; sid: 100001; rev: 1;)
→ すべての送信元からすべての送信先に対してICMP通信がきたらアラートを発報する
alert http any any -> any any (msg: "Access to himazin331.com"; http.host; content: "himazin331.com"; sid: 100002; rev: 1;)
→ すべての送信元において"himazin331.com"とHTTP通信が行われたらアラートを発報する
 (himazin331.comのIPアドレス/ポートは問わない)

となります。とても簡単なルールですね。

実行 #1

以下のコマンドを入力してSuricataを実行します。

-cは設定ファイルパスの指定オプション。多分無くても動くと思います。-iはインターフェースの指定オプション、-vはログレベルInfoを出力するオプションです。
インターフェースの指定は複数指定が可能で、eth0とwlan0両方を監視対象としています。

<Notice> - all X packet processing threads, X management threads initialized, engine started.みたいなのが出力されたら監視が開始されます。

1
$ sudo suricata -c /usr/local/etc/suricata/suricata.yaml -i eth0 -i wlan0 -v
2
1/7/2023 -- 05:09:58 - <Notice> - This is Suricata version 6.0.13 RELEASE running in SYSTEM mode
3
1/7/2023 -- 05:09:58 - <Info> - CPUs/cores online: 4
4
1/7/2023 -- 05:09:58 - <Info> - Setting engine mode to IDS mode by default
5
1/7/2023 -- 05:09:58 - <Info> - Found an MTU of 1500 for 'eth0'
6
1/7/2023 -- 05:09:58 - <Info> - Found an MTU of 1500 for 'eth0'
7
1/7/2023 -- 05:09:58 - <Info> - Found an MTU of 1500 for 'wlan0'
8
1/7/2023 -- 05:09:58 - <Info> - Found an MTU of 1500 for 'wlan0'
9
1/7/2023 -- 05:09:58 - <Info> - fast output device (regular) initialized: fast.log
10
1/7/2023 -- 05:09:58 - <Info> - eve-log output device (regular) initialized: eve.json
11
1/7/2023 -- 05:09:58 - <Info> - stats output device (regular) initialized: stats.log
12
1/7/2023 -- 05:09:58 - <Info> - Running in live mode, activating unix socket
13
1/7/2023 -- 05:10:02 - <Info> - 2 rule files processed. 34468 rules successfully loaded, 0 rules failed
14
1/7/2023 -- 05:10:02 - <Info> - Threshold config parsed: 0 rule(s) found
15
1/7/2023 -- 05:10:03 - <Info> - 34471 signatures processed. 1278 are IP-only rules, 5234 are inspecting packet payload, 27752 inspect application layer, 108 are decoder event only
16
1/7/2023 -- 05:10:11 - <Info> - Going to use 4 thread(s)
17
1/7/2023 -- 05:10:11 - <Info> - Going to use 4 thread(s)
18
1/7/2023 -- 05:10:11 - <Info> - Running in live mode, activating unix socket
19
1/7/2023 -- 05:10:11 - <Info> - Using unix socket file '/usr/local/var/run/suricata/suricata-command.socket'
20
1/7/2023 -- 05:10:11 - <Notice> - all 8 packet processing threads, 4 management threads initialized, engine started.
21
1/7/2023 -- 05:10:11 - <Info> - All AFP capture threads are running.

ICMP検知 #1

PC上でターミナルを開き、pingコマンドを実行します。

まずは192.168.1.0/24のネットワークで。PC: 192.168.1.9 ---> Rasp Pi: 192.168.1.6

ping 192.168.1.6 -n 10

pingが完了したらラズパイに戻って、Ctrl+CでSuricataを終了します。

次に下のコマンドを実行し、アラートが出力されているかを確認します。

$ cat /usr/local/var/log/suricata/fast.log
07/01/2023-05:10:34.258335 [**] [1:100001:1] ICMP ping detected [**] [Classification: (null)] [Priority: 3] {ICMP} 192.168.1.9:8 -> 192.168.1.6:0
07/01/2023-05:10:34.258420 [**] [1:100001:1] ICMP ping detected [**] [Classification: (null)] [Priority: 3] {ICMP} 192.168.1.6:0 -> 192.168.1.9:0
$ cat /usr/local/var/log/suricata/eve.json | grep 100001
{"timestamp":"2023-07-01T05:16:51.347768+0900","flow_id":852141781765752,"in_iface":"eth0","event_type":"alert","src_ip":"192.168.120.3","src_port":0,"dest_ip":"192.168.120.5","dest_port":0,"proto":"ICMP","icmp_type":8,"icmp_code":0,"alert":{"action":"allowed","gid":1,"signature_id":100001,"rev":1,"signature":"ICMP ping detected","category":"","severity":3},"flow":{"pkts_toserver":1,"pkts_toclient":0,"bytes_toserver":74,"bytes_toclient":0,"start":"2023-07-01T05:16:51.347768+0900"}}
{"timestamp":"2023-07-01T05:16:51.347865+0900","flow_id":852141781765752,"in_iface":"eth0","event_type":"alert","src_ip":"192.168.120.5","src_port":0,"dest_ip":"192.168.120.3","dest_port":0,"proto":"ICMP","icmp_type":0,"icmp_code":0,"alert":{"action":"allowed","gid":1,"signature_id":100001,"rev":1,"signature":"ICMP ping detected","category":"","severity":3},"flow":{"pkts_toserver":1,"pkts_toclient":1,"bytes_toserver":74,"bytes_toclient":74,"start":"2023-07-01T05:16:51.347768+0900"}}

つづいて、192.168.120.0/24のネットワークで。PC: 192.168.120.3 ---> Rasp Pi: 192.168.120.5

ping 192.168.120.5 -n 10

先程同様に終了し、ログをみてみます。

$ cat /usr/local/var/log/suricata/fast.log
07/01/2023-05:16:51.347768 [**] [1:100001:1] ICMP ping detected [**] [Classification: (null)] [Priority: 3] {ICMP} 192.168.120.3:8 -> 192.168.120.5:0
07/01/2023-05:16:51.347865 [**] [1:100001:1] ICMP ping detected [**] [Classification: (null)] [Priority: 3] {ICMP} 192.168.120.5:0 -> 192.168.120.3:0
$ cat /usr/local/var/log/suricata/eve.json | grep 100001
{"timestamp":"2023-07-01T05:16:51.347768+0900","flow_id":852141781765752,"in_iface":"eth0","event_type":"alert","src_ip":"192.168.120.3","src_port":0,"dest_ip":"192.168.120.5","dest_port":0,"proto":"ICMP","icmp_type":8,"icmp_code":0,"alert":{"action":"allowed","gid":1,"signature_id":100001,"rev":1,"signature":"ICMP ping detected","category":"","severity":3},"flow":{"pkts_toserver":1,"pkts_toclient":0,"bytes_toserver":74,"bytes_toclient":0,"start":"2023-07-01T05:16:51.347768+0900"}}
{"timestamp":"2023-07-01T05:16:51.347865+0900","flow_id":852141781765752,"in_iface":"eth0","event_type":"alert","src_ip":"192.168.120.5","src_port":0,"dest_ip":"192.168.120.3","dest_port":0,"proto":"ICMP","icmp_type":0,"icmp_code":0,"alert":{"action":"allowed","gid":1,"signature_id":100001,"rev":1,"signature":"ICMP ping detected","category":"","severity":3},"flow":{"pkts_toserver":1,"pkts_toclient":1,"bytes_toserver":74,"bytes_toclient":74,"start":"2023-07-01T05:16:51.347768+0900"}}

ICMPパケットを10個送ったので、forward/backward合わせて20個のアラートがあることを期待したのですが、なぜか2個しか無いですね....
フロー情報を出力したeve.jsonをみても、pkts_toserver/pkts_toclientは1だし...

この辺、理由がわかるかた居ましたらTwitterやメールで教えてください。

まあ、とりあえずICMPパケットが送られてきたことを検知して、アラートが出力されたことが確認できましたね。

HTTP検知 #1

ラズパイに別セッションでSSH接続し、そのターミナル上で"himazin331.com"にHTTP通信でアクセスします。

まずは192.168.1.0/24のネットワークで。Rasp Pi: 192.168.1.6 ---> himazin331.com: 103.152.178.181

$ curl --interface wlan0 http://himazin331.com

Suricataを終了し、ログを見ます。

$ cat /usr/local/var/log/suricata/fast.log
07/01/2023-05:20:33.577228 [**] [1:100001:1] ICMP ping detected [**] [Classification: (null)] [Priority: 3] {ICMP} 192.168.120.1:3 -> 192.168.120.5:3
07/01/2023-05:20:33.649334 [**] [1:100002:1] Access to himazin331.com [**] [Classification: (null)] [Priority: 3] {TCP} 103.152.178.181:80 -> 192.168.1.6:39760
07/01/2023-05:20:33.652658 [**] [1:100002:1] Access to himazin331.com [**] [Classification: (null)] [Priority: 3] {TCP} 103.152.178.181:80 -> 192.168.1.6:39760
07/01/2023-05:20:33.652701 [**] [1:100002:1] Access to himazin331.com [**] [Classification: (null)] [Priority: 3] {TCP} 192.168.1.6:39760 -> 103.152.178.181:80
07/01/2023-05:20:33.653460 [**] [1:100002:1] Access to himazin331.com [**] [Classification: (null)] [Priority: 3] {TCP} 192.168.1.6:39760 -> 103.152.178.181:80
07/01/2023-05:20:33.674213 [**] [1:100002:1] Access to himazin331.com [**] [Classification: (null)] [Priority: 3] {TCP} 103.152.178.181:80 -> 192.168.1.6:39760
07/01/2023-05:20:33.674251 [**] [1:100002:1] Access to himazin331.com [**] [Classification: (null)] [Priority: 3] {TCP} 192.168.1.6:39760 -> 103.152.178.181:80
$ cat /usr/local/var/log/suricata/eve.json | grep 100002
{"timestamp":"2023-07-01T05:20:33.649334+0900","flow_id":294012943676400,"in_iface":"wlan0","event_type":"alert","src_ip":"103.152.178.181","src_port":80,"dest_ip":"192.168.1.6","dest_port":39760,"proto":"TCP","alert":{"action":"allowed","gid":1,"signature_id":100002,"rev":1,"signature":"Access to himazin331.com","category":"","severity":3},"http":{"hostname":"himazin331.com","url":"/","http_user_agent":"curl/7.74.0","http_method":"GET","protocol":"HTTP/1.1","length":0},"app_proto":"http","flow":{"pkts_toserver":3,"pkts_toclient":2,"bytes_toserver":284,"bytes_toclient":140,"start":"2023-07-01T05:20:33.603120+0900"}}
{"timestamp":"2023-07-01T05:20:33.652658+0900","flow_id":294012943676400,"in_iface":"wlan0","event_type":"alert","src_ip":"103.152.178.181","src_port":80,"dest_ip":"192.168.1.6","dest_port":39760,"proto":"TCP","alert":{"action":"allowed","gid":1,"signature_id":100002,"rev":1,"signature":"Access to himazin331.com","category":"","severity":3},"http":{"hostname":"himazin331.com","url":"/","http_user_agent":"curl/7.74.0","http_method":"GET","protocol":"HTTP/1.1","length":0},"app_proto":"http","flow":{"pkts_toserver":3,"pkts_toclient":3,"bytes_toserver":284,"bytes_toclient":559,"start":"2023-07-01T05:20:33.603120+0900"}}
{"timestamp":"2023-07-01T05:20:33.652701+0900","flow_id":294012943676400,"in_iface":"wlan0","event_type":"alert","src_ip":"192.168.1.6","src_port":39760,"dest_ip":"103.152.178.181","dest_port":80,"proto":"TCP","alert":{"action":"allowed","gid":1,"signature_id":100002,"rev":1,"signature":"Access to himazin331.com","category":"","severity":3},"http":{"hostname":"himazin331.com","url":"/","http_user_agent":"curl/7.74.0","http_content_type":"text/html","http_method":"GET","protocol":"HTTP/1.1","status":301,"redirect":"https://himazin331.com/","length":162},"app_proto":"http","flow":{"pkts_toserver":4,"pkts_toclient":3,"bytes_toserver":350,"bytes_toclient":559,"start":"2023-07-01T05:20:33.603120+0900"}}
{"timestamp":"2023-07-01T05:20:33.653460+0900","flow_id":294012943676400,"in_iface":"wlan0","event_type":"alert","src_ip":"192.168.1.6","src_port":39760,"dest_ip":"103.152.178.181","dest_port":80,"proto":"TCP","alert":{"action":"allowed","gid":1,"signature_id":100002,"rev":1,"signature":"Access to himazin331.com","category":"","severity":3},"http":{"hostname":"himazin331.com","url":"/","http_user_agent":"curl/7.74.0","http_content_type":"text/html","http_method":"GET","protocol":"HTTP/1.1","status":301,"redirect":"https://himazin331.com/","length":162},"app_proto":"http","flow":{"pkts_toserver":5,"pkts_toclient":3,"bytes_toserver":416,"bytes_toclient":559,"start":"2023-07-01T05:20:33.603120+0900"}}
{"timestamp":"2023-07-01T05:20:33.674213+0900","flow_id":294012943676400,"in_iface":"wlan0","event_type":"alert","src_ip":"103.152.178.181","src_port":80,"dest_ip":"192.168.1.6","dest_port":39760,"proto":"TCP","alert":{"action":"allowed","gid":1,"signature_id":100002,"rev":1,"signature":"Access to himazin331.com","category":"","severity":3},"http":{"hostname":"himazin331.com","url":"/","http_user_agent":"curl/7.74.0","http_content_type":"text/html","http_method":"GET","protocol":"HTTP/1.1","status":301,"redirect":"https://himazin331.com/","length":162},"files":[{"filename":"/","sid":[],"gaps":false,"state":"CLOSED","stored":false,"size":162,"tx_id":0}],"app_proto":"http","flow":{"pkts_toserver":5,"pkts_toclient":4,"bytes_toserver":416,"bytes_toclient":625,"start":"2023-07-01T05:20:33.603120+0900"}}
{"timestamp":"2023-07-01T05:20:33.674251+0900","flow_id":294012943676400,"in_iface":"wlan0","event_type":"alert","src_ip":"192.168.1.6","src_port":39760,"dest_ip":"103.152.178.181","dest_port":80,"proto":"TCP","alert":{"action":"allowed","gid":1,"signature_id":100002,"rev":1,"signature":"Access to himazin331.com","category":"","severity":3},"http":{},"app_proto":"http","flow":{"pkts_toserver":6,"pkts_toclient":4,"bytes_toserver":482,"bytes_toclient":625,"start":"2023-07-01T05:20:33.603120+0900"}}

つづいて、192.168.120.0/24のネットワークで。Rasp Pi: 192.168.120.5 ---> himazin331.com: 103.152.178.181

$ curl --interface eth0 http://himazin331.com

Suricataを終了し、ログを見ます。

$ cat /usr/local/var/log/suricata/fast.log
07/01/2023-05:22:19.954569 [**] [1:100001:1] ICMP ping detected [**] [Classification: (null)] [Priority: 3] {ICMP} 192.168.120.1:3 -> 192.168.120.5:3
07/01/2023-05:22:20.016863 [**] [1:100002:1] Access to himazin331.com [**] [Classification: (null)] [Priority: 3] {TCP} 103.152.178.181:80 -> 192.168.120.5:33156
07/01/2023-05:22:20.017127 [**] [1:100002:1] Access to himazin331.com [**] [Classification: (null)] [Priority: 3] {TCP} 103.152.178.181:80 -> 192.168.120.5:33156
07/01/2023-05:22:20.017149 [**] [1:2013028:7] ET POLICY curl User-Agent Outbound [**] [Classification: Attempted Information Leak] [Priority: 2] {TCP} 192.168.120.5:33156 -> 103.152.178.181:80
07/01/2023-05:22:20.017149 [**] [1:100002:1] Access to himazin331.com [**] [Classification: (null)] [Priority: 3] {TCP} 192.168.120.5:33156 -> 103.152.178.181:80
07/01/2023-05:22:20.017831 [**] [1:100002:1] Access to himazin331.com [**] [Classification: (null)] [Priority: 3] {TCP} 192.168.120.5:33156 -> 103.152.178.181:80
07/01/2023-05:22:20.018316 [**] [1:100002:1] Access to himazin331.com [**] [Classification: (null)] [Priority: 3] {TCP} 103.152.178.181:80 -> 192.168.120.5:33156
07/01/2023-05:22:20.018372 [**] [1:100002:1] Access to himazin331.com [**] [Classification: (null)] [Priority: 3] {TCP} 192.168.120.5:33156 -> 103.152.178.181:80
$ cat /usr/local/var/log/suricata/eve.json | grep 100002
{"timestamp":"2023-07-01T05:22:20.016863+0900","flow_id":435169198357210,"in_iface":"eth0","event_type":"alert","src_ip":"103.152.178.181","src_port":80,"dest_ip":"192.168.120.5","dest_port":33156,"proto":"TCP","alert":{"action":"allowed","gid":1,"signature_id":100002,"rev":1,"signature":"Access to himazin331.com","category":"","severity":3},"http":{"hostname":"himazin331.com","url":"/","http_user_agent":"curl/7.74.0","http_method":"GET","protocol":"HTTP/1.1","length":0},"app_proto":"http","flow":{"pkts_toserver":3,"pkts_toclient":2,"bytes_toserver":284,"bytes_toclient":140,"start":"2023-07-01T05:22:20.015066+0900"}}
{"timestamp":"2023-07-01T05:22:20.017127+0900","flow_id":435169198357210,"in_iface":"eth0","event_type":"alert","src_ip":"103.152.178.181","src_port":80,"dest_ip":"192.168.120.5","dest_port":33156,"proto":"TCP","alert":{"action":"allowed","gid":1,"signature_id":100002,"rev":1,"signature":"Access to himazin331.com","category":"","severity":3},"http":{"hostname":"himazin331.com","url":"/","http_user_agent":"curl/7.74.0","http_method":"GET","protocol":"HTTP/1.1","length":0},"app_proto":"http","flow":{"pkts_toserver":3,"pkts_toclient":3,"bytes_toserver":284,"bytes_toclient":559,"start":"2023-07-01T05:22:20.015066+0900"}}
{"timestamp":"2023-07-01T05:22:20.017149+0900","flow_id":435169198357210,"in_iface":"eth0","event_type":"alert","src_ip":"192.168.120.5","src_port":33156,"dest_ip":"103.152.178.181","dest_port":80,"proto":"TCP","alert":{"action":"allowed","gid":1,"signature_id":100002,"rev":1,"signature":"Access to himazin331.com","category":"","severity":3},"http":{"hostname":"himazin331.com","url":"/","http_user_agent":"curl/7.74.0","http_content_type":"text/html","http_method":"GET","protocol":"HTTP/1.1","status":301,"redirect":"https://himazin331.com/","length":162},"app_proto":"http","flow":{"pkts_toserver":4,"pkts_toclient":3,"bytes_toserver":350,"bytes_toclient":559,"start":"2023-07-01T05:22:20.015066+0900"}}
{"timestamp":"2023-07-01T05:22:20.017831+0900","flow_id":435169198357210,"in_iface":"eth0","event_type":"alert","src_ip":"192.168.120.5","src_port":33156,"dest_ip":"103.152.178.181","dest_port":80,"proto":"TCP","alert":{"action":"allowed","gid":1,"signature_id":100002,"rev":1,"signature":"Access to himazin331.com","category":"","severity":3},"http":{"hostname":"himazin331.com","url":"/","http_user_agent":"curl/7.74.0","http_content_type":"text/html","http_method":"GET","protocol":"HTTP/1.1","status":301,"redirect":"https://himazin331.com/","length":162},"app_proto":"http","flow":{"pkts_toserver":5,"pkts_toclient":3,"bytes_toserver":416,"bytes_toclient":559,"start":"2023-07-01T05:22:20.015066+0900"}}
{"timestamp":"2023-07-01T05:22:20.018316+0900","flow_id":435169198357210,"in_iface":"eth0","event_type":"alert","src_ip":"103.152.178.181","src_port":80,"dest_ip":"192.168.120.5","dest_port":33156,"proto":"TCP","alert":{"action":"allowed","gid":1,"signature_id":100002,"rev":1,"signature":"Access to himazin331.com","category":"","severity":3},"http":{"hostname":"himazin331.com","url":"/","http_user_agent":"curl/7.74.0","http_content_type":"text/html","http_method":"GET","protocol":"HTTP/1.1","status":301,"redirect":"https://himazin331.com/","length":162},"files":[{"filename":"/","sid":[],"gaps":false,"state":"CLOSED","stored":false,"size":162,"tx_id":0}],"app_proto":"http","flow":{"pkts_toserver":5,"pkts_toclient":4,"bytes_toserver":416,"bytes_toclient":625,"start":"2023-07-01T05:22:20.015066+0900"}}
{"timestamp":"2023-07-01T05:22:20.018372+0900","flow_id":435169198357210,"in_iface":"eth0","event_type":"alert","src_ip":"192.168.120.5","src_port":33156,"dest_ip":"103.152.178.181","dest_port":80,"proto":"TCP","alert":{"action":"allowed","gid":1,"signature_id":100002,"rev":1,"signature":"Access to himazin331.com","category":"","severity":3},"http":{},"app_proto":"http","flow":{"pkts_toserver":6,"pkts_toclient":4,"bytes_toserver":482,"bytes_toclient":625,"start":"2023-07-01T05:22:20.015066+0900"}}

カスタムルールの変更

次にもう少し実際の運用に近づけて、any(すべての通信)とするのではなくホームネットワークに限ったルールに変更してみましょう。

suricata.yamlを開き、HOME_NET192.168.120.0/24として定義します。

$ sudo vi /usr/local/etc/suricata/suricata.yaml
vars:
# more specific is better for alert accuracy and performance
address-groups:
#HOME_NET: "[192.168.0.0/16,10.0.0.0/8,172.16.0.0/12]" # comment out
HOME_NET: "[192.168.120.0/24]" # edit
#HOME_NET: "[10.0.0.0/8]"
#HOME_NET: "[172.16.0.0/12]"
#HOME_NET: "any"

次にカスタムルールを変更します。

$ sudo vim /usr/local/var/lib/suricata/rules/user_custom.rules
alert icmp any any -> $HOME_NET any (msg: "ICMP ping detected from external network"; sid: 100001; rev: 2;)
alert http $HOME_NET any -> any any (msg: "Access to himazin331.com"; http.host; content: "himazin331.com"; sid: 100002; rev: 2;)

最後に更新を忘れずに。

$ sudo suricata-update

実行 #2

$ sudo suricata -c /usr/local/etc/suricata/suricata.yaml -i eth0 -i wlan0 -v

ICMP検知 #2

操作は先程と同様なので簡易的に記述します。

  • ネットワーク192.168.1.0/24 : PC: 192.168.1.9 ---> Rasp Pi: 192.168.1.6
    ^C1/7/2023 -- 05:36:32 - <Notice> - Signal Received. Stopping engine.
    1/7/2023 -- 05:36:33 - <Info> - time elapsed 14.521s
    1/7/2023 -- 05:36:34 - <Info> - Alerts: 0
    1/7/2023 -- 05:36:35 - <Info> - cleaning up signature grouping structure... complete
    アラート数が0となっています。
  • ネットワーク192.168.120.0/24 : PC: 192.168.120.3 ---> Rasp Pi: 192.168.120.5
    ^C1/7/2023 -- 05:37:32 - <Notice> - Signal Received. Stopping engine.
    1/7/2023 -- 05:37:32 - <Info> - time elapsed 14.525s
    1/7/2023 -- 05:37:33 - <Info> - Alerts: 2
    1/7/2023 -- 05:37:34 - <Info> - cleaning up signature grouping structure... complete
    アラート数が2となっています。

192.168.120.0/24のネットワークでのみ、ルールが適用されアラートが出力されていることが確認できました。

HTTP検知 #2

  • ネットワーク192.168.1.0/24 : PC: 192.168.1.9 ---> himazin331.com: 103.152.178.181
    ^C1/7/2023 -- 05:39:16 - <Notice> - Signal Received. Stopping engine.
    1/7/2023 -- 05:39:16 - <Info> - time elapsed 15.893s
    1/7/2023 -- 05:39:17 - <Info> - Alerts: 1
    1/7/2023 -- 05:39:18 - <Info> - cleaning up signature grouping structure... complete
    $ cat /usr/local/var/log/suricata/fast.log
    07/01/2023-05:39:13.242902 [**] [1:100001:2] ICMP ping detected from external network [**] [Classification: (null)] [Priority: 3] {ICMP} 192.168.120.1:3 -> 192.168.120.5:3
    ICMP通信のルールはこのケースだと除外されないのでアラートが出力されますが、HTTP通信のルールには適用されずアラートは出力されません。
  • ネットワーク192.168.120.0/24 : PC: 192.168.120.3 ---> himazin331.com: 103.152.178.181
    ^C1/7/2023 -- 05:41:27 - <Notice> - Signal Received. Stopping engine.
    1/7/2023 -- 05:41:27 - <Info> - time elapsed 16.617s
    1/7/2023 -- 05:41:28 - <Info> - Alerts: 5
    1/7/2023 -- 05:41:29 - <Info> - cleaning up signature grouping structure... complete
    $ cat /usr/local/var/log/suricata/fast.log
    07/01/2023-05:41:15.925092 [**] [1:100001:2] ICMP ping detected from external network [**] [Classification: (null)] [Priority: 3] {ICMP} 192.168.120.1:3 -> 192.168.120.5:3
    07/01/2023-05:41:15.974681 [**] [1:2013028:7] ET POLICY curl User-Agent Outbound [**] [Classification: Attempted Information Leak] [Priority: 2] {TCP} 192.168.120.5:42754 -> 103.152.178.181:80
    07/01/2023-05:41:15.974681 [**] [1:100002:2] Access to himazin331.com [**] [Classification: (null)] [Priority: 3] {TCP} 192.168.120.5:42754 -> 103.152.178.181:80
    07/01/2023-05:41:15.976533 [**] [1:100002:2] Access to himazin331.com [**] [Classification: (null)] [Priority: 3] {TCP} 192.168.120.5:42754 -> 103.152.178.181:80
    07/01/2023-05:41:15.977208 [**] [1:100002:2] Access to himazin331.com [**] [Classification: (null)] [Priority: 3] {TCP} 192.168.120.5:42754 -> 103.152.178.181:80
    こちらは期待通り、HTTP通信のルールが適用されてアラートが出力されました。

おわりに

いかがでしたか?ラズパイにSuricataを入れて動かしてみました。

今回は、とても簡単なルールにとても簡単なネットワーク構成でしたが、Suricataはもっと高度なルールを作成できますし、より詳細なログを出力が可能です。
例えば、本記事中でHTTP通信のパケット情報がeve.jsonに記載されていましたが、パケットのmetadataを出力することもでき、HTTP Request/Response Bodyも確認できます。

また、監視インターフェースをプロミスキャスモードでアップすることで、同一ネットワーク上の通信を監視することもできます。というかそれができてIDSです。

このRaspberry PiとSuricataのお話は今後も何回か書こうと思います。
現時点では、Suricataがアラートを発報したらラズパイのGPIOでLEDを点灯させてみるとか、Suricataが出力したeve.jsonをElasticsearchやらの分析ツールに食わせて統計データとして眺めてみるとかやろうかなと考えています。

参考