Splunk Cloud に SC4S を使ってSyslogを送信する
主にネットワーク機器から出力されるログは syslog というフォーマット形式となっていることが多いです。
SC4S は syslog-ng OSE を利用して開発された軽量なログ転送エージェントで、コンテナまたはUnix OSにインストールして使うことができます。
転送されたデータは Splunk Enterprise または Splunk Cloud の HTTP Endpoint でデータを受け取ることができます。
特に Splunk Cloud では、Syslog プロトコルなど HTTPS 以外のネットワークデータを直接受け付けることができないため、SC4S を使うことでSyslogデータを Splunk Cloud まで送ることができます。
もちろん、Universal Forwarder を中継サーバーとして syslog を転送することもできるのですが、中継サーバーのローカルにデータを溜め込む必要がなく大量のデータを転送することに向いています。
公式のドキュメントや、ブログ等のリファレンスは以下となりますので、詳細について気になる方は確認してみてください。
公式ドキュメント
ブログ(SC4Sブログ パート1※下記リンクからパート4までたどることができます)
SC4S Github
参考になったブログ
Syslog ng OSE ドキュメント
インストールする
公式ドキュメントに従って、インストールしていきます。
最初に、ホストOS がデータを転送できるように設定を行います。
syslog を出力するネットワーク機器などからデータを受け取って、そのまま転送をするかたちになるためです。
転送の時に適切なバッファリングになるように設定します。
sudo vi /etc/sysctl.conf
# 以下の設定を追加します
net.core.rmem_default = 17039360
net.core.rmem_max = 17039360
設定を反映します。
sudo sysctl -p
環境によって、大量のデータを転送することになるため、バッファリングが適切ではない場合、データをドロップしてしまう可能性があります。
以下のコマンドで、パケットの損失が発生しているかを確認することができます。
本番運用後に、継続的にこちらを監視するように設定しても良さそうですね。
sudo netstat -su | grep "receive errors"
ipv4トラフィックのデータ転送を有効化します。
sudo vi /etc/sysctl.conf
# 以下の設定を追加します
net.ipv4.ip_forward=1
設定を反映します。
sudo sysctl -p
念の為再起動後も有効化されていることを確認します。
## 再起動後に確認
sudo sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1
SC4Sで使うローカルディレクトリを作成します。
sudo mkdir -p /opt/sc4s/local
sudo mkdir -p /opt/sc4s/config
sudo mkdir -p /opt/sc4s/context
sudo mkdir -p /opt/sc4s/archive
sudo mkdir -p /opt/sc4s/tls
OSに併せていくつかの組み合わせでSC4Sを稼働させることが可能です。
こちら を参考に自分の環境にあったインストール方法を選択します。
RedHat系のOSであれば、「Docker CE + systemd」あたりが良さそうです。
私も、Amazon Linux 2023 環境で検証したため、この組み合わせでいきます。
Dockerのインストールは こちら を参考に進めます。
最初にパッケージを最新の状態にアップデートします
sudo dnf update
既存にdockerが入っている場合はアンインストールしておきます。
sudo dnf remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
リポジトリの設定とインストールを行います。
sudo dnf -y install dnf-plugins-core
sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo dnf install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
docker サービスの有効化と、正常にインストールできたか確認します
sudo systemctl enable --now docker
sudo docker run hello-world
## 以下のような出力があればOKです
Hello from Docker!
This message shows that your installation appears to be working correctly.
こちら の内容と同じように、systemd の unit ファイルを作成します。
sudo /lib/systemd/system/sc4s.service
[Unit]
Description=SC4S Container
Wants=NetworkManager.service network-online.target docker.service
After=NetworkManager.service network-online.target docker.service
Requires=docker.service
[Install]
WantedBy=multi-user.target
[Service]
Environment="SC4S_IMAGE=ghcr.io/splunk/splunk-connect-for-syslog/container3:latest"
# Required mount point for syslog-ng persist data (including disk buffer)
Environment="SC4S_PERSIST_MOUNT=splunk-sc4s-var:/var/lib/syslog-ng"
# Optional mount point for local overrides and configurations; see notes in docs
Environment="SC4S_LOCAL_MOUNT=/opt/sc4s/local:/etc/syslog-ng/conf.d/local:z"
# Optional mount point for local disk archive (EWMM output) files
Environment="SC4S_ARCHIVE_MOUNT=/opt/sc4s/archive:/var/lib/syslog-ng/archive:z"
# Map location of TLS custom TLS
Environment="SC4S_TLS_MOUNT=/opt/sc4s/tls:/etc/syslog-ng/tls:z"
TimeoutStartSec=0
ExecStartPre=/usr/bin/docker pull $SC4S_IMAGE
# Note: /usr/bin/bash will not be valid path for all OS
# when startup fails on running bash check if the path is correct
ExecStartPre=/usr/bin/bash -c "/usr/bin/systemctl set-environment SC4SHOST=$(hostname -s)"
# Note: Prevent the error 'The container name "/SC4S" is already in use by container <container_id>. You have to remove (or rename) that container to be able to reuse that name.'
ExecStartPre=/usr/bin/bash -c "/usr/bin/docker rm SC4S > /dev/null 2>&1 || true"
ExecStart=/usr/bin/docker run \
-e "SC4S_CONTAINER_HOST=${SC4SHOST}" \
-v "$SC4S_PERSIST_MOUNT" \
-v "$SC4S_LOCAL_MOUNT" \
-v "$SC4S_ARCHIVE_MOUNT" \
-v "$SC4S_TLS_MOUNT" \
--env-file=/opt/sc4s/env_file \
--network host \
--name SC4S \
--rm $SC4S_IMAGE
Restart=on-failure
SC4Sコンテナ用のローカルボリュームをアタッチします。
転送先となる Splunk Cloud とネットワーク上での通信断があった際に、このローカルストレージにバイナリデータとして書き込まれます。
sudo docker volume create splunk-sc4s-var
次に、SC4Sの環境変数を設定するコンフィグファイルを作成します。
このファイルに、転送先となるURLを設定したり、データを受信するためのポートを指定したりします。
データ受信ポートはログソースごとで変えることで、より正確なログの仕分けをするのに活用されます。(この後の設定でも確認していきます。
まずは、転送先のHEC URLとHECトークンを入れます。
sudo vi /opt/sc4s/env_file
##
SC4S_DEST_SPLUNK_HEC_DEFAULT_URL=https://your.hec-url:443
SC4S_DEST_SPLUNK_HEC_DEFAULT_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
設定を変更した際は以下のコマンドで反映とサービスの起動をします。
sudo systemctl stop sc4s
sudo systemctl daemon-reload
sudo systemctl enable sc4s
sudo systemctl start sc4s
ステータスを確認します。
sudo docker logs SC4S
## 以下のような出力が出ていたらOK
syslog-ng checking config
sc4s version=v1.36.0
Configuring health check port: 8080
[2025-01-11 18:31:08 +0000] [135] [INFO] Starting gunicorn 23.0.0
[2025-01-11 18:31:08 +0000] [135] [INFO] Listening at: http://0.0.0.0:8080 (135)
[2025-01-11 18:31:08 +0000] [135] [INFO] Using worker: sync
[2025-01-11 18:31:08 +0000] [138] [INFO] Booting worker with pid: 138
starting syslog-ng
ログの確認
では早速ログ取り込みの確認をしていきますが、まず最初に syslog のログフォーマットについて確認しておきます。
syslog にはフォーマット形式が2種類あり、RFC3164(BSD-syslog)、RFC5424(IETF-syslog) として定義されています。
定義されている構造は こちら などを参考にしていただけるとわかりやすいかと思います。
さらに、syslog の 「MSG」 部分のイベントのフォーマットを共通化するために、CEF と LEEF が使われる場合があります。
CEF, LEEF のフォーマットについては こちら が参考になるかと思います。
SC4Sでは、CEF、LEEF形式の場合、明示的にポートを指定する必要があります。
まず、CEF形式からやってみます。
SC4S CEF の取り込み
公式ドキュメント参考先
環境設定ファイルを開き、ポートを指定します。ポートは、syslog 送信元の設定に合わせます。送信先や受信ポートなどの設定に関するファイルは/opt/sc4s/env_file
です。
sudo vi /opt/sc4s/env_file
## CEF用の受付ポートを開放
SC4S_LISTEN_CEF_UDP_PORT = 5141
SC4S_LISTEN_CEF_TCP_PORT = 5141
設定反映のため、再起動します。
sudo systemctl stop sc4s
sudo systemctl daemon-reload
sudo systemctl enable sc4s
sudo systemctl start sc4s
再起動後には毎回ログを確認して正常起動していることを確認しておくのが良いです。(設定ファイルの構文エラーとなって、正しく起動できていないことなどあるため。)
sudo docker logs SC4S
下記のログを入れてみます。
Jan 31 10:20:53 3.3.3.3 CEF:0|Imperva Inc.|SecureSphere|12.0.0|Firewall|SSL Untraceable Connection|Medium|
ログを送信してみます。
echo 'Jan 31 10:20:53 3.3.3.3 CEF:0|Imperva Inc.|SecureSphere|12.0.0|Firewall|SSL Untraceable Connection|Medium|' > /dev/udp/127.0.0.1/5141
Splunk Cloud で検索してみます。
index は *
で検索します。SC4S が想定している形式のログ(Known Vendor で SC4S のOOTBパーサーに合致する場合)であれば、ログの中から自動で sourcetype
、index
、host
、timestamp
、source
が識別され、付与されます。(source
の指定がなかった場合はsc4s
)
まず、最初にどういった風に解釈されたかを確認するために、index=*
で見てみるのがおすすめです。
さらに、文字列を部分一致で検索してみます。
ログ内にあった、timestamp Jan 31 10:20:53
、host 3.3.3.3
が識別されていることがわかります。
sourcetype
とindex
については、こちら に記載のある通りに設定されます。(sourcetype
は imperva:waf:firewall:cef
、index
は netwaf
)
index
がlastchanceindex
になっているのは、ドキュメントに記載のある netwaf
を Splunk Cloud 上でつくっていないからです。
これらの一連のパースする動きは、Github に公開されているコンフィグファイルかコンテナ内に入ってsyslog-ng
のコンフィグファイルから確認することもできます。
試しにnetwaf
の index を Splunk Cloud でつくってみます。
そしてもう一度、ログを送信した後に、Splunk Cloud で確認してみます。
index
が netwaf
で入ってきたことが確認できました。
index の設計上、netfw が必要なく、既存の index に入れておきたい場合は、SC4Sの設定コンフィグ(/opt/sc4s/local/context/splunk_metadata.csv
)を変更します。
この設定ファイルの記載方法は、基本的に こちら の通りです。
key,metadata,value
です。
key
はvendor_product
のように指定する必要があります。CEF の場合、ログから特定することができ、|Imperva Inc.|SecureSphere|
、|Firewall|
が該当します。
CEF の key
については こちら の通りです。
metadata
は、index、source、host、sourcetype、sc4s_template が選択できます。
value
はそれぞれの metadata
に対する実際の設定値を指定します。
sudo vi /opt/sc4s/local/context/splunk_metadata.csv
## Imperva の syslog を main インデックスにいれる
Imperva Inc._SecureSphere_Firewall,index,main
設定反映のために、再起動と、ログを確認しておきます。
sudo systemctl stop sc4s
sudo systemctl daemon-reload
sudo systemctl enable sc4s
sudo systemctl start sc4s
sudo docker logs SC4S
もう一度同じログを送信して、Splunk Cloudで確認します。
index を変更することができました。
もう一つ別のログでやってみます。Tremd Microのサンプルログを入れてみます。
Jan 31 10:20:53 3.3.3.3 CEF:0|Trend Micro|Apex Central|2019|700211|Attack Discovery Detections|3|deviceExternalId=5 rt=Jan 17 2019 03:38:06 GMT+00:00 dhost=VCAC-Window-331 dst=10.201.86.150 customerExternalID=8c1e2d8f-a03b-47ea-aef8-5aeab99ea697 cn1Label=SLF_RiskLevel cn1=0 cn2Label=SLF_PatternNumber cn2=30.1012.00 cs1Label=SLF_RuleID cs1=powershell invoke expression cat=point of entry cs2Label=SLF_ADEObjectGroup_Info_1 cs2=process - code9.exe - {USER: administrator09} deviceNtDomain=APEXTMCM dntdom=OSCEDomain1 TMCMLogDetectedHost=VCAC-Window-331 TMCMLogDetectedIP=10.201.86.150 ApexCentralHost=TW-CHRIS-W2019devicePayloadId=1C00290C0360-9CDE11EB-D4B8-F51F-C697 TMCMdevicePlatform=Windows 7 6.1 (Build 7601) Service Pack 1
同じように、syslog に送信してみます。
echo 'Jan 31 10:20:53 3.3.3.3 CEF:0|Trend Micro|Apex Central|2019|700211|Attack Discovery Detections|3|deviceExternalId=5 rt=Jan 17 2019 03:38:06 GMT+00:00 dhost=VCAC-Window-331 dst=10.201.86.150 customerExternalID=8c1e2d8f-a03b-47ea-aef8-5aeab99ea697 cn1Label=SLF_RiskLevel cn1=0 cn2Label=SLF_PatternNumber cn2=30.1012.00 cs1Label=SLF_RuleID cs1=powershell invoke expression cat=point of entry cs2Label=SLF_ADEObjectGroup_Info_1 cs2=process - code9.exe - {USER: administrator09} deviceNtDomain=APEXTMCM dntdom=OSCEDomain1 TMCMLogDetectedHost=VCAC-Window-331 TMCMLogDetectedIP=10.201.86.150 ApexCentralHost=TW-CHRIS-W2019devicePayloadId=1C00290C0360-9CDE11EB-D4B8-F51F-C697 TMCMdevicePlatform=Windows 7 6.1 (Build 7601) Service Pack 1' > /dev/udp/127.0.0.1/5141
sourcetype
が cef
と認識されているので、少し使いづらそうです。
その他、ログ内の =
でつながっている部分は全てフィールドとして認識してくれているので、これはこのままでも分析できそうです。
可能であれば、開発済みの add on などがあればそちらにマッピングしたいところです。ここでは、どの add on が適切かまでは検討しませんでしたが、とりあえず適当にsourcetype
だけ変更してみましょう。
sudo vi /opt/sc4s/local/context/splunk_metadata.csv
## Trend Micro のログのソースタイプを変更
Trend Micro_Apex Central,sourcetype,deepsecurity-intrusion_prevention
設定を変更したので再起動します。
sudo systemctl stop sc4s
sudo systemctl daemon-reload
sudo systemctl enable sc4s
sudo systemctl start sc4s
sudo docker logs SC4S
また、ログを送信してみて、Splunk Cloudで確認します。
sourcetype
が変更できたことを確認しました。
SC4S LEEF の取り込み
次に LEEF 形式のログを取り込んでみます。
公式ドキュメント参考先
環境設定ファイルを開き、LEEF用のポートを指定します。ポートは、syslog 送信元の設定に合わせます。
sudo vi /opt/sc4s/env_file
## LEEF用の受付ポートを開放
SC4S_LISTEN_LEEF_UDP_PORT = 5142
SC4S_LISTEN_LEEF_TCP_PORT = 5142
設定反映のため、再起動します。
sudo systemctl stop sc4s
sudo systemctl daemon-reload
sudo systemctl enable sc4s
sudo systemctl start sc4s
sudo docker logs SC4S
下記のログを入れてみます。
<111>Apr 19 10:29:53 3.3.3.3 LEEF:2.0|Lancope|StealthWatch|1.0|41| |src=192.0.2.0 dst=172.50.123.1 sev=5 cat=anomaly srcPort=81 dstPort=21 usrName=joe.black
ログを送信します。
echo '<111>Apr 19 10:29:53 3.3.3.3 LEEF:2.0|Lancope|StealthWatch|1.0|41| |src=192.0.2.0 dst=172.50.123.1 sev=5 cat=anomaly srcPort=81 dstPort=21 usrName=joe.black' > /dev/udp/127.0.0.1/5142
host
と timestamp
がきちんと認識できていることが確認できます。
source
は |Lancope|StealthWatch|
VENDOR PRODUCT 部分が入ります。
sourcetype
は LEEF:2.0|
が入ります。
こちら に記載がある通り、各種メタデータを変更することが可能です。
LEEFの場合は、ログの 0番目のカラム=LEEF:VERSION、1番目のカラムに device_vendor、2番目のカラムに device_product として認識します。
splunk_metadata.csv
を開き、key,metadata,value
で変更が可能です。
今回はとばします。
その他の RFC3164、RFC5424
syslog の「MSG」部分が特にフォーマットに従っていないログや、syslog ヘッダー自体がないログを試してみます。
これらのログは一般的にデフォルトの 514ポート で受け取ります。
まず、Linux や ネットワーク機器 などで出力される SSH ログのようなものです。
juniper のログを参考に入れてみます。
sshd のログで以下のログです。
Jan 20 17:04:51 starfire sshd[4182]: error: Could not load host key: /etc/ssh/ssh_host_dsa_key
ログを送信します。
echo 'Jan 20 17:04:51 starfire sshd[4182]: error: Could not load host key: /etc/ssh/ssh_host_dsa_key' > /dev/udp/127.0.0.1/514
Splunk Cloud で確認します。
host
と timestamp
がきちんと認識できていることが確認できます。
sourcetype
に juniper:legacy
と認識されていることがわかります。
index
は該当する index を作成していなかったのか lastchanceindex
となっています。
sc4s_tags
を確認すると、app.app-syslog-juniper_junos_unstructured-pam
となっているので、こちら のコンフィグを確認してみます。
おそらく、app-syslog-juniper_junos_unstructured.conf
のルールに引っかかって、メタデータがつけられているのではと想像できます。
つぎに、FortiGate のログで試してみます。
下記のようなログです。
date=2022-04-12 time=08:30:10 devname=FORTIGATE-12345 devid=FGT1234567890123 logid=1234567890 type=attack subtype=ips level=notice vd=root srcip=192.168.1.20 dstip=192.168.2.30 attack="UDP flood" proto=17 service=0/0 duration=1 attackid=12005
ログを送信します。
echo 'date=2022-04-12 time=08:30:10 devname=FORTIGATE-12345 devid=FGT1234567890123 logid=1234567890 type=attack subtype=ips level=notice vd=root srcip=192.168.1.20 dstip=192.168.2.30 attack="UDP flood" proto=17 service=0/0 duration=1 attackid=12005' > /dev/udp/127.0.0.1/514
host
と timestamp
がきちんと認識できていることが確認できます。
sourcetype
に fgt_attack
と認識されていることがわかります。
index
は該当する index を作成していなかったのか lastchanceindex
となっています。
こちらのルールに該当できたのだと思われます。
いろいろなログで、syslog の転送と、パースができることを確認しました。
後は、Splunk Cloud 側に対応する製品の add-on などを入れて、より分析しやすいようにすると良さそうですね。
まとめ
SC4S を使うことで、大方のログが簡単に取り込み、パースができることを確認できました。
一方で SC4S の OOTBで用意されたパースと少し異なる形で入ってきた場合、自分でパースを調整する必要がありそうだと思いました。
パース仕組みそのものは syslog-ng の仕様に従って、処理されていますが、私自身あまり syslog-ng でフィルタやパースをつくったことがないため、よりカスタマイズしていくには、このあたりの知識も必要になってきそうです。
以上です。
本記事がどなたかの助けになれば幸いです。