💎

Arkime で lua を用いた SMTP 処理を実装する

2024/02/12に公開

はじめに

Arkime はパケットキャプチャを実現する OSS です。

キャプチャした通信の中から SMTP 通信を抽出する処理を実装します。公式では C 言語による SMTP 処理のコードが用意されています。Arkime は lua によるプラグインもサポートしているため、よりシンプルに実装できる lua を用いて SMTP に対する処理を作ってみたいと思います。

具体的には、 SMTP の通信をフィルタしそのメール情報を抽出&ローカルに保存する処理を実装していきます。

動作環境

  • ubuntu 22 (amd)

インストール

ここでは、 ubuntu 22 のサーバ内に必要なものをインストールします。

Arkime

まずは Arkime をインストールします。

以下のページから、好きなパッケージをダウンロード出来ます。
https://arkime.com/downloads

今回は、以下の ubuntu22 用の version 4.5.0 をダウンロードしました。

https://s3.amazonaws.com/files.molo.ch/builds/ubuntu-22.04/arkime_4.5.0-1_amd64.deb

パッケージがダウンロードできたら、それをインストールします。

apt install -y [arkime_4.5.0-1.amd64.deb]

docker & docker-compose

次に docker と docker-compose をインストールします。これは必須ではないですが、後述する Elasticsearch & Kibana は docker-compose で構築する方が楽なので入れます。

インストール方法については、以下を参考にしました。
https://qiita.com/kujiraza/items/a8236f65e2c46735ee91

Elasticsearch & Kibana

Arkime は通信のメタデータを Elasticsearch に保存することが出来ます。
ここではメタデータの確認のために、 Kibana も一緒にインストールします。

Elasticsearch と Kibana は docker-compose でまとめて起動した方が楽なので、以下のようにそれ用の yaml を用意します。今回は 8.12.1 のバージョンを使用します。

version: "3"

services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.12.1
    ports:
      - 9200:9200
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=false
      - xpack.ml.enabled=false
    ulimits:
      memlock:
        soft: -1
        hard: -1

  kibana:
    image: docker.elastic.co/kibana/kibana:8.12.1
    environment:
      ELASTICSEARCH_HOSTS: http://elasticsearch:9200
    ports:
       - 5601:5601

あとは compose コマンドで起動します。

docker compose up -d

lua

Arkime で lua プラグインを使うために、 OS に lua をインストールします。
公式サイトにも専用の README があり、 lua のバージョンは 5.3 以上の必要があります。
https://github.com/arkime/arkime/tree/v4.5.0/capture/plugins/lua

インストールは、 apt で可能です。

apt install -y lua5.3

swaks

swaks は、 CLI でメール送信ができるソフトウェアです。
https://www.jetmore.org/john/code/swaks/

今回 SMTP の通信を発生させたいため、swaks を利用します。

インストールは、 apt で可能です。

apt install -y swaks

postfix

ローカルで SMTP サーバを用意するために、 postfix を用います。

インストールは、 apt で可能です。

apt install -y postfix

Arkime のセットアップ

ubuntu 22 で Arkime を起動するために必要なセットアップを行います。

セットアップ方法は、公式ドキュメントを参考にします。
https://raw.githubusercontent.com/arkime/arkime/main/release/README.txt

セットアップ後、 arkime-capture(パケットキャプチャ用サービス) および arkime-viewer(セッション閲覧用サービス) が起動していることを確認します。

systemctl status arkimecapture.service
systemctl status arkimeviewer.service

postfix のセットアップ

swaks によるメール送信テストを行うために、ローカルで postfix のセットアップを行います。
このセットアップにより、テスト用に送信したメールを SMTP サーバが受信しローカルに保存できるようになります。

セットアップ方法は、以下の記事を参考にしました。
https://www.kagoya.jp/howto/it-glossary/mail/postfix/

この記事の設定に加え、今回のテスト用ドメイン example.local を以下のように設定します。

- mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
+ mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain, example.local

この追加により、ローカルの SMTP サーバに example.local のドメインのメールが到着したら、自分宛のメールと判断しローカルに保存してくれるようになります。

セットアップが完了したら、以下のコマンドで postfix を再起動します。

sudo newaliases
sudo /etc/init.d/postfix restart

SMTP 通信の送信テスト

まずは SMTP 通信を行い、 Arkime がキャプチャできるかを確認してみます。
インストールしておいた swaks を使います。

以下のようなコマンドを実行します。

swaks --to massu@example.local --server [smtp-server-ip] --header 'Subject: Hello World!' --body 'これはテストメールです!'

コマンド実行が成功すると、 着弾したメールが SMTP サーバ( postfix )が起動しているホスト上の ${HOME}/Maildir/new 配下に保存されます。

lua プラグインの動作テスト

次に lua プラグインの動作テストを行います。
ここでは HTTP 通信に対して、通信内容を標準出力するだけのプラグインを作成してみます。

スクリプトは以下になります。

function httpFeed(session, data)
    print("This is HTTP session!")
    print(session)
    print(data)
end

MolochSession.register_body_feed("http", "httpFeed")

このスクリプトを http_feed.lua として /opt/arkime/lua 配下に配置します。
そして /opt/arkime/etc/config.ini に以下を追加します。

+ plugins=lua.so
+ luaFiles=/opt/arkime/lua/http_feed.lua;

これで arkime-capture を再起動します。

systemctl restart arkimecapture.service

Arkime が起動しているホストに対して、試しに HTTP 通信を行なってみます。今回はこのホスト上で Elasticsearch も起動しているため、 Elasticsearch のヘルスチェック API を実行しました。

curl http://[host-ip]:9200

API 実行後、 /opt/arkime/logs/capture.log を見てみると、以下のようにスクリプトに記載した形式の出力内容が確認できました。

This is HTTP session!
MolochSession: 0x7fb5c006e5d8
{
  "name" : "b567079637c2",
  "cluster_name" : "docker-cluster",
  "cluster_uuid" : "lUmizd9GTK6UG7ZB1cjPHg",
  "version" : {
    "number" : "8.12.1",
    "build_flavor" : "default",
    "build_type" : "docker",
    "build_hash" : "6185ba65d27469afabc9bc951cded6c17c21e3f3",
    "build_date" : "2024-02-01T13:07:13.727175297Z",
    "build_snapshot" : false,
    "lucene_version" : "9.9.2",
    "minimum_wire_compatibility_version" : "7.17.0",
    "minimum_index_compatibility_version" : "7.0.0"
  },
  "tagline" : "You Know, for Search"
}

lua プラグインによるメール抽出

lua プラグインの動作テストが出来たので、今回の目的である「メール抽出」をやってみます。

メールデータの抽出用の lua スクリプトとして、以下を作成しました。

local basePath = '/opt/arkime/mail/'

function parseSMTP(session, str, direction)
    print("Called parseSMTP")

    local f, errorMessage, errorCode = io.open(basePath .. os.date('%Y-%m-%d-%H-%M-%S') .. '.eml', 'a')

    if f ~= nil then
        f:write(str)
        f:close()
    else
        print(errorMessage .. ', errno=' .. errorCode)
    end

    return 0
end

function smtpClassify(session, str, direction)
    if str:len() < 5 then
        return 0
    end

    if str:sub(1, 4) == string.char(0x48, 0x45, 0x4c, 0x4f) or str:sub(1, 4) == string.char(0x45, 0x48, 0x4c, 0x4f) then
        print("This is SMTP session! Try to parse data ...")
        session:register_parser(parseSMTP)
        return 0
    end
end

MolochSession.register_tcp_classifier("smtp", 0, string.char(0x48, 0x45, 0x4c, 0x4f), "smtpClassify")
MolochSession.register_tcp_classifier("smtp", 0, string.char(0x45, 0x48, 0x4c, 0x4f), "smtpClassify")

このスクリプトを smtp.lua として /opt/arkime/lua 配下に配置します。
そして /opt/arkime/etc/config.ini に以下を追加します。

+ luaFiles=/opt/arkime/lua/smtp.lua;

これで arkime-capture を再起動します。

systemctl restart arkimecapture.service

また、今回のスクリプトでは、 /opt/arkime/mail 配下にメールファイルを保存します。
プロセスからファイル書込みができるように、 permission を設定する必要があります。

chmod 777 /opt/arkime/mail

それでは、Arkime が起動しているホストに対して、試しに SMTP 通信を行なってみます。
swaks を用いて、以下のようなコマンドを実行します。

swaks --to massu@example.local --server [smtp-server-ip] -h 'Subject: This is test mail' -d '
これはテスト用のメールです。

現在、Arkime と swaks と lua を用いて、メール抽出のテストを実施中です。
現在、Arkime と swaks と lua を用いて、メール抽出のテストを実施中です。
現在、Arkime と swaks と lua を用いて、メール抽出のテストを実施中です。

メール本文を終了します。'

swaks によるメール送信が完了したら、通信内容から抽出したメールデータが /opt/arkime/mail 配下に保存されます。

root@ubuntu-amd:/opt/arkime# ls -ltr mail/
-rw-r--r-- 1 nobody daemon 783 Feb 12 22:42 2024-02-12-22-42-30.eml

中身は以下のようになっています。

EHLO Subject: This is test mail
...
MAIL FROM:<xxx@xxx>
250 2.1.0 Ok
RCPT TO:<massu@example.local>
250 2.1.5 Ok
DATA
354 End data with <CR><LF>.<CR><LF>

これはテスト用のメールです。

現在、Arkime と swaks と lua を用いて、メール抽出のテストを実施中です。
現在、Arkime と swaks と lua を用いて、メール抽出のテストを実施中です。
現在、Arkime と swaks と lua を用いて、メール抽出のテストを実施中です。

メール本文を終了します。
.
250 2.0.0 Ok: queued as D099B18C6FB
QUIT
221 2.0.0 Bye

lua プラグインを用いて、メールの抽出が出来ました。

終わりに

今回は、Arkime の lua プラグインを用いて SMTP 通信内容からメールを抽出する処理を実装しました。
lua はスクリプト言語ということもあり、比較的容易な文法で実装できるため、Arkime の機能拡張として有効な手段であると感じました。

Discussion