Arkime で lua を用いた SMTP 処理を実装する
はじめに
Arkime はパケットキャプチャを実現する OSS です。
キャプチャした通信の中から SMTP 通信を抽出する処理を実装します。公式では C 言語による SMTP 処理のコードが用意されています。Arkime は lua によるプラグインもサポートしているため、よりシンプルに実装できる lua を用いて SMTP に対する処理を作ってみたいと思います。
具体的には、 SMTP の通信をフィルタしそのメール情報を抽出&ローカルに保存する処理を実装していきます。
動作環境
- ubuntu 22 (amd)
インストール
ここでは、 ubuntu 22 のサーバ内に必要なものをインストールします。
Arkime
まずは Arkime をインストールします。
以下のページから、好きなパッケージをダウンロード出来ます。
今回は、以下の 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 で構築する方が楽なので入れます。
インストール方法については、以下を参考にしました。
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 以上の必要があります。
インストールは、 apt
で可能です。
apt install -y lua5.3
swaks
swaks は、 CLI でメール送信ができるソフトウェアです。
今回 SMTP の通信を発生させたいため、swaks を利用します。
インストールは、 apt
で可能です。
apt install -y swaks
postfix
ローカルで SMTP サーバを用意するために、 postfix を用います。
インストールは、 apt
で可能です。
apt install -y postfix
Arkime のセットアップ
ubuntu 22 で Arkime を起動するために必要なセットアップを行います。
セットアップ方法は、公式ドキュメントを参考にします。
セットアップ後、 arkime-capture
(パケットキャプチャ用サービス) および arkime-viewer
(セッション閲覧用サービス) が起動していることを確認します。
systemctl status arkimecapture.service
systemctl status arkimeviewer.service
postfix のセットアップ
swaks によるメール送信テストを行うために、ローカルで postfix のセットアップを行います。
このセットアップにより、テスト用に送信したメールを SMTP サーバが受信しローカルに保存できるようになります。
セットアップ方法は、以下の記事を参考にしました。
この記事の設定に加え、今回のテスト用ドメイン 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