Edited at

rsyslogで複数のIPアドレスをフィルタリングしたかった話

More than 1 year has passed since last update.


rsyslogでIPアドレスをフィルタリングしたかった


1つの送信元IPからのsyslogを特定のファイルに保存する方法

特定のIPアドレス(例:192.168.1.1)がsyslogの送信元だった場合のrsyslog.confのフィルタリング設定は

rsyslog.conf その1

:fromhost-ip, isequal, "192.168.1.1"  -/var/log/test.log

& ~

の2行を書けばよい。

サブネットでフィルタリングする場合は

rsyslog.conf その2

:fromhost-ip, startswith, "192.168.1." /var/log/test.log

& ~

というのは、世の中を検索すれば出てくる。


2つ以上のIPアドレスをフィルタリングする

ついでにいうと、192.168.1.1 と 192.168.1.2 をフィルタリングする場合は

rsyslog.conf その3

:fromhost-ip, isequal, "192.168.1.1" /var/log/test.log

& ~
:fromhost-ip, isequal, "192.168.1.2" /var/log/test.log
& ~

と書けばよいのだが、

rsyslog.conf その4

if $fromhost-ip == ['192.168.1.1' , '192.168.1.2' ] then {

/var/log/test.log
stop
}

なんて書き方もあるらしい。


でも僕がやりたいことはこれじゃない!

IPアドレスの特定のオクテットが同じ値で、他のオクテットが0から255まで使用されている場合に、rsyslogでその特定のオクテット値でフィルタリングしろという命令が下った。

例えば、


  • 192.168.16.15

  • 172.16.16.118

  • 172.17.16.16

  • 172.17.16.56

  • 172.18.16.141

という感じのsyslog送信元が全部で100個近くあった場合、上記のその3やその4のようにrsyslog.confを書いても良い。

configの作成時間については、エクセルやawkなどで適切に整形してあげれば、それほど面倒なものではないが、なんだか負けた気になってしまう。(何と戦っているか、そもそもわからないけれど)

fromhost-ip以外のrsyslog.confのプロパティで、フィルタリングできる場所を探したが、うまい文字列がない。


ここで正規表現かよ…orz

rsyslog.confのフィルタリング設定のコンペアオペレーションを見ていたら、"regex"が使えるという。

でも僕は正規表現が苦手だ。そもそも正規表現を書こうと思ったこともなければ、使おうと思ったこともない。読んでも何が書いてあるか理解できないし、理解する気もなかった。だが、今回の場合フィルタ条件は上記の例だとIPアドレスの第3オクテットしかなく、これがうまく行けば、もしかしたら正規表現が好きになるかもしれないという、根拠のない信念が湧いてきた。


IPアドレスの正規表現

世の中、親切な人が多い。特にこの業界では先人が色々と試行錯誤した結果を残してくれているので、IPアドレスの正規表現の仕方を調べてみた。いろいろな記述方法があることがわかったが、例えば第3オクテットが16の正規表現は、たぶんこれでOKとなる。

(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.)([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.16\.([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])

もっと大雑把な書き方だと、

[0-9]{1,3}\.[0-9]{1,3}\.16\.[0-9]{1,3}

なんて感じでも、とりあえずOKのようだ。


rsyslog.confに記述してみる

実際に、rsyslog.confに下記の内容をでフィルタリングできるのか試してみた。

:fromhost-ip, regex,"([0-9]{1,3}\.[0-9]{1,3}\.16\.[0-9]{1,3})" -/var/log/test.log

これで動くだろうと思っていたら、全然うごかない。なんかやり方が違うのか?と思って調べてみたがrsyslogでregexを使ったフィルタのかけ方がうまくヒットしない。わからないなら実験してみるまで。

ということで、自分のPCに入れてある仮想CentOSを使用し実験してみた。


実験!

CentOS6.9、rsyslogは

[root@hoge]# rsyslogd -v

rsyslogd 5.8.10, compiled with:
FEATURE_REGEXP: Yes
FEATURE_LARGEFILE: No
GSSAPI Kerberos 5 support: Yes
FEATURE_DEBUG (debug build, slow code): No
32bit Atomic operations supported: Yes
64bit Atomic operations supported: Yes
Runtime Instrumentation (slow code): No

See http://www.rsyslog.com for more information.

となっている。

この状態で、rsyslogdのプロセス再起動をすると、fromhost-ipが127.0.0.1のsyslogがrsyslogdに送られてくる。第2オクテットの"0"だけ数字にして、あとは正規表現で書いたらどうなるか、実験してみた。


実験1(正規表現は使用せずにIPアドレスを記述)

:fromhost-ip, regex,"127.0.0.1" -/var/log/test.log


結果1

ちゃんとtest.logに記載された。


実験2(第4オクテットを"[1-9]"とするとどうなるか?)

:fromhost-ip, regex,"127.0.0.[1-9]" -/var/log/test.log


結果2

ちゃんとtest.logに記載された。


実験3 ()の影響をみる

:fromhost-ip, regex,"([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.).0.0.[0-9]" -/var/log/test.log


結果3

test.logにはログが書き込まれない。もしかしたら()は使えないのか?と思って、第1オクテットを変更


実験4 {}の影響をみるため、第1オクテットを以下の物に変えた

[0-9]{1,3}


結果4

これもログに書き込まれない。


実験5 更に元に戻って、正規表現だけにしてみる

[0-9][0-9][0-9]


結果5

これはきちんと動作する。

{}も使えないのかーと思って、もしかしたら?と思ってもう一度コンペアオペレーションを見ていたら、regex次のコンペアオペレーションに"ereregex"という拡張regexが使えると書いてある。拡張regexだとどうなるのか、何が拡張されたのかは後で調べるとして、ereregexを使用してみた。

拡張regex

:fromhost-ip, ereregex, "[0-9]{1,3}\.0\.0\.[0-9]" -/var/log/test.log

とすると、フィルタされるようになった。

気を良くして、第2オクテットだけ"0"にして、それ以外を大雑把だけど、

[0-9]{1,3}\.

に変えてもフィルタされるようになった。

4つのオクテットが厳密にIPアドレスの0-255内に入っているかどうかは、fromhost-ipによって検証されているはずなので、厳密でなくても大丈夫だろう。


結論らしきもの

rsyslog.confで正規表現を使って複数のIPアドレスをフィルタする場合は、ereregexを使うことで第3オクテットの固定された、複数IPアドレスをフィルタリングできる。

:fromhost-ip, ereregex, "[0-9]{1,3}\.[0-9]{1,3}\.16\.[0-9]{1,3}" -/var/log/test.log

みたいな大雑把なフィルタでも十分複数IPをフィルタリングすることができることがわかった。

ついでに言うと、好きにもなっていないし、理解したわけでもないが、少しだけ正規表現がわかったような気になった。

さらについでに言うと、やったことを忘れないうちに、夜中12時を回ってからこんな記事を書くと、眠くて誤記が多くなる。もう寝よう。