こんにちは。インフラエンジニアの永峰です。
普段はパブリッククラウドや仮想化基盤上でのインフラ構築などをやっています。
ちょっと前にElastic Stackをガッツリ扱っていたんですが、その中でElastic Stackのプロダクトの1つであるLogstashにiptablesを組み合わせることで、いくつかの制約下におけるSyslog転送を実装する機会がありましたので、この記事ではその内容についてご紹介したいと思います。
[目次]
はじめに
弊社には社内向けにログ収集・検索・分析・可視化を行うための基盤があり、その基盤はBeats, Logstash, Elasticsearch, Kibana、いわゆるElastic Stackを用いて構築しています。
この度「Beatsが導入できないのでSyslogでログを送りたい」と言う送信元ノードが新たに基盤に加わったので、Logstash(とそのサーバ)側で受け入れのためのカスタマイズを実施しました。
それだけだとちょっと分かる人には
「そんなのSyslog input plugin使えば一発じゃん?」
と言われかねませんが、流石にそう単純にはいかない制約があり、一工夫することになりました。
なお、OSやその他関連ツールのバージョンは下記のとおりです。
- Ubuntu 22.04.3 LTS
- logstash 8.11.1
- iptables v1.8.7 (nf_tables)
制約
①514番ポートしか使えない
送信元ノードでは仕様により、送信先ポートをデフォルトの514番ポートから変更することが不可能でした。
そのためLogstash側でも514番ポートでlistenする必要がありますが、
本環境ではLogstashはデフォルトではlogstashユーザで実行しており、システムポート(ウェルノウンポート)である514番ポートでlistenすることはできません。
「それならLogstashをrootユーザで実行すれば良いのでは?」
場合によってはそれも一案なのですが、ここで2つ目の制約が関わってきます。
②rootユーザでLogstashを実行しない
rootユーザでプロセスを実行する場合、保持する権限の高さから複数のリスクを抱えることになり、セキュリティレベルが下がります。
利便性と天秤にかけて、今回はセキュリティレベルの維持を優先することにしました。
そのため、rootユーザでのLogstash実行は避ける前提で対応方針を策定します。
方針
まず、サーバとしては514番ポートで受け付けます。
次にlogstashユーザによるLogstashの実行を維持するため、Logstash自体は10514番ポートでlistenすることにします。
そしてiptablesで、サーバの514番ポートで受け付けた通信を10514番ポートに転送する方針とします。
実装
Logstash
パイプライン設定ファイルで、Beatsに対する既存のinput設定に加え、Syslogに対するinput設定を追加します。
ポートは10514指定を忘れずに。
input {
beats {
#
# 中略
#
}
syslog {
port => 10514
#
# 中略
#
}
}
iptables
514 -> 10514へのポート転送を設定します。
念の為tcp, udpどちらでも対応するようにします。
設定します。
iptables -t nat -A PREROUTING -i eth0 -p udp -m udp --dport 514 -m comment --comment "Redirect syslog traffic to port 10514(UDP)" -j REDIRECT --to-ports 10514
iptables -t nat -A PREROUTING -i eth0 -p tcp -m tcp --dport 514 -m comment --comment "Redirect syslog traffic to port 10514(TCP)" -j REDIRECT --to-ports 10514
確認します。
iptables -L -t nat
結果がこちら。
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
REDIRECT udp -- anywhere anywhere udp dpt:syslog /* Redirect syslog traffic to port 10514(UDP) */ redir ports 10514
REDIRECT tcp -- anywhere anywhere tcp dpt:shell /* Redirect syslog traffic to port 10514(TCP) */ redir ports 10514
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
なお、iptablesの設定はこのままでは永続化されず、再起動すると消えてしまうので、
実際にはiptables-persistentを導入して永続化まで行なっています。
永続化のための設定ファイルが出力されていることを確認します。
cat /etc/iptables/rules.v4
結果がこちら。
*nat
:PREROUTING ACCEPT [160413:16586913]
:INPUT ACCEPT [75589:6177775]
:OUTPUT ACCEPT [190901:16608784]
:POSTROUTING ACCEPT [190901:16608784]
-A PREROUTING -i eth0 -p udp -m udp --dport 514 -m comment --comment "Redirect syslog traffic to port 10514(UDP)" -j REDIRECT --to-ports 10514
-A PREROUTING -i eth0 -p tcp -m tcp --dport 514 -m comment --comment "Redirect syslog traffic to port 10514(TCP)" -j REDIRECT --to-ports 10514
COMMIT
問題なさそうですね。
それでは動作を確認します。
動作確認
別環境からSyslogを送付してみます。
logger \"hogehoge fugafuga\" -i -t \"sample\" -n <TARGET_LOGSTASH_SERVER>
Elasticsearchで受け取れているか、Kibanaの開発ツールから確認します。
Elasticsearchへの格納に成功していることが確認できました。
おわりに
以上、非rootユーザでLogstashを実行し、かつSyslogの送受信に使うポートはデフォルトの514を使用するという制約のもとでの、LogstashによるSyslog転送の実装でした。
Logstashへの入力はリモートサーバからならBeats、またはローカルならFileプラグイン辺りの採用事例が多いと思われますが、
今回取り上げたSyslogプラグインや、検証用にも便利なStdinプラグインなど、用途に応じて多様なプラグインを選択できます。
そこに加えてサーバ側の設定を工夫することで、さらに多様な要件に対応可能なログ収集パイプラインを構築することができますので、色々なプラグインの組み合わせとサーバ側の実装を是非試してみて下さい。