不正中継に迅速に気付けるよう、Zabbixでpostfixの送信状況を監視する

メールサーバに問題があった際に迅速に気づけるよう、メールサーバの送受信状況を常に把握できるよう、zabbixの監視対象にpostfixの送受信状況を含めます。

※zabbixの設計上、通常はzabbix-proxyを使うべきところを、監視対象が1台しかいないセグメントだったので、proxy導入せずに強引に対応しています。zabbixの監視スクリプトの勉強には丁度良いかもしれませんが、2台以上存在するセグメントの監視であればzabbix-proxyを導入したうえで、zabbix-postfixを、オフィシャルサイトの手順通りに導入するのが良いと思います。

Postfixのメール送受信状況取得コマンド

今回、postfixのzabbixテンプレートをインストールして改造している過程で、主に以下のコマンドを使ってログ分析しているのがわかりました。更に、zabbixの場合、60秒間隔等、ユーザの指定した感覚で状況を聞きに来るので、60秒おきにログ全量を読み込んだら、重複してログを見ることになってしまいます。その解決策として、pygtail.pyで前回どこまで読み込んだかをファイルに記録しておき、60秒後に前回読み込んだ後の未読み込み分を処理していました。

今回はzabbix-postfixを利用させてもらったのですが、同パッケージ中で、メールの状況を取得するのに使われていたコマンドは以下でした。

(今回利用させてもらったzabbix-postfix以外でも、ほぼ同じコマンドを叩いていることも調査の過程でわかりました)

mailq

一つはpostfixを運用している方なら誰でも使ったことがあるであろうmailqコマンドです。きれいにメールを転送しきっていると以下のように今はキューに何もないことを示すメッセージが表示されます。

mailq
Mail queue is empty

バウンスメールが大量にあったりすると、メッセージIDと概要が件数分出力されます。迷惑メールの不正中継等に利用されると、バウンスメール件数が溜まっていくので、mailq実行結果の件数が増える事があります。

pflogsumm

もう一つはpflogsummコマンドです。実行オプションは多々あるのですが、以下のように結果出力されます。

/usr/sbin/pflogsumm -h 0 -u 0 --bounce_detail=0 --deferral_detail=0 --reject_detail=0 --no_no_msg_size --smtpd_warning_detail=0 /var/log/mail.log

Grand Totals
------------
messages

    497   received
    468   delivered
    444   forwarded
     10   deferred  (118  deferrals)
     63   bounced
    292   rejected (38%)
      0   reject warnings
      0   held
      0   discarded (0%)

  20069k  bytes received
  19909k  bytes delivered
    383   senders
    107   sending hosts/domains
     12   recipients
     11   recipient hosts/domains


Per-Day Traffic Summary
-----------------------
    date          received  delivered   deferred    bounced     rejected
    --------------------------------------------------------------------
    Mar 13 20xx        67         62         54         13          5
    Mar 14 20xx        77         72          4          9          2
    Mar 15 20xx        98         94         17         11         24
    Mar 16 20xx        81         77         18          8        142
    Mar 17 20xx        88         83          9          9        116
    Mar 18 20xx        86         80         16         13          3

Per-Hour Traffic Daily Average
------------------------------
    time          received  delivered   deferred    bounced     rejected
    --------------------------------------------------------------------
    0000-0100           2          1          1          1          2
    0100-0200           2          1          2          1          2
    0200-0300           1          0          1          1          2
    0300-0400           2          2          2          1          1
    0400-0500           1          1          2          1          1
    0500-0600           0          0          1          0          2
    0600-0700           4          4          1          0          1
    0700-0800           1          1          1          0          1
    0800-0900           5          5          2          0          1
    0900-1000           6          6          1          0          2
    1000-1100           6          6          1          0          2
    1100-1200           6          6          1          0          2
    1200-1300           7          7          0          0          2
    1300-1400           7          6          0          1          1
    1400-1500           4          3          0          1          2
    1500-1600           6          6          0          1          3
    1600-1700           4          4          0          0          2
    1700-1800           4          4          1          0          2
    1800-1900           9          8          1          1          3
    1900-2000           4          3          0          1          2
    2000-2100           2          2          0          0          3
    2100-2200           2          2          0          0          3
    2200-2300           1          1          0          0          3
    2300-2400           1          1          1          0          3

smtp delivery failures: none

Fatal Errors: none

Panics: none

Master daemon messages
----------------------
      3   daemon started -- version 3.4.13, configuration /etc/postfix
      1   terminating on signal 15

Zabbixでの監視(zabbix-postfixを利用)

postfixのサイトでzabbixテンプレートの紹介があったので、まずはそちらを見て、zabbix-postfixを活用させていただくことにしました。選択した理由は単純にコードがわかりやすく、英語記載の為わかりやすかっただけです。

ただし、上記はzsendコマンドを用いてデータをzabbix-serverに送るようになっていたので、リモートから単純にAgentのデータを取得できるように適当に改造しました。

zabbix-postfixのセットアップ

殆どサイトに記載されている通りにセットアップしましたが、zabbix-senderは不要なので入れていません。(zabbix-serverへ通信可能なセグメントに属しているのであれば、一緒にインストールすれば良いと思います。)

sudo apt install pflogsumm bc zabbix-agent

cd /tmp
git clone https://github.com/rafael747/zabbix-postfix.git
cd /tmp/zabbix-postfix


sudo cp zabbix_postfix.sh /usr/local/sbin/
sudo cp pygtail.py /usr/local/sbin/
sudo chmod +x /usr/local/sbin/pygtail.py
sudo chmod +x /usr/local/sbin/zabbix_postfix.sh


sudo cp zabbix_postfix /etc/sudoers.d/
sudo chmod 440 /etc/sudoers.d/zabbix_postfix

sudo cp zabbix_postfix.conf /etc/zabbix/zabbix_agentd.d/

ここから下の作業は、senderを利用可能なNW構成で運用している場合、対応する必要がありません。senderを利用不可の環境下では、対応することで、Agent経由でデータ取得できるようになります。

Agentでリモートからデータ取得できるように改造する

/usr/local/sbin/zabbix_postfix.shの中身を以下のように修正しました。見て分かるようにオリジナルのzsendをしている方は、pflogsummコマンド一回の実行で、全部のパラメータのデータをzabbix-serverに送るような効率的な処理をしていましたが、今回の修正ではパラメータ毎にpflogsummを実行する非効率な処理になっています。

当方のサーバの場合、pflogsummコマンドを実行してもほぼ一瞬でコマンドが終わる事と、リソース使用状況も大して変化がなかったことから、今回はこれで良しとしました。中間ファイルを書こうかとも思ったのですが、あまり手を入れるとオリジナルの変更に追随するのが大変になってしまうので。。。

コード全量を乗せずに、変更対象箇所をコメントアウトして、その下に修正結果を記載するようにしています。viで開いて編集してください。

# 引数でreceived等、取得したいパラメータを指定できるようにする
TARGET=$1

# POSで示しているdatファイルはログを何処まで読んだかの制御ファイルの為、取得項目ごとに
# POS="/tmp/zabbix-postfix-offset.dat"
POS="/tmp/zabbix-postfix-offset.${TARGET}.dat"


# zsendしている箇所はTARGET引数を見て、該当するケースを出力するように変更
#zsend pf.received $(echo -e "${DATA}" | grep -m 1 received | cut -f1 -d"r")
#zsend pf.delivered $(echo -e "${DATA}" | grep -m 1 delivered | cut -f1 -d"d")
#zsend pf.forwarded $(echo -e "${DATA}" | grep -m 1 forwarded | cut -f1 -d"f")
#zsend pf.deferred $(echo -e "${DATA}" | grep -m 1 deferred | cut -f1 -d"d")
#zsend pf.bounced $(echo -e "${DATA}" | grep -m 1 bounced | cut -f1 -d"b")
#zsend pf.rejected $(echo -e "${DATA}" | grep -m 1 rejected | cut -f1 -d"r")
#zsend pf.rejectwarnings $(echo -e "${DATA}" | grep -m 1 "reject warnings" | cut -f1 -d"r")
#zsend pf.held $(echo -e "${DATA}" | grep -m 1 held | cut -f1 -d"h")
#zsend pf.discarded $(echo -e "${DATA}" | grep -m 1 discarded | cut -f1 -d"d")
#zsend pf.bytesreceived $(echo -e "${DATA}" | grep -m 1 "bytes received" | cut -f1 -d"b"|sed -e 's/k/\*1024/g' -e 's/m/\*1048576/g' -e 's/g/\*1073741824/g' |bc)
#zsend pf.bytesdelivered $(echo -e "${DATA}" | grep -m 1 "bytes delivered" | cut -f1 -d"b"|sed -e 's/k/\*1024/g' -e 's/m/\*1048576/g' -e 's/g/\*1073741824/g' |bc)


[ $TARGET = 'received' ] && echo $(echo -e "${DATA}" | grep -m 1 received | cut -f1 -d"r")
[ $TARGET = 'delivered' ] && echo $(echo -e "${DATA}" | grep -m 1 delivered | cut -f1 -d"d")
[ $TARGET = 'forwarded' ] && echo $(echo -e "${DATA}" | grep -m 1 forwarded | cut -f1 -d"f")
[ $TARGET = 'deferred' ] && echo $(echo -e "${DATA}" | grep -m 1 deferred | cut -f1 -d"d")
[ $TARGET = 'bounced' ] && echo $(echo -e "${DATA}" | grep -m 1 bounced | cut -f1 -d"b")
[ $TARGET = 'rejected' ] && echo $(echo -e "${DATA}" | grep -m 1 rejected | cut -f1 -d"r")
[ $TARGET = 'rejectwarnings' ] && echo $(echo -e "${DATA}" | grep -m 1 "reject warnings" | cut -f1 -d"r")
[ $TARGET = 'held' ] && echo $(echo -e "${DATA}" | grep -m 1 held | cut -f1 -d"h")
[ $TARGET = 'discarded' ] && echo $(echo -e "${DATA}" | grep -m 1 discarded | cut -f1 -d"d")
[ $TARGET = 'bytesreceived' ] && echo $(echo -e "${DATA}" | grep -m 1 "bytes received" | cut -f1 -d"b"|sed -e 's/k/\*1024/g' -e 's/m/\*1048576/g' -e 's/g/\*1073741824/g' |bc)
[ $TARGET = 'bytesdelivered' ] && echo $(echo -e "${DATA}" | grep -m 1 "bytes delivered" | cut -f1 -d"b"|sed -e 's/k/\*1024/g' -e 's/m/\*1048576/g' -e 's/g/\*1073741824/g' |bc)

次に、「/etc/sudoers.d/zabbix_postfix」に以下を追加しました。

zabbix ALL=NOPASSWD:/usr/local/sbin/zabbix_postfix.sh

最後に「/etc/zabbix/zabbix_agentd.d/zabbix_postfix.conf」に以下を追加しました。1行目が元々の行で、2行目以降が追加分です。

UserParameter=pf.mailq,sudo /usr/bin/mailq | grep -v "Mail queue is empty" | grep -c '^[0-9A-Z]'
UserParameter=pf.received,sudo /usr/local/sbin/zabbix_postfix.sh received
UserParameter=pf.delivered,sudo /usr/local/sbin/zabbix_postfix.sh delivered
UserParameter=pf.forwarded,sudo /usr/local/sbin/zabbix_postfix.sh forwarded
UserParameter=pf.deferred,sudo /usr/local/sbin/zabbix_postfix.sh deferred
UserParameter=pf.bounced,sudo /usr/local/sbin/zabbix_postfix.sh bounced
UserParameter=pf.rejected,sudo /usr/local/sbin/zabbix_postfix.sh rejected
UserParameter=pf.rejectwarnings,sudo /usr/local/sbin/zabbix_postfix.sh rejectwarnings
UserParameter=pf.held,sudo /usr/local/sbin/zabbix_postfix.sh held
UserParameter=pf.discarded,sudo /usr/local/sbin/zabbix_postfix.sh discarded
UserParameter=pf.bytesreceived,sudo /usr/local/sbin/zabbix_postfix.sh bytesreceived
UserParameter=pf.bytesdelivered,sudo /usr/local/sbin/zabbix_postfix.sh bytesdelivered

Zabbix Agentの再起動

新しいスクリプトを追加したので、zabbix-agentを再起動します。

systemctl restart zabbix-agent.service

Zabbix Serverへのテンプレート登録と設定変更

template_postfix.xmlを作業用のPCにダウンロードし、Zabbix管理画面からテンプレート登録します。

登録したテンプレートの設定を変更します。インポートしたテンプレートのアイテムを選択すると、タイプがzabbixトラッパーになっているものがあります。これらを全てZabbix エージェントに変更します。

下図のような感じで、更新間隔はもともとあったZabbixエージェントと同じように60秒間隔にします。

zabbixトラッパーとなっていたものは、上記画面のように全てZabbixエージェントに変更します。

上記までで登録したテンプレートを、該当ホストに括り付けて設定完了です。データは以下のように取れました。

初回取り込み時に、それまで蓄積したログ全部を取り込んでしまうので、グラフがはねてしまうのですが、以降は60秒おきにデータ取得するようになるので、運用していくうちに普段の数字がつかめると思います。

最後に

今回は他のサーバソフトウェアに応用しやすそうなzabbix-postfixを使わせて頂きました。作者の方、どうもありがとうございました。

zabbix-postfixを改造することで、他のログ監視に役立てられるノウハウが蓄積されました。LinuxのFWログ等も普段は適当に流し読みしているだけなのですが、分析コマンド有無を確認したうえで、同様に処理を作りこむことで容易に監視が出来るのかと思います。

ブックマーク パーマリンク.

コメントを残す

メールアドレスが公開されることはありません。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください