使用 Nagios 监控电子邮件

作者:Mike Diehl

您是否曾感到自己被忽视?您是否曾感到自己在说话却无人倾听?当您的电子邮件系统出现故障而您却毫不知情时,感觉就像这样。

在过去一周,我遇到了几个系统问题,导致人们无法收到我和妻子发送的电子邮件。可悲的是,我们并不知道邮件没有被送达。我们会收到一条询问问题的消息,然后回复发件人,并没有在意。几天后,我们会接到那个人的电话,询问我们是否会回复。

在我们的案例中,两种情况同时不利于我们:Comcast 防火墙策略的变更和 Yahoo 邮件投递策略的变更。

这一切都始于我妻子开始抱怨电子邮件系统出了问题,因为她前一天发给一位朋友的消息没有收到回复。我快速地给我的一个朋友发了一封电子邮件,收到了回复,并告诉我的妻子“对我来说是有效的”,并认为只是她的朋友没有及时回复。

然后,为了向她证明邮件服务器是健康的,我要求服务器打印出它的邮件队列。糟糕!队列中有 55 条消息等待投递。当然,这时,即使我也注意到收到的垃圾邮件量已经降为零。所以,休斯顿,我们遇到了问题。

在我的家用机器通过 Comcast 连接到互联网上运行我自己的邮件服务器几年后,Comcast 决定实施新的防火墙策略,并开始阻止住宅用户的网络上的入站 SMTP (tcp/25) 连接。当然,我没有被告知这一变更,因为我不使用 Comcast 的电子邮件系统!以前,我们会从我们的工作站发送电子邮件,我们的邮件服务器会通过 Comcast 的智能主机转发消息;入站消息直接发送到我们的服务器。这种配置已经工作了很多年。但是,随着新的防火墙策略,有些东西坏了。我们的一些消息被投递了,而有些则没有。我推测,那些没有被投递的消息是通过进行发送地址验证的服务器发送的,并且由于他们无法连接回我的邮件服务器来验证我的电子邮件地址,他们拒绝了投递。

所以,我决定采取廉价的解决办法。我可以每月额外花费 20 美元并获得 Comcast 的商业账户,我最终也这样做了,但我一开始并没有。我创建了一个从我的家用机器到我在开放互联网上的一个服务器的 VPN 隧道。然后,我移动了我的 DNS 指针以指向该机器,并让它通过 VPN 转发入站消息。我将我的家用服务器配置为使用该机器作为其智能主机,而不是 Comcast 的服务器。除了公然违反 Comcast 的可接受使用政策外,这似乎会工作得很好。

然后,另一只靴子也落下了。

我和我的妻子很快意识到这工作得更好了,但仍然不太对劲。我妻子每天通过电子邮件联系的人都没有收到她的消息。共同点是所有这些人都在使用 Yahoo 电子邮件账户。所以,我手动强制投递了一条电子邮件消息,并看到 Yahoo 由于可疑的流量模式而推迟了投递。这很有道理;我试图一次性投递 55 条延迟的消息。

重要的是要注意,我监控了我的电子邮件服务器,并且 Exim 守护程序从未发出警报,因此仅仅监控一项服务是不够的。与其监控服务本身,不如监控服务器的功能,这正是本文余下部分要讨论的内容。

我曾犹豫是否要再写一篇关于 Nagios 的文章,但电子邮件正变得越来越重要,当它出现故障时,故障方式会很奇怪。

当然,我也监控了我的 Exim 守护程序以及我的服务器到互联网的路由。我使用 Nagios 服务检查 SMTP,就像这样

define service {
        use generic-service
        name                    smtp
        host_name               host.example.com
        notification_options    w,c,r
        service_description     E-Mail SMTP Server
        check_command           check_smtp
}

我使用类似的检查来监控我的互联网网关。但是,尽管电子邮件情况变得如此糟糕,但这些警报都不会指示问题。因此,我没有监控进程是否正在运行,而是开始监控服务器的关键功能:电子邮件传输和投递。

我想解决的第一个问题是在消息卡在 Exim 的邮件队列中时收到通知。我实际上认为我必须编写一个自定义程序来检查这种情况。在进一步研究情况时,我偶然发现了一个有类似问题的人的帖子。事实证明,Nagios 已经有一个执行此检查的命令,而我从未知道。Nagios 的检查命令位于 /usr/nagios/libexec/ 中,让我告诉你,那个目录里有很多宝藏。

所以,我在 Nagios 的 checkcommands.cfg 文件中创建了一个条目,像这样

define command{
        command_name    check_mailq
        command_line    $USER1$/check_mailq -w 3 -c 5 -v 9
}

然后,我在 services.cfg 文件中创建了一个条目,看起来像这样

define service {
        use generic-service
        name                    mailq
        host_name               dominion
        notification_options    w,c,r
        service_description     SMTP Mail Queue
        check_command           check_mailq
}

最后,我重启了 Nagios 并通过关闭我的服务器的外部网络接口并尝试发送电子邮件消息来测试新的配置。显然,邮件传输操作失败了,我收到了警报。

所以,在这一点上,我非常确定,如果我的电子邮件系统再次出现问题,至少我会及时知道。但是,我认为最好再进行一次检查。

如果我的服务器发现自己出现在实时黑名单 (RBL) 上,那就太好了。再一次,Nagios 有一个命令来检查这种情况,但它是用 C 源代码编写的,我无法编译。无论如何,我认为我更喜欢我的解决方案。

我的程序在 http://www.anti-abuse.org 上查找服务器的 IP 地址,反过来,它会针对其他几个 RBL 同时检查该 IP 地址。我可能会将 Nagios 配置为每天最多执行几次此检查。

这是程序

#!/usr/bin/perl

open CMD, "wget -q http://www.anti-abuse.org/rblresults.php?host=192.168.1.1 -O - |";

while () {
        if (!/listed in /) { next; }
        if (!/NOT listed in /) { $error++; }
}

if (!$error) {
        print "OK\n";
        exit 0;
} else {
        print "CRITICAL: $error\n";
}

正如你所看到的,它并没有那么复杂。它只是向 Anti-abuse.org 发送一个查询并查找结果。在这种情况下,我硬编码了我的机器的 IP 地址,但使用 Nagios 的变量之一并将 IP 地址作为命令行参数发送给该程序将是微不足道的。然后,该程序确保每个结果都表明我的机器没有在 RBL 上列出。如果此检查失败,我们将设置一个标志以供稍后使用。最后,我像上面那样创建了一个 checkcommand.cfg 和 services.cfg 条目。

现在我发现自己处于一个尴尬的境地,写了一个我无法测试的程序。为了充分测试这个程序,我必须让我的服务器进入 RBL 列表,我不会这样做。即便如此,我相信这个程序会工作。

我不知道你怎么看,但我靠电子邮件为生,所以我的电子邮件系统必须工作。我最近遇到的问题表明我的监控策略是不够的。我相信新的策略会及时提醒我注意这种情况。但是,与往常一样,您无法测试所有内容,所以我确信我遗漏了一些东西。

加载 Disqus 评论