web-dev-qa-db-ja.com

別のマシンからsyslog経由で受信したログを書き換える

PfsenseのインストールであるマシンAを使用して、syslog経由でUbuntuボックスにログを送信します。 Ubuntu Boxはログを書き換え、たとえばホスト名を置き換え、フォーマットを少し変更する必要があります。

形式は一般的に次のとおりです

Mar  7 00:05:32 hostname service: field1 field2 field3 field4 field5 field6 field7

ホスト名、サービス、フィールドの順序を変更したり、特定のフィールドに特定の値が含まれているメッセージを除外したりすることはできません。

フィルタリングおよび処理後、メッセージはログファイルのディスクに書き込まれ、syslogを介して別のマシンに送信されます。

ロギングの部分はささいなことです-着信メッセージを受け入れるようにrsyslogdを設定し、それらを転送するだけです。ただ、書き直し部分にこだわっています。私はrsyslogdと結婚していません。 syslog-esqueデーモンが実行します。

6
vidarlo

質問は少しあいまいですが、可能な解決策を提案しようと思います。メッセージを書き換えるために、rsyslogはいくつかのモジュールを提供します。そのうちの1つは mmfields です。着信メッセージを特定の文字(one文字)でfieldsそして、これらのフィールドへのアクセスを許可します。次のようなメッセージの場合

a=1 b=two c=3 d=four

区切り文字は空白になり、フィールドには$!f2$!f3$!f4、および$!f5としてアクセスできます。残念ながら、最初のフィールド($!f1)は常に空です。これは、メッセージの前にスペースがあり、それが最初のフィールドになるためです。したがって、上記のメッセージの場合、$!f1==""$!f2=="a=1"$!f3=="b=two"$!f4=="c=3"、および$!f5=="d=four"が取得されます。

rsyslogには他の message modifiermodules も同梱されていますが、詳細が不足しているため、これを選択しました。次のファイルを/etc/rsyslog.d/10-so.confとして保存します。希望する実行順序に従って名前を変更しますが、.conf拡張子は保持します。

# Load the "Message Modification" module "mmfields" to split
# incoming messages into fields at a certain separator:
module(load="mmfields")

# Format used for messages that are forwarded to another Host.
# The fields are re-ordered and field #3 is omitted.
template(name="rewrite_forward" type="list") {
    constant(value="<")
    property(name="pri")
    constant(value=">")
    property(name="timestamp" dateFormat="rfc3339")
    constant(value=" ")
    property(name="hostname")
    constant(value=" ")
    property(name="syslogtag")
    constant(value=" ")
    property(name="$!f4")
    constant(value=" ")
    property(name="$!f2")
    constant(value=" ")
    property(name="$!f5")
}

# Format used for messages that are written to a local logfile.
# The format is almost the same as above, but lacks the priority,
# uses a different timestamp format, and ends with a "\n" as this
# is suitable for messages printed to a logfile.
template(name="rewrite_file" type="list") {
    property(name="timestamp")
    constant(value=" ")
    property(name="hostname")
    constant(value=" ")
    property(name="syslogtag")
    constant(value=" ")
    property(name="$!f4")
    constant(value=" ")
    property(name="$!f2")
    constant(value=" ")
    property(name="$!f5")
    constant(value="\n")
}

if ( $programname == "so" ) then {

    # split message into fields at (exactly) one space character.
    # The "fields" can then be referred to as "$!f1", "$!f2", ..., "$!fN".
    # Note that "$!f1" will always be an empty string because the message
    # usually starts with a blank and that is considered to be the first
    # field. 
    action( type="mmfields" 
            separator=" " 
    )

    # If the second field is the string "b=2", then go ahead and log and
    # forward the message. Change the condition to your liking.
    if ($!f3 == "b=2") then {

        # write rewritten logmessage to local file
        action( type     = "omfile"
                file     = "/var/log/so-rewrite-fields.log"
                template = "rewrite_file"
        )

        # just for reference: write the unmodified message to the
        # very same logfile. Drop this for actual processing. It 
        # serves just as a debugging aid.
        action( type = "omfile"
                file = "/var/log/so-rewrite-fields.log"
        )

        # forward rewritten message to another Host
        action( type = "omfwd"  
                target   = "127.0.0.1"  # change to actual destination
                port     = "514"        # change to actual destination
                protocol = "udp"        # change to actual destination
                template = "rewrite_forward"
        )

    }

    # no further processing:
    stop
}

rsyslogを再起動し(Sudo systemctl restart rsyslog.service経由)、それを試してください:

# A message that won't be logged because `$!f3 != "b=2"`:
logger -t so --id=$$ "a=1 b=3 txt=Hello number=$RANDOM"

# A message that will be logged because `$!f3 == "b=2"`:
logger -t so --id=$$ "a=1 b=2 txt=Hello number=$RANDOM"

2番目のloggerステートメントの出力は次のようになります。

Mar 14 21:40:34 stratum9 so[3533]: txt=Hello a=1 number=6484        # rewritten msg
Mar 14 21:40:34 stratum9 so[3533]: a=1 b=2 txt=Hello number=6484    # original msg

ホスト名を変更するには、単に置き換えます

constant(value=" ")
property(name="hostname")
constant(value=" ")

テンプレートで

constant(value=" fromElsewhere ")

Syslogtagを変更するには(何を呼び出すかservice)、以下を置き換えます

    constant(value=" ")
    property(name="syslogtag")
    constant(value=" ")

constant(value=" otherService: ")

出力は次のようになります。

Mar 14 22:05:51 fromElsewhere otherService: txt=Hello a=1 number=11763   # rewritten
Mar 14 22:05:51 stratum9 so[3533]: a=1 b=2 txt=Hello number=11763       # original

その他のメッセージプロパティについては、 ここ を参照してください。

私のアプローチ( mmfields を使用)は常に同じ順序を持つフィールドに依存しており、a=1 b=2からb=1 a=2のようなメッセージを簡単に書き換えることができないことに注意してください(キーと値のペアを並べ替えて変更します)。そのためには、別の module の方が適切かもしれません。

6
PerlDuck

私の知る限り、これはlogstash elasticsearchとKibanaを使用することで実現できます。私は同じことをしようとしており、エルクスタックを設定することで多かれ少なかれ成功していました。次に、logstashでgrokフィルターを使用して、syslogメッセージを異なるフィールドに分割し、それらを使用してパターンを照合し、アラートを送信します。これを見てください ガイド どこから始めればよいかについていくつかの答えが得られるかもしれません。

この種の設定には、mysqlログ、Apacheまたはnginxログなどのフィルターが最初から組み込まれています。これがelkスタックの機能とアーキテクチャの良い 概要 です。これがお役に立てば幸いです。

1
ognjen