2011/09/16 CentOS5.5





rsyslogを設定する

ここではrsyslogの実践的なconf記述を記します。
インストールについては別項「rsyslogをインストールする」を参照してください。

rsyslog.confの例
rsyslog.confの記述と式のルール
集約したsyslogを再転送する
受け取ったsyslogを機器別に自動保存する
読みやすい形式でログを出力する
syslogメッセージの内容に対して、メールを送信する


rsyslog.confの例(デフォルトのコメントアウト部は省いてあります)
#$ModLoad immark   # provides --MARK-- message capability
$ModLoad imuxsock # provides support for local system logging (e.g. via logger command)
$ModLoad imklog   # kernel logging (formerly provided by rklogd)

$template customformat,"%timegenerated% %HOSTNAME% %syslogtag%%msg%\n"
$template logFileName,"/var/log/syslog/%fromhost%/messages_%fromhost%_%$year%%$month%%$day%.log"
$template mailFileName,"/var/log/syslog/%fromhost%/mail_%fromhost%_%$year%%$month%%$day%.log"

# Log anything (except mail) of level info or higher.
# Don't log private authentication messages!
#*.info;mail.none;authpriv.none;cron.none                -/var/log/messages
*.info;mail.none;authpriv.none;cron.none                -?logFileName;customformat
*.info;mail.none;authpriv.none;cron.none                @remoteserver

# The authpriv file has restricted access.
authpriv.*                                              /var/log/secure

# Log all the mail messages in one place.
#mail.*                                                  -/var/log/maillog
mail.*                                                  -?mailFileName;customformat

$ModLoad ommail

$ActionMailSMTPServer mailserver.address
$ActionMailFrom admin@example.local
$template mailsubject,"Syslog Warning"
$template mailbody,"%fromhost%\r\n%msg%"
$ActionMailSubject mailsubject
$ActionExecOnlyOnceEveryInterval  -1

$ActionMailTo admin-ml@example.local
if $fromhost-ip == '192.168.1.100' and $msg contains 'System Warning' then :ommail:;mailbody

$ActionMailTo admin-ml@example.local
if $fromhost-ip != '127.0.0.1' and $msg contains 'authenticated failure' and $syslogfacility-text == 'daemon' then :ommail:;mailbody

$ActionMailTo administrator@example.local
if $fromhost-ip =='192.168.1.254' and $syslogfacility-text == 'syslog' and $syslogseverity-text == 'crit' then :ommail:;mailbody

# Log cron stuff
cron.*                                                  -/var/log/cron

# Everybody gets emergency messages
*.emerg                                                 *

# Save news errors of level crit and higher in a special file.
uucp,news.crit                                          -/var/log/spooler

# Save boot messages also to boot.log
local7.*                                                /var/log/boot.log

# UDP Syslog Server:
$ModLoad imudp.so  # provides UDP syslog reception
$UDPServerRun 514 # start a UDP syslog server at standard port 514




rsyslog.confの記述と条件式のルール
rsyslog.confの考え方は、上から順に条件判断をしていきます。
条件に一致すれば、アクションを実行します。そして引き続き次の条件判断へ移ります。

例えば
・ローカルのログはmessagesへ出力
・リモートから受信したログはremote_messageへ保存
・リモートから受信したログを含めて、全てのログを別のリモートサーバへ再転送
・192.168.1.100から受信したログだけはmessage_192.168.1.100へ保存

この条件を以下のように記述したとします。

*.info;mail.none;authpriv.none;cron.none                -/var/log/messages
*.*                @remoteserver
:fromhost-ip, isequal, "192.168.1.100" /var/log/message_192.168.1.100
:fromhost-ip, !isequal, "127.0.0.1" /var/log/remote_message

これでは望むようには動作しません。

ローカルログは正しく出力しますが、リモートから受け取ったログも同じようにmessageへ出力してしまいます。
リモートサーバへの転送は全てのリモートログとローカルログについて行われます。これは希望通りです。
次にリモートサーバ192.168.1.100から受信したログなら、message_192.168.1.100へ出力します。
最後にローカル以外(リモートログ)なら、remote_messageへ出力します。ここに192.168.1.100も含まれてしまいます。

結果的にmessagesにはローカルとリモートのログが混ざって出力されます。
192.168.1.100から送られてきたログも、messages、message_192.168.1.100、remote_messageへ出力されます。
これではログが無駄に肥大化してしまいます。

上記条件を満たすには、以下のようになります。

*.*               @remoteserver
:fromhost-ip, isequal, "192.168.1.100" /var/log/message_192.168.1.100
& ~
:fromhost-ip, !isequal, "127.0.0.1" /var/log/remote_message
& ~
*.info;mail.none;authpriv.none;cron.none                -/var/log/messages


この場合はどうでしょう。

全てのログをリモートサーバへ転送。
送信元IPが192.168.1.100の場合だけmessage_192.168.1.100へ出力します。
「& ~」は直前の条件、この場合は「:fromhost-ip, isequal, "192.168.1.100" ~」を表し、送信元192.168.1.100に一致したログを破棄(~)します。
次に送信元が127.0.0.1以外、つまりリモートサーバからの送信ログはremote_messageへ出力します。
192.168.1.100のログはすでに破棄されているので、含まれません。
「& ~」は直前の条件、この場合は「:fromhost-ip, !isequal, "127.0.0.1" ~」を表し、送信元がリモートサーバのログは破棄します。
最後にmessagesへの出力。ただしリモートログは全て破棄されているので、出力されるのはローカルログのみです。

当初の条件を厳密にクリアすることが出来ました。
同じことをするのに、他にもいろんな記述が考えられます。

loggerコマンドでファシリティやプライオリティを指定してテストし、出力を確認します。

#logger -p user.info "test"

なお、記述ミスや文法ミスに気を付けましょう。
confの文法チェックをするには以下のようにします。
#rsyslogd -N 1

ちなみにチェック時に「WARNING: rsyslogd is running in compatibility mode」と出力されるのは気にしなくていいです。
これがチェックが互換性モード(ver3)で実施されているというだけなので、サービス起動のパラメータファイル(sysconfig/rsyslog)が正しく書き込まれていれば、実害はありません。
どうしても気になるのなら、コマンドの末尾に「-c5」を加えます。
#rsyslogd -N 1 -c5



集約したsyslogを再転送する

 リモートから集約したログをさらに別のsyslogサーバへ転送できます。集約と保存、集約と解析を別々のサーバで実施する場合はこの機能は必須です。
 syslogではログの再転送はできません。

rsyslog.conf

*.info;mail.none;authpriv.none;cron.none                -/var/log/messages
*.info;mail.none;authpriv.none;cron.none                @remoteserver

この記述では
全ての受信したログデータを、messagesへ出力します。
全ての受信したログデータを、リモートサーバへUDPで送信します。

この設定では受け取ったUDPのシスログを全て一つのmessagesへ出力します。
一つのファイルへログを出力し続けると、ログも肥大化するし閲覧するのは困難になってくるでしょう。
ログはホスト名別か、ファシリティ別に分けるほうが理に適っています。



受け取ったsyslogを機器別に自動保存する

 多数の機器から集約したsyslogを一つのファイルに延々書き込むのは閲覧の点からも現実的ではありません。
 rsyslogでならホスト名、日付別にファイル・ディレクトリをダイナミックに振り分け保存できます。
 しかも自動でディレクトリまで作ってくれるため、機器の変更追加のたびに設定変更する必要がありません。
 機器の数が増えてくると、この機能はかなり重要です。

rsyslog.conf

$template logFileName,"/var/log/syslog/%fromhost%/messages_%fromhost%_%$year%%$month%%$day%.log"
$template mailFileName,"/var/log/syslog/%fromhost%/mail_%fromhost%_%$year%%$month%%$day%.log"

#*.info;mail.none;authpriv.none;cron.none                /var/log/messages
*.info;mail.none;authpriv.none;cron.none                -?logFileName

#mail.*                                                  -/var/log/maillog
mail.*                                                  -?
mailFileName


まずテンプレートでログの出力名を定義します。
ここでは「/var/log/syslog/送信元ホスト名/messages_送信元ホスト名_年月日.log」名で保存します。
なお、ディレクトリは自動で生成されます。

もちろん、ローカルを含めて各サーバ別のログを/var/log/syslog以下に保存するのですから、messagesのログはコメントアウトして良いでしょう。

ここでテーマになるのが、ホスト名や日付を呼び出すプロパティ名です。
本家にプロパティ名の説明があるので参考になります。

%fromhost%
送信元IPを逆引きして得られたホスト名。DNSやhostsで解決できなければIPアドレスになります。

%hostname%
ログを出力したホスト名、つまりsyslogの中に「出力者」として記述してあるホスト名です。
通常はログを送信したシステムのホスト名と同一です。
しかしログ出力しているサーバがマルチホームネットワークであったりsyslogサーバの参照しているDNSによっては、ログ本文中に記述してあるホスト名とsyslogサーバが認識できるリモートホスト名が同一であるとは限りません。

%fromhost-ip%
ログの送信元IPです。ローカルログの場合は127.0.0.1が使用されます。
これをチェックすればローカルログかリモートログかが判別できます。

ホスト名のネットワークが複雑である。NW機器など、サーバ以外のものが多くあるときは、いっそ割り切ってIPアドレスに統一する手もあるでしょう。

特にsyslogfacility-text(ファシリティ名)やprogramname(ログを出力したプログラム)は複雑な条件のときに使用することがあります。


読みやすい形式でログを出力する
2011-09-15T00:37:41+09:00 localhost kernel: Kernel logging (proc) stopped.
デフォルト

カスタム
Sep 15 10:11:49 localhost kernel:imklog 5.8.5, log source = /proc/kmsg started.

rsyslogでデフォルトで出力されるログはいまいち読みづらいです。全ての原因はTを挟んでいるのと、+9時間のJST調整です。
この出力形式を調整し、syslogと同じ形式します。

rsyslog.conf

$template customformat,"%timegenerated% %HOSTNAME% %syslogtag%%msg%"
*.info;mail.none;authpriv.none;cron.none                /var/log/messages;customformat
*.info;mail.none;authpriv.none;cron.none                -?logFileName;customformat

テンプレートで形式を設定し、ログ出力の設定の後ろにセミコロンでフォーマットを繋げます。
rsyslogを再起動して、ログの出力形式を確認します。
なぜか二回再起動しないと有効にならないことがあります。

日付にはできればデフォルトの西暦を用いたいところですが、プロパティが見つかりません。
$nowプロパティや$hourがありますが、これでは秒が取得できません。



syslogメッセージの内容に対して、メールを送信する

全ての機器のsyslogをrsyslogで解析し、特定キーワードを見つけたら警告メールを送信できます。
これはommailというモジュールを使用します。
解析も構文が複雑になるものの、ちゃんと細かく指定できるので、特定のIPアドレスのログ、特定のファシリティの特定キーワードが含まれている場合はこのメールアドレスへ送信するなど造作もないです。
なおメール送信には件名や本文に日本語を用いないほうが無難です。

まずはrsyslog.confの中でommailをロードし、メール送信に関する定義を行います。これは共通です。

rsyslog.conf

$ModLoad ommail

$ActionMailSMTPServer mailserver.address
$ActionMailFrom admin@example.local
$ActionMailTo admin-ml@example.local
$template mail_subject,"Syslog Warning"
$template mail_body,"%fromhost%\r\n%msg%"
$ActionMailSubject mail_subject
$ActionExecOnlyOnceEveryInterval  -1

条件によって送信先アドレスが変化するなら、条件式の手前でメールアドレスを定義定義しなおします(後述)。
判断にはプロパティ式と条件式があります。
プロパティ式は簡単に記述でき、条件式は複雑な条件を記述するのに向きます。
なおプロパティ式の文字列はダブルクォートで囲みます。条件式はどちらでも動作しますが、シングルクォートを指定することが多いようです。


特定キーワードを含むログが出力されたらメール送信

プロパティ式

:msg, contains, "System warning":ommail:;mail_body

条件式

if $msg contains 'Failed password' then :ommal:;mail_body


特定ホストからログが出力されたらメール送信

プロパティ式

:fromhost-ip, isequal, "192.168.1.100" :ommail::;mail_body

条件式
if $fromhost-ip == '192.168.1.100' then :ommail:;mail_body

これだけではメールが頻発しますので、通常は他の条件を加えたり、一定時間メール送信を抑制します。


特定ホストから特定キーワードを含むログが出力されたらメール送信

条件式
if $fromhost-ip == '192.168.1.100' and $msg contains 'System Warning' then :ommail:;mail_body


リモートホストから特定ファシリティの特定キーワードを含むログが出力されたらメール送信

条件式

if $fromhost-ip != '127.0.0.1' and $msg contains 'System Warning' and $syslogfacility-text == 'daemon' then :ommail:;mailbody

一般的単語だと、他のファシリティから送信されても検知してしまいます。より条件を絞りましょう。


一度メールを送ったら1時間はメールを再送信しない

定義式

$ActionExecOnlyOnceEveryInterval  3600    # infinite retries if host is down

3600秒の間は、メール送信を抑制します。さもないと、鬼のような連射メールが飛んできます。
しかし他の条件のメールも抑えてしまうため、使いどころが難しい機能です。
なお「-1」を指定するとメール送信抑制はありません。


複数のメール送信条件を行う

条件式
$ActionMailTo admin-ml@example.local
if $fromhost-ip == '192.168.1.100' and $msg contains 'System Warning' then :ommail:;mail_body
& ~

$ActionMailTo admin-ml@example.local
if $fromhost-ip == '192.168.1.101' and $msg contains 'System Warning' then :ommail:;mail_body
& ~

$ActionMailTo administratorl@example.local
if $fromhost-ip == '127.0.0.1' and  $syslogfacility-text == "daemon" and  $syslogseverity-text == 'crit'  and $msg contains 'System Warning' then :ommail:;mail_body

メールアドレスは条件式のたびに与える必要があります。
同じメールアドレスであっても、その都度与えておかないと二つ目以降のメール条件でエラーログを出力し、送信できません。

条件式が複雑になると、動作は確認は必須です。
コンフィグファイルのチェック、そして確実にメール送信ができるかをコマンドにて確認します。

#syslogd -N 1 -c5

#logger -p daemon.crit "System Warning"






prev.gif