Linux 作为备份电子邮件服务器

作者:John Blair

几个月前的某个星期五早上,我负责的 Microsoft Exchange 电子邮件服务器崩溃了。当时,我还是一个相当新的 Windows NT 管理员。我们称之为 tuccster 的服务器直到接下来星期天晚上才再次正常运行。

不幸的是,此时我的问题才刚刚开始。我们的部门电子邮件服务器已经宕机近三天,并且兆字节的重要电子邮件被假脱机在互联网上的远程服务器上。无法预测邮件何时到达,以及有多少电子邮件可能永远不会出现。由于不同的电子邮件服务器尝试以不同的间隔重新发送电子邮件,因此显示出来的内容将以时间顺序混乱的方式到达。虽然我学到了很多关于 Windows NT 灾难恢复的知识,但整个事件对我们部门的用户来说都是一个主要的麻烦,对我来说也是一个可怕的尴尬。

虽然我不相信我能够阻止 Microsoft Exchange 的故障,但我本可以设置一个备用电子邮件服务器,以便在 tuccster 宕机时假脱机所有传入邮件。在事故发生后不久,我找到了一台旧的 Gateway 486/66,它带有一张以太网卡,将被更快的 Pentium 系统取代。使用 Debian Linux 和 sendmail,我设置了一个备用电子邮件服务器,每当主要的基于 Windows 的服务器 tuccster 宕机时,它都会接收和假脱机任何传入的电子邮件。添加 Web 服务器和一个用 Perl 编写的简单 CGI 脚本为系统提供了一个简单的用户界面。我配置了 Web 服务器,以便可以从某些受信任的主机使用 Web 浏览器来检查 sendmail 队列中是否有任何内容正在等待。一旦我们的主服务器准备好开始接收电子邮件,就可以通过单击同一网页上的链接来刷新 sendmail 队列。

DNS MX 记录

“备用电子邮件服务器”是互联网上的一个旧想法——设置一个备用电子邮件服务器的功能实际上内置于域名服务器 (DNS) 协议中。其目的是让每个重要的电子邮件服务器都有一个备份。域名服务器包含多种类型的记录。其中最常见的类型是 SOA 记录,它指示域数据的权限;NS 记录,它列出域的名称服务器;A 记录,它将名称映射到地址;PTR 记录,它执行相反的操作,将地址映射到名称;以及 MX 记录,它描述“邮件交换器”。MX 记录允许人们定义实际负责接收定向到任何特定主机的邮件的主机。实际负责接收电子邮件的主机不必是邮件似乎要发送到的主机。

为了说明为什么这会很有用,想象一下一组名为 larry、curly 和 moe 的工作站。为了减少 curly 和 moe 的负载,我们希望将所有传入的电子邮件定向到 larry,而不管邮件实际发送到哪个主机。MX 记录提供了一种实现此目标的方法。假设我们使用以下内容对我们的 DNS 服务器进行编程

larry.tucc.uab.edu.  IN  MX  1  larry.tucc.uab.edu.
curly.tucc.uab.edu.  IN  MX  1  larry.tucc.uab.edu.
moe.tucc.uab.edu.    IN  MX  1  larry.tucc.uab.edu.

如果有人尝试向 foo@moe.tucc.uab.edu 发送电子邮件,则邮件传输代理 (MTA) 应查找 DNS 记录并查看 larry 负责所有定向到 moe 的电子邮件。并非所有 MTA 都正确实施 MX 重定向。然后,邮件将被传递到 larry,就好像它是发送到 foo@larry.tucc.uab.edu 一样。

虽然这很有用,但它并不是 MX 记录可以完成的全部。出现在示例中“MX”和“larry.tucc.uab.edu”之间的数字是首选项值。假设我担心在 larry 上运行的学生项目可能会导致系统定期崩溃,或者 larry 正在运行不太可靠的电子邮件服务器。我可以通过使用以下 DNS 条目将 curly 设置为备用服务器

larry.tucc.uab.edu.  IN  MX  1  larry.tucc.uab.edu.
larry.tucc.uab.edu.  IN  MX  2  curly.tucc.uab.edu.
curly.tucc.uab.edu.  IN  MX  1  larry.tucc.uab.edu.
curly.tucc.uab.edu.  IN  MX  2  curly.tucc.uab.edu.
moe.tucc.uab.edu.    IN  MX  1  larry.tucc.uab.edu.
moe.tucc.uab.edu.    IN  MX  2  curly.tucc.uab.edu.

现在假设 larry 由于某种原因宕机了。尝试向 larry 发送电子邮件的远程主机将发现 larry 不可用。然后,它将从 DNS 中了解到 curly 是 larry 的下一个首选电子邮件服务器。远程主机将消息发送到 curly。curly 上的邮件传输代理(例如 sendmail)将意识到 larry 比 curly 更受青睐作为邮件交换器。然后,它会在本地假脱机消息,定期尝试传递消息,直到成功为止。

使用 Linux 设置备用服务器

您现在可能已经猜到,我使用了完全相同的技术来设置我的备用电子邮件服务器。偶然的是,部门中较旧的 486 计算机之一被安排用一台闪亮的新 Pentium PC 来替换。这台计算机配备 16MB 内存、600MB 硬盘驱动器和以太网卡,非常适合这项工作。设置计算机相对容易。我选择安装 Debian 发行版,因为我对它最熟悉。我可以同样轻松地使用任何其他发行版。我的设置必不可少的组件是最新的 sendmail 版本、Apache Web 服务器(尽管 NCSA、CERN 或另一个 Web 服务器也可以工作)和 Perl。我还安装了其他工具,例如 Emacs、gcc、make、rcs 和 vi,以便在系统上工作时更舒适。

这些实用程序还允许我在不使用另一个系统的情况下重建内核,如果我必须在某种事故后修复系统,它们应该会派上用场。我将所有 X11 库都从系统中删除以节省磁盘空间。在编译包含运行系统所需模块的内核后,我使用相同的内核创建了一个救援启动软盘。没有理由不为最坏的情况做好准备。最后,我将系统命名为 bartleby,以赫尔曼·梅尔维尔短篇小说 抄写员巴特比 中愁眉苦脸的邮局抄写员命名。

下一步是为 bartleby 选择一个合适的位置。如果 tuccster 再次自行崩溃,只需将 bartleby 放置在与 tuccster 同一个房间中即可提供足够的备份。但是,到目前为止,我的脑海中已经有了灾难恢复,并希望防止其他类型的故障。我最终在我们的主机房中找到了一个位置,该位置位于不同的建筑物中。这使得 bartleby 位于与 tuccster 不同的子网上,因此如果我们自己的子网发生故障,电子邮件也不会丢失。位于主机房也意味着 bartleby 位于受保护的电源系统上。

在 tuccster 被其 UPS 自动关闭很久之后,bartleby 仍将愉快地假脱机任何传入的电子邮件。几个月后,当我们的子网被维护人员意外断开连接时,将系统放置在单独子网上的明智之处得到了证明。在 bartleby 正确就位后,剩下的就是将相应的条目添加到我们的 DNS 并配置 sendmail 和 Web 服务器。

就像我在“三傻”示例中一样,我想将 MX 记录添加到我们的域名服务器中,以便将 bartleby 和 tuccster 都列为 tuccster 的 MX 主机,其中 tuccster 作为首选主机。我输入的两个 MX 记录如列表 1所示。

虽然配置 sendmail 通常令人恐惧,但在这种情况下很容易。sendmail 默认情况下将正确处理延迟的电子邮件。所有必要的只是配置 sendmail 以发送和接收定向到和来自 bartleby 的电子邮件,这由 Debian 包安装脚本自动处理。完成 sendmail 安装后,bartleby 作为备用电子邮件服务器正常工作。下次我将 tuccster 关闭进行维护时,我使用 sendmail -bp 命令检查了 bartleby 上的 sendmail 队列。果然,队列中有几封电子邮件消息,等待 tuccster 再次唤醒。在我将 tuccster 重新联机后,我使用 sendmail -q 命令刷新了队列。

可以通过在 sendmail 首次启动时将时间参数附加到 -q 命令来调整 sendmail 尝试处理任何假脱机消息的频率。sendmail 的 Debian 包在 sendmail 启动脚本的开头包含一个宏,使设置此值变得容易。我将我的设置为 30 分钟(实际的命令行参数是 -q30m)。sendmail 手册页描述了 -q 命令的语法。我通常在每个星期五晚上深夜自动关闭 Exchange 服务器,以将其消息存储保存到磁带上。我希望 bartleby 自动刷新其队列,以便在备份期间延迟的任何消息都可以在没有人为干预的情况下正确到达。您可能希望延长队列刷新之间的时间。

创建简单的基于 Web 的界面

我设置的系统非常好。但是,它确实需要至少对 UNIX shell 有最少的了解才能登录并检查或刷新 sendmail 队列。我希望在我离开办公室时发生某些事情时,系统尽可能万无一失。我决定使用一个用 Perl 编写的简单 CGI 脚本。此脚本(参见列表 2)显示 sendmail 队列的当前内容,以及来自 df 命令的输出。这使某人可以一目了然地看到系统中假脱机的电子邮件消息以及剩余的磁盘空间量。如果 sendmail 队列不为空,则会创建一个链接,单击该链接可以刷新队列。

由于这是此 Web 服务器提供的唯一服务,因此我将其称为“index.cgi”并将其放置在服务器目录的根目录中。将“index.cgi”添加到 srm.conf 配置文件中的 DirectoryIndex 列表会导致在访问服务器时自动执行该脚本。我还调整了 httpd.conf 文件中的 MinSpareServers 和 MaxSpareServers 值,以便不留下任何备用服务器运行。在这种情况下,我不介意降低响应时间以释放一些额外的内存。还有一些最终的安全问题需要考虑。我认为 sendmail 队列的列表是“敏感但未分类”的信息。我的意思是,我不认为入侵者会发现其中包含的信息特别有用,但话又说回来,我也没有看到需要使整个互联网都可以轻松访问该信息的必要性。刷新队列的操作本身几乎是无害的,尽管我想可能会通过重复刷新队列来发起拒绝服务攻击。最后,我决定允许从部门中的少数几台计算机进行非基于密码的访问。

这些机器中的每一台都位于可能需要检查队列的管理员的办公室中。我使用 列表 3 中 access.conf 文件中显示的 Apache 指令实现了这些限制。

我可以添加几乎每个 Web 浏览器都提供的标准明文密码身份验证,但我不相信它会增加足够的实际安全性来抵消不便之处。此 Web 界面的屏幕截图如下所示。

Linux as a Backup E-mail Server

我决定限制我自己对 shell 的访问权限。此外,我安装了贝尔实验室的 s/key 系统以避免明文密码,并使用 TCP Wrappers 来限制可以登录系统的主机。虽然从检查 sendmail 队列中几乎没有什么可获得的(除了,也许,流量分析),但从不受限制地访问任何传入的电子邮件消息中可以获得很多东西。

结论

使用在旧硬件上运行 Linux 系统的备用电子邮件服务器是在主服务器发生灾难时保留传入电子邮件的绝佳工具。虽然我正在备份 Microsoft Exchange 服务器,但相同的技术可用于备份任何供应商的 SMTP 服务器。设置备用服务器几乎不需要任何成本,只需配置所需的时间。拥有一个完全独立于我们网络其余部分的非常稳定的系统也被证明是有用的。自从我首次配置 bartleby 以来,我已经设置了一系列相对简单的脚本来监视我们网络上的其他服务,并在发生异常情况时通知我。

备用电子邮件系统是将 Linux 以低调但“任务关键型”应用程序偷偷引入您的组织的好方法。一旦您向任何持怀疑态度的决策者证明 Linux 是一个“真正的”操作系统,您就可以开始在更重要的角色中利用它。

Linux as a Backup E-mail Server
John Blair 目前在 Cobalt Microserver 担任软件工程师。当他不黑 Cobalt 可爱的蓝色 Qube 时,他会和他的妻子 Rachel 以及新生儿子 Ethan 一起出去玩。John 也是 SSC 出版的《Samba:集成 UNIX 和 Windows》的作者。欢迎通过 jdblair@cobaltmicro.com 与他联系。
加载 Disqus 评论