UbuntuにIPS(Suricata)を導入する

## 前書き
Suricata公式ドキュメントをみて試行錯誤してましたが、
最終的にはDigital Ocean社の記事を参考にさせていただきました。

## 環境
OS: Ubuntu 20.04
ファイアウォール: <strong>nftables</strong>

## リポジトリ追加
- Suricataのパッケージがあるリポジトリを追加する。

```
sudo add-apt-repository ppa:oisf/suricata-stable
```

## Suricataインストール

```
sudo apt install suricata
sudo systemctl enable suricata.service
```

## Suricata初期設定
- 監視対象のインターフェース名を確認する。
```
ip -p -j route show default
```

- 「interface」を環境に合わせて修正する。

```
sudo nano /etc/suricata/suricata.yaml

# Linux high speed capture support
af-packet:
  - interface: eth0　# ここ
    # Number of receive threads. "auto" uses the number of cores
    #threads: auto
    # Default clusterid. AF_PACKET will load balance packets based on flow.
    cluster-id: 99
. . .
```

- Suricataの起動中にルールを読み込み直せるように設定する。
  - ファイル末尾に以下を追加する。
```
detect-engine:
  - rule-reload: true
```
 - これで以下のコマンドでSuricata起動中にルールファイルを読み込み直せる。(数秒かかる)
```
sudo kill -usr2 $(pidof suricata)
```

- jq(JSONパーサー)をインストールする。
  - JSONフォーマットの「eve.log」というのを確認するのが、Suricataの主流のようなのでインストールしておく。
  - 「eve.log」はなんでも記録するようなのでサイズに注意。

```
sudo apt update
sudo apt install jq
```

## Suricataルール更新
- ルールファイルをダウンロードする。
  - 「suricata-update」はルールファイル更新用のツール。
```
sudo suricata-update
```

```
19/10/2021 -- 19:31:03 - <Info> -- Using data-directory /var/lib/suricata.
19/10/2021 -- 19:31:03 - <Info> -- Using Suricata configuration /etc/suricata/suricata.yaml
19/10/2021 -- 19:31:03 - <Info> -- Using /etc/suricata/rules for Suricata provided rules.
. . .
19/10/2021 -- 19:31:03 - <Info> -- No sources configured, will use Emerging Threats Open
19/10/2021 -- 19:31:03 - <Info> -- Fetching https://rules.emergingthreats.net/open/suricata-6.0.3/emerging.rules.tar.gz.
 100% - 3044855/3044855               
. . .
19/10/2021 -- 19:31:06 - <Info> -- Writing rules to /var/lib/suricata/rules/suricata.rules: total: 31011; enabled: 23649; added: 31011; removed 0; modified: 0
19/10/2021 -- 19:31:07 - <Info> -- Writing /var/lib/suricata/rules/classification.config
19/10/2021 -- 19:31:07 - <Info> -- Testing with suricata -T.
19/10/2021 -- 19:31:32 - <Info> -- Done.
```

- ET Open Rules が  `/var/lib/suricata/rules/suricata.rules`に追加される。
- なお、有償のルールを適用する際は以下のように行う。

```
sudo suricata-update list-sources
sudo suricata-update enable-source tgreen/hunting    # tgreen/huntingを適用する例
```

- ルールにエラーが無いか確認する。

```
sudo suricata -T -c /etc/suricata/suricata.yaml -v
```

## 自前のルールを追加する(任意)
- ルールファイルを作成してルールを書き込む。

```
sudo nano /var/lib/suricata/rules/local.rules
```
- ルールを書き込む。

```
drop ip any any -> any any (msg:"GPL ATTACK_RESPONSE id check returned root"; content:"uid=0|28|root|29|"; classtype:bad-unknown; sid:2100498; rev:7; metadata:created_at 2010_09_23, updated_at 2010_09_23;)

```

- Suricataにルールファイルを読ませる。

```
sudo nano /etc/suricata/suricata.yaml
```

- `rule-files`を探してファイル名を追加する。

```
rule-files:
  - suricata.rules    # local.rulesと同じルールがあるのでテスト時はコメントアウト
  - local.rules
```

- ルールをチェックする。

```
sudo suricata -T -c /etc/suricata/suricata.yaml -v
```

- 問題が無ければSuricataのルールを読み込み直す。

```
sudo kill -usr2 $(pidof suricata)
```

## nfqueue有効化
- Suricataがファイアウォールからパケットを受け取るようにする。
  - Suricata設定ファイルを編集する。

```
sudo nano /etc/default/suricata
```

```
# LISTENMODE=af-packet # コメントアウト
LISTENMODE=nfqueue     # 追加
```

- Suricataを再起動する。

```
sudo systemctl restart suricata.service
sudo systemctl status suricata.service
```

## nftables(ファイアウォール)設定

- IPS用の設定(チェーン)をテーブルに追加する。
  - ファイアウォールがSuricataにパケットを渡すようにする
  - チェーン評価時にSuricata側でパケットのaccept/dropを行う
  - パケットをファイアウォールに戻して再評価したり、さらに他のツールに渡したりもできるらしい。(今回はしない)

```
table inet filter {
    # ファイアウォール設定
    chain input {
        ...
    }

    # IPS用設定
    chain ips {
        # ローカルマシン向けパケットを受信した際の処理
        # priorityの値は基本の設定より上げておく(後に評価させる)
        type filter hook input priority 1;

        # "queue"でパケットをSuricataに渡せる
        # "num 0"は省略可能で、Suricataの起動引数に"-q 0"を付けて紐づける
        # "bypass"を付けないとSuricata未起動時に全パケットをdropしてしまう(不通になる)
        queue num 0 bypass;
    }
```

# 動作テスト
- 以下のコマンドを実行する。(↑で追加した自前ルールでチェック)

```
curl --max-time 5 http://testmynids.org/uid/index.html
```

- 以下のような出力が得られる。

```
curl: (28) Operation timed out after 5000 milliseconds with 0 out of 39 bytes received
```

- ログを確認する。

```
jq 'select(.alert .signature_id==2100498)' /var/log/suricata/eve.json
```

- `"action": "blocked"`となっていればパケットをdropできている。

```
  "alert": {
    "action": "blocked",
    ...
```

## ログ設定

/etc/logrotate.d/suricata
```
/var/log/suricata/*.log /var/log/suricata/*.json
{
    daily
    rotate 7
    missingok
    compress
    notifempty
    sharedscripts
    postrotate
            /bin/kill -HUP `cat /var/run/suricata.pid 2>/dev/null` 2>/dev/null || true
    endscript
}
```

logrotateお試し実行
```
logrotate -dv /etc/logrotate.d/suricata
```

<hr>

# 参考
https://www.digitalocean.com/community/tutorials/how-to-install-suricata-on-ubuntu-20-04
https://www.stackovercloud.com/2021/12/10/how-to-configure-suricata-as-an-intrusion-prevention-system-ips-on-ubuntu-20-04/
https://wiki.nftables.org/wiki-nftables/index.php/Main_Page