即使是角色定义非常狭窄的服务器,如专用web服务器,也需要各种小型“助手”服务来处理基本的管理问题。在本章中,我们将讨论其中的一些服务,如时间同步、发送邮件、DHCP服务、调度任务等。我们将从使用SSH保护您与FreeBSD服务器的远程连接开始。
Unix的一大优势是它易于远程管理。无论服务器是在你面前,还是在一个远程的、有路障的地下实验室里,由一只名叫伊凡的自大狂黄鼠狼指导的恶毒护卫犬包围的最高安全设施中,如果你有网络访问权限,你就可以控制它。
多年来,telnet(1)
一直是访问远程服务器的标准方式。然而,作为一种远程管理协议,telnet有一个严重的问题:通过大多数版本的telnet发送的所有内容都是未加密的。任何拥有数据包嗅探器的人,只要连接到您的任何地方,都可以窃取您的用户名、密码以及您在telnet会话中查看的任何信息。当您使用telnet时,世界上最好的密码选择方案都无法保护您的用户名和密码。入侵者将非法数据包嗅探器放置在任何地方;我在小型本地网络和全球企业网络、处理敏感政府工作的律师事务所、家用电脑和互联网主干上都见过它们。对数据包嗅探器的唯一防御是以数据包嗅嗅器无法理解的方式处理您的身份验证凭据和数据。这就是SSH或安全shell发挥作用的地方。
SSH的行为与telnet非常相似,因为它在远程主机上提供了一个高度可配置的终端窗口。但与telnet不同,SSH会加密您通过网络发送的所有内容。SSH不仅可以确保您的密码不会被嗅探,还可以确保您输入的命令及其输出都是加密的。虽然telnet确实比SSH有一些小优势,因为它需要更少的CPU时间,配置也更简单,但SSH的安全优势完全超过了它们。SSH还具有telnet没有的许多功能,例如通过加密会话隧道传输任意协议的能力。SSH可以在Unix的所有现代变体上运行,甚至可以在Microsoft Windows上运行。
SSH通过公钥加密对远程连接进行加密和身份验证。SSH守护进程向客户端提供服务器的公钥,并将私钥留给自己。客户端和服务器使用加密密钥在它们之间协商加密安全的通道。由于完成此交易需要公钥和私钥,因此您的数据是安全的;即使有人捕获了你的SSH流量,他们也只能看到加密的垃圾。
要使用SSH,您必须在FreeBSD计算机上运行SSH服务器,在工作站上运行SSH客户端。
sshd(8)
守护进程在TCP端口22上监听来自网络的SSH请求。要在启动时启用sshd,请在/etc/rc.conf中添加以下行:
xxxxxxxxxx
sshd_enable="YES"
设置好后,您可以使用 /etc/rc.d/sshd
脚本或 service sshd
子命令来启动和停止SSH。停止SSH守护进程不会终止已在使用中的SSH会话;它只会阻止守护进程接受新连接。
与我们看到的未加密协议不同,sshd很难手动测试。您可以做的一件事是使用 nc(1)
连接到SSH TCP端口,确认sshd正在运行。
xxxxxxxxxx
# nc localhost 22
SSH-2.0-OpenSSH_7.2 FreeBSD-20160310
我们连接到端口22,并获得一个SSH横幅。我们可以看到,监听此端口的守护进程称自己为SSH版本2,在FreeBSD上以OpenSSH 7.2实现,版本为20160310。您可以通过一个简单的 nc(1)
连接获得所有这些信息,但这是sshd提供的最后一个免费信息。除非你能够即时手动加密数据包,否则这已经是你能做到的了。按CTRL-C离开 nc(1)
并返回命令提示符。
第一次启动 sshd(8)
时,程序会意识到它没有加密密钥,并自动创建它们。初始化sshd过程创建三对密钥:RSA密钥、ECDSA密钥和ED25519密钥。
以 .pub 结尾的密钥文件包含每种类型密钥的公钥。这些是sshd连接客户端的关键。这使连接用户能够验证他连接的服务器是否真的是他认为的服务器。(入侵者欺骗用户登录虚假机器,以获取他们的用户名和密码。)看看这些公钥文件之一;它相当长。即使用户有机会确认服务器提供了正确的密钥,它也太长了,即使是最偏执的用户也不会费心验证每一个字符。
幸运的是,SSH允许您生成密钥指纹(key fingerprint),这是密钥的更短表示。您无法加密流量或使用指纹协商连接,但两个不相关的密钥具有相同指纹的可能性可以忽略不计。要为公钥生成指纹,请输入命令 ssh-keygen -lf keyfile.pub
。
xxxxxxxxxx
# ssh-keygen -lf /etc/ssh/ssh_host_rsa_key.pub
2048 SHA256:tEcBfgXctTfaaEF9d5QK3oYUwr5Tb/cuIr3MNxV4wwE root@bert (RSA)
第一个数字 2048
表示密钥中的位数。2048是2018年RSA密钥的标准,但随着计算能力的提高,我预计这个数字还会增加。以 tEcB开
头、以 wwE
结尾的字符串是公钥的指纹。虽然它很长,但它比实际的密钥短得多,可读性也高得多。将此密钥指纹从原始服务器复制到可以从客户端计算机访问的位置。如果人类需要验证指纹,可以尝试网页或纸质列表。如果您的SSH客户端支持SSHFP记录,并且您的DNS区域支持DNSSEC,则可以使用DNS。首次连接时,使用此密钥确认服务器的身份,或使用其他密钥分发方法之一。
虽然sshd具有完全可用的配置,但在了解 sshd(8)
提供的所有功能后,您可能需要调整设置。配置文件 /etc/ssh/sshd_config 列出了所有默认设置,并用哈希标记(#)注释掉。如果要更改设置的值,请取消注释条目并更改其值。
我们不会讨论所有可用的sshd选项;那需要一本相当大的书。此外,OpenSSH的发展速度足够快,以至于这本书在上架之前就已经过时了。相反,我们将关注人们所做的一些更常见的理想配置更改。
更改SSH守护进程的配置后,使用 /etc/rc.d/sshd restart
或 service sshd restart
重新启动守护进程。
当您连接到sshd的TCP端口时,VersionAddendum
(版本附录)会出现在服务器名称中。有些人建议更改此设置以伪装操作系统版本。然而,通过在与主机交换的数据包上使用指纹技术来识别计算机的操作系统非常简单,因此这通常不值得花时间。(另一方面,如果将 VersionAddendum
更改为 DrunkenBadgersSoftware
让您感到愉快,请继续。)
sshd(8)
默认监听TCP端口22。如果你愿意,你可以将其更改为非标准端口。如果你想让sshd监听多个端口(例如,除了端口22之外的端口443),你可以在单独的行中包含多个 Port
条目:
xxxxxxxxxx
Port 22
Port 443
更改端口作为安全措施没有用。减少日志抖动可能很有用。我坦率地承认,我有一个小型SSH服务器,专门监听各种流行的TCP端口,以绕过无用的网络安全设备。但这并没有使SSH更加安全。
sshd默认监听计算机上所有IP地址的传入请求。如果你需要限制要监听的地址范围(例如,在jail服务器上),你可以在这里指定:
xxxxxxxxxx
ListenAddress 203.0.113.8
如果你想让sshd监听多个地址,请使用多个 ListenAddress
行。
这两个设置控制 sshd(8)
记录连接信息的方式。有关日志记录的更多信息,请参阅第21章。
这控制了用户在连接后多长时间内必须登录。如果传入用户连接但未在此时间窗口内成功登录,sshd将断开连接。
不要让人们以root身份登录您的服务器。相反,他们应该以普通用户的身份通过SSH登录,并使用 su(1)
成为root用户。允许直接root登录消除了您识别谁错误配置了您的系统的任何希望,并允许入侵者更容易地掩盖他们的踪迹。
这是用户在单次连接期间尝试输入密码的次数。在登录失败的次数之后,用户将被断开连接。
SSH允许用户将任意TCP/IP端口转发到远程系统。如果你的用户有shell访问权限,他们可以安装自己的端口转发器,所以几乎没有理由禁用它。
类Unix操作系统使用X11(或X)协议来显示图形程序。在X中,显示器与物理机器分离。例如,你可以在一台机器上运行一个网络浏览器,并在另一台计算机上显示结果。
由于X有着错综复杂的安全历史,许多管理员本能地禁用X转发。但是,拒绝SSH上的X转发通常不会禁用X转发。如果拒绝基于SSH的X转发,大多数用户只会使用X的内置网络感知或第三方转发器通过未加密的TCP/IP转发X,这在大多数情况下比允许通过SSH转发X要糟糕得多。如果你的sshd服务器安装了X库和客户端程序,用户可以通过某种方式转发X;最好让SSH为您处理转发。如果您没有安装X软件,则 X11Forwarding
无效。
横幅是在身份验证发生之前显示的消息。此选项最常见的用途是显示法律警告。默认情况下不使用横幅。
SSH允许您使用 scp(1)
将文件从一个系统安全地复制到另一个系统。虽然scp工作得很好,但它不是很用户友好。sftp服务器提供了一个类似FTP的文件传输接口,减少了您在用户教育上花费的时间,但仍然保持了可靠的安全性。
默认情况下,任何拥有合法shell的人都可以登录服务器。使用配置变量 AllowGroups
、 DenyGroups
、 AllowUsers
和 DenyUsers
,sshd(8)
允许您定义可能访问或不访问您的计算机的特定用户和组。
当您明确列出可以通过SSH登录到计算机的用户时,任何未列出的用户都无法通过SSH登录。
例如,AllowGroups
选项允许您将SSH访问限制为 /etc/group 中定义的指定组中的用户(请参阅第9章)。如果设置了此选项,并且用户不在任何允许的组中,则无法登录。用空格分隔多个组:
xxxxxxxxxx
AllowGroups wheel webmaster dnsadmin
如果您不想授予整个组SSH访问权限,可以使用 AllowUsers
列出单个用户。通过使用 AllowUsers
,您禁止除列出的用户之外的所有人访问SSH。
DenyGroups
列表与 AllowGroups
相反。指定系统组中的用户无法登录。列出的组必须是他们的主组,这意味着它必须列在 /etc/master.passwd 中,而不仅仅是 /etc/group 中。这一限制使得 DenyGroups
的用处不如初看上去那么大;您不能定义一个名为 nossh
的通用组,只需将用户添加到其中,除非您也将其设置为主要组。明确列出允许的组是一个更有用的策略。
最后,DenyUsers
变量列出了可能无法登录的用户。您可以使用它来明确禁止某些属于允许的组的用户。
这四种不同的设置使得用户可以同时处于多个组中。例如,一个用户可能在 AllowGroups
中列出的组和 DenyGroups
中列出的一个组中。然后呢?SSH守护进程按以下顺序检查这些值:DenyUsers
、AllowUsers
、DenyGroups
和 AllowGroups
。比赛的第一条规则获胜。例如,假设Bert是wheel组的成员。以下是 sshd_config 的一个片段:
xxxxxxxxxx
DenyUsers: bert
AllowGroups: wheel
Bert无法通过SSH连接到此计算机,因为在 AllowGroups
之前检查了 DenyUsers
。
当然,FreeBSD附带了SSH客户端,大多数类Unix操作系统也是如此。如果可能的话,使用附带的SSH客户端——它是OpenSSH的一部分,由OpenBSD团队的一个子集开发,它不仅是最流行的实现,也是最好的实现。如果你被判处运行微软操作系统,我推荐PuTTY,它可以免费用于商业或非商业目的,并且具有出色的终端模拟功能。微软正在将OpenSSH的一个分支集成到Windows中,但在我写这篇文章的时候,它仍处于测试阶段。
这是一本FreeBSD的书,所以我们将重点介绍FreeBSD的OpenSSH客户端。您可以通过多种方式配置客户端,但最常见的配置选项只是禁用服务器提供的功能。如果你真的有兴趣调整客户端的行为,请阅读 ssh_config(5)
。
要使用SSH连接到另一台主机,请键入ssh
hostname 。作为回应,你会看到这样的东西:
xxxxxxxxxx
# ssh mwl.io
The authenticity of host 'mwl.io (203.0.113.221)' can't be established.
ECDSA key fingerprint is SHA256:ZxOWglg4oqcZKHOLv5tfqPlAwDW6UGVbiTvjfAjMc4E.
No matching host key fingerprint found in DNS.
Are you sure you want to continue connecting (yes/no)? yes
您的客户端会立即从您连接的主机检索公钥,并检查其自己的内部SSH密钥列表,以查找该主机的匹配密钥。如果服务器提供的密钥与客户端列表中的密钥匹配,则客户端会认为您正在与正确的主机通信。如果客户端的已知主机列表中没有主机密钥,它会显示密钥指纹供您批准。
SSH客户端提供的指纹应该与您在服务器上生成的指纹相同。如果指纹不一致,则表示您连接到了错误的主机,需要立即断开连接。如果匹配,接受密钥并继续。接受指纹后,密钥将保存在您的主目录 .ssh/known_hosts 中。
如果你正在本地网络上构建一个新的服务器供私人使用,也许你不必手动比较密钥指纹。但是,您仍然应该复制密钥指纹,因为您最终会希望从远程位置连接,并且需要验证密钥。如果很多人会连接到服务器,通常可以将指纹放在网页上。你必须决定你需要多少安全保障。我强烈建议你谨慎行事。
接受主机密钥,您将被允许登录服务器。虽然使用带有密码的私钥比使用密码更可取,但使用SSH的密码仍然比telnet更好。
SSH客户端适合命令行访问,但将文件从一个系统移动到另一个系统呢?SSH包括两个用于在网络上移动文件的工具:scp(1)
和 sftp(1)
。
scp(1)
是“secure copy”,是移动单个文件的理想选择。scp有两个参数:第一,文件的当前位置;然后是期望的位置。所需的位置指定为 <username>@<hostname>:<filename>。假设我想将文件 bookbackup.tgz 从本地系统复制到远程服务器 mwl.io ,并为远程副本命名。我会运行:
xxxxxxxxxx
# scp bookbackup.tgz mwlucas@mwl.io:bookbackup-january.tgz
如果要为新副本命名,可以在第二个参数中省略文件名:
xxxxxxxxxx
# scp bookbackup.tgz mwlucas@mwl.io:
scp(1)
还允许您将文件从远程系统复制到本地系统:
xxxxxxxxxx
# scp mwlucas@mwl.io:bookbackup-january.tgz bookbackup.tgz
如果您不想更改本地系统上的文件名,可以使用单个点作为目标名称:
xxxxxxxxxx
# scp mwlucas@mwl.io:bookbackup.tgz .
最后,如果您在远程系统上的用户名与本地用户名相同,您可以删除用户名和 @
符号。例如,为了备份我的工作,我只需使用:
xxxxxxxxxx
# scp bookbackup.tgz mwl.io:
虽然这看起来很复杂,但它对于在网络中快速移动单个文件非常有用。
如果你喜欢交互式系统,或者你不知道你想从远程服务器抓取的文件的确切名称, sftp(1)
是你的朋友。sftp(1)
接受一个参数,即用户名和服务器名称,使用scp的远程服务器语法:
xxxxxxxxxx
# sftp mwlucas@mwl.io
Connecting to bewilderbeast...
Password:
sftp> ls
sftp(1)
客户端看起来很像标准的命令行FTP客户端;它支持常用的FTP命令,如 ls
(列表)、cd
(更改目录)、get
(下载文件)和 put
(上传文件)。一个重要的区别是sftp(1)
不需要在ASCII和二进制传输之间进行选择;它只是按原样传输文件。
使用SSH、scp和sftp,您可以完全消除网络中的明文密码。
OPENSSH密码和密钥 为了真正保护您的系统,请使用基于密钥的SSH身份验证。创建密钥并不难,但以最适合您环境的方式部署它们比我在这里能适应的要复杂得多。消除SSH密码是您可以在网络中做出的最大的安全改进。
虽然SSH是最常见的系统管理工具,但我们只是对其进行了表面处理。你花在掌握SSH上的时间会得到数倍的回报。你可以在网上找到几个好的教程和一些不错的书,包括我自己的SSH Mastery(倾斜风车出版社,2018)。
在过去的几年里,运行电子邮件服务器变得更加复杂。应对邮件服务器上的垃圾邮件、病毒和随机垃圾需要一套专门的技能,而且每年垃圾的数量都在激增。在部署邮件服务器之前,请仔细考虑。然而,每个主机都需要某种邮件客户端。FreeBSD包括两个软件套件,可用于管理本地邮件和将邮件转发到邮件服务器:Sendmail和Dragonfly mail Agent。
Sendmail 是邮件程序的鼻祖。它可以是服务器、客户端、过滤器和任意邮件spindler。如果你想与如此孤立的站点交换邮件,以至于它们每天通过拨号线路通过UUCP通信一次,并且还想与最新的商业邮件服务器交换邮件,Sendmail是一个不错的选择。然而,对我们大多数人来说,瑞士陆军的电子邮件粉碎器(Swiss Army Car Crusher of Email)太过分了。
Dragonfly Mail Agent(DMA)来自Dragonfly BSD。它是一个非常简单的邮件客户端,可以在本地主机上传递邮件或将其转发到邮件服务器。这正是你的普通主机需要将每日状态邮件转发给负责阅读它们的仆从,将报告从你的应用程序发送给应用程序管理员,以及转发你的WordPress安全插件希望你阅读的所有烦人的报告。
我们将花一些时间与DMA。不过,在我们开始之前,让我们先谈谈FreeBSD是如何应对世界上邮件服务器的多样性的。
几十年来,Sendmail是类Unix系统中唯一可用的邮件服务器。因此,大量的软件希望每台服务器都有 /usr/sbin/sendmail ,并希望它的行为与sendmail完全一样。更糟糕的是,当用不同的名字调用Sendmail时,它的行为会有所不同。程序 mailq(1)
是 sendmail(8)
的硬链接,但由于其名称不同,其行为也不同。newaliases(1)
、send-mail(8)
、hoststat(8)
和 purgestat(8)
也是如此。
由于客户端希望找到Sendmail,任何替换的邮件服务器都必须精确地模拟Sendmail,直到这种多名称行为。使用不同的邮件服务器并不像擦除Sendmail二进制文件并用其他东西替换它们那么容易。但人们会尝试。
因此,探索不熟悉的Unix系统的系统管理员可能不知道 /usr/sbin/sendmail 到底是什么!如果有人之前安装了几个不同的邮件服务器,试图找到比Sendmail更不可怕的东西,你就必须求助于侦探工作和顽强的毅力来识别你所谓的 sendmail(8)
。
FreeBSD通过使用一个单独的 mailwrapper(8)
程序来解决所有这些混淆。邮件包装器将Sendmail的请求定向到安装在其他地方的首选邮件服务器。
在 /etc/mail/mailer.conf 中配置 mailwrapper(8)
。此文件包含程序名称列表,以及要调用的实际程序的路径。以下是默认的mailer.conf,它将所有内容定向到旧的 sendmail(8)
:
xxxxxxxxxx
sendmail /usr/libexec/sendmail/sendmail
send-mail /usr/libexec/sendmail/sendmail
mailq /usr/libexec/sendmail/sendmail
newaliases /usr/libexec/sendmail/sendmail
hoststat /usr/libexec/sendmail/sendmail
purgestat /usr/libexec/sendmail/sendmail
左列中的这六个“程序”中的每一个都是其他程序可能用于Sendmail的名称。右侧列给出了应该调用的程序的路径。在这里,我们看到Sendmail安装为 /usr/libexec/sendmail/sendmail 。如果使用其他邮件程序,则必须编辑 mailer.conf 以指向邮件程序的正确路径。大多数替代邮件程序为每个功能使用单独的程序,因为自Sendmail诞生以来,磁盘空间的成本已经大幅下降。当您从软件包或port安装替代邮件程序时,安装后消息通常会提供如何为您的安装更新 mailer.conf 的说明。如果你想让新的邮件服务器工作,请按照这些说明操作。如果你在不使用软件包的情况下安装了其他邮件服务器,你需要自己编辑 mailer.conf。
Dragonfly邮件代理(DMA——Dragonfly Mail Agent)可以在本地传递邮件并将邮件发送到另一台服务器。它无法通过网络接收邮件。在大多数邮件服务器绑定到本地主机上的TCP端口25的情况下,dma(8)
则不能。它只为可以调用 /usr/sbin/sendmail 或其对应程序之一的程序传递邮件。
在激活DMA之前,请在 /etc/dma/dma.conf 中配置它。此文件包含您可以取消注释并设置为特定值的变量。虽然DMA有几个可配置的设置,但您应该将其中大部分保留为默认值。
智能主机是实际的邮件服务器,此客户端应通过该主机中继邮件。使用主机名或IP地址。
xxxxxxxxxx
SMARTHOST=mail.mwl.io
如果您的邮件管理员是一个在非标准端口上运行智能主机电子邮件的疯子,或者您试图逃避ISP的阻止端口25出站,请在此处设置TCP端口:
xxxxxxxxxx
PORT 2025
如果你不设置智能主机,但设置了端口,你将中断邮件传递。
您可能希望您的服务器在发送邮件时声称自己是另一台主机。也许你的云提供商给了这个系统一个由随机数字组成的主机名,但你希望它以www.example.com的身份发送邮件。使用MAILNAME设置一个假主机名。
xxxxxxxxxx
MAILNAME www.mwl.io
如果你给MAILNAME一个文件的完整路径,dma(8)
将使用该文件的第一行作为主机名。
一些邮件服务器非常严格地检查中继邮件,并拒绝不充分伪造的邮件。对于这些主机,您需要使用MASQUERADE选项。伪装为您提供了两种不同的更改消息的选项。如果你使用一个完整的电子邮件地址,所有通过 dma(8)
发送的邮件都会被重写,使其来自该地址。如果您使用带有@符号的用户名,如 bert@
,则所有电子邮件似乎都来自主机上的该用户。主机名本身不会改变发送用户名,但会更改主机名。
xxxxxxxxxx
MASQUERADE bert@mwl.io
从该主机发送的任何消息似乎都来自Bert。任何回复都会给他。一切都是应该的。
有些主机永远不会收到邮件。主机上的任何帐户都不应收到邮件,即使是来自其他本地帐户的邮件。通过取消注释NULLCLIENT选项完全禁用本地邮件传递。
几十年来,电子邮件协议中嵌入了一系列不同的安全措施。您的邮件服务器可能会使用其中的任何一种或全部。请与您的电子邮件管理员联系,了解智能主机的要求和支持。
通过取消注释SECURETRANSFER选项启用TLS(或SSL,如果您的邮件服务器非常糟糕)。您不需要将其设置为值;它的存在本身就开启了TLS。如果您的邮件服务器需要STARTTLS,请取消注释该选项。如果你想在TLS协商失败的情况下发送邮件,也可以取消对OPPORTUNISTIC_TLS的注释。
这三个选项都需要前面的选项。您可以单独使用SECURETRANSFER,也可以同时使用STARTTLS和SECURETRANSFORM,或者同时使用这三种方式。没有前面选项的STARTTLS和SECURETRANSFER不起作用。
如果您需要本地TLS证书,请使用CERTFILE选项进行设置。
xxxxxxxxxx
CERTFILE /etc/ssl/host.crt
这些选项应该可以让您连接到几乎任何智能主机。
一些智能主机要求客户端使用用户名和密码进行身份验证。将身份验证凭据放入 /etc/dma/auth.conf 文件中。每个条目都需要以下格式:
xxxxxxxxxx
user|host:password
假设我的智能主机是 mail.mwl.io 。用户名是 www1 ,密码是 BatteryHosseStapleCorrect 。我的 auth.conf 将包含:
xxxxxxxxxx
www1|mail.mwl.io:BatteryHorseStapleCorrect
DMA将使用此功能登录到您的主机。
如果要在未加密的连接上使用用户名和密码,则必须设置INSECURE变量。通过网络发送未加密的身份验证信息是一个坏主意,但许多邮件服务器都充满了坏主意。
使用DMA需要关闭所有现有的Sendmail进程,并在 mailer.conf 中启用 DMA(8)
。
Sendmail作为守护进程运行,即使它只处理本地传递。使用 service(8)
或 /etc/rc.d/sendmail 脚本关闭Sendmail。
xxxxxxxxxx
# service sendmail stop
确保它永远不会再开始:
xxxxxxxxxx
# sysrc sendmail_enable=NONE
现在,转到 /etc/mail/mailer.conf ,将每个邮件程序指向 dma(8)
:
xxxxxxxxxx
sendmail /usr/libexec/dma
send-mail /usr/libexec/dma
mailq /usr/libexec/dma
newaliases /usr/libexec/dma
rmail /usr/libexec/dma
DMA没有持久守护进程,因此不需要启动脚本。
恭喜,您现在拥有了一个小型、简单、有效的客户端邮件代理。
/etc/mail/aliases 文件包含发送到特定帐户或用户名的电子邮件的重定向。甚至像DMA这样的邮件客户端和邮件代理也使用别名(aliases)文件。在别名文件中添加条目是本地重定向电子邮件的好方法。
虽然别名文件有一大堆功能,但DMA只能使用其中的一小部分。将电子邮件重定向到任意文件等功能不起作用。我们将讨论基本功能。
打开别名文件,四处看看。每一行都以别名或地址开头,后跟冒号和要向其发送电子邮件的真实用户列表。我们将通过示例说明别名的工作原理。
应该始终有人阅读发送到root帐户的电子邮件。与其让某人登录每台服务器阅读消息,不如将root的所有电子邮件转发到另一个电子邮件地址:
xxxxxxxxxx
root: bert@mwl.io
我已经指派伯特阅读所有机器上的所有邮件。
许多电子邮件地址没有与之关联的帐户。例如,所需的postmaster地址通常没有帐户。您可以使用别名将此转发到真实帐户:
xxxxxxxxxx
postmaster: root
于是,postmaster转发给root,root再转发给伯特。伯特收到了这两个地址的所有电子邮件。
默认别名文件包含各种互联网服务的标准地址,以及所有默认FreeBSD服务帐户的别名。默认情况下,它们都会转到root。通过将真实地址定义为根电子邮件的目的地,您将自动收到所有系统管理电子邮件。
您可以列出多个用户以创建小型邮件列表。这不适用于动态列表,但对于快速和脏列表来说就足够了。
xxxxxxxxxx
escalate: mwlucas@mwl.io, bert@mwl.io, helpdesk@mwl.io
当你发现自己创建了一个别名邮件列表时,你就需要开始考虑要部署哪个邮件列表解决方案。你需要它的时间比你想象的要早。
如果数据库开始在三个小时后输入日期,或者如果电子邮件明天到达,你很快就会听到。时间很重要。您有两个工具来管理系统时间:tzsetup(8)
控制时区,ntpd(8)
调整时钟。首先手动设置时区,然后使用网络时间协议。
使用 tzsetup(8)
可以轻松管理时区,这是一个菜单驱动的程序,可以为每个时区在系统上进行适当的更改。全球组织可能会在其系统上使用默认的UTC(Universal Time Clock - 世界时钟,以前称为格林尼治标准时间(Coordinated Universal Time),目前称为协调世界时,很快将以另一个名字命名),而其他组织则使用自己的本地时间。输入 tzsetup
,按照地理提示,为您的位置选择合适的时区。如果你知道你的时区的正式名称,你可以在命令提示符下设置它,而无需经过提示。
xxxxxxxxxx
# tzsetup America/Detroit
tzsetup(8)
程序将相关时区文件从 /usr/share/zoneinfo 复制到 /etc/localtime 。这是一个二进制文件,您无法使用普通的文本编辑器进行编辑。如果您的时区特征发生了变化,例如夏令时开始更改的那一天,您必须升级FreeBSD以获取新的时区文件,然后重新运行tzsetup(8)
以正确重新配置时间。
用户可以使用 TZ
环境变量设置他们的个人时区。
Network time protocol (NTP —— 网络时间协议) 是一种在网络上同步时间的方法。您可以使本地计算机的时钟与政府研究实验室的原子钟或主服务器上的时间相匹配。提供时间同步的计算机称为时间服务器(time servers),大致分为两组:第1层和第2层。
第1层NTP服务器直接连接到高度精确的计时设备。如果你真的需要这种精度,那么你真正需要的是你自己的原子钟。像廉价GPS上的USB无线电时钟可能看起来很好,但事实证明,USB是传输计时数据的糟糕媒介。去订购一个专用的非USB GPS接收器,然后选择一个1级NTP服务器。
第2层NTP服务器从第1层NTP服务器获取数据,将时间服务作为公共服务提供。他们的服务精确到几分之一秒以内,几乎足以满足所有非生命维持应用的需求。一些情况甚至会让你找到第3层时间服务器,它依赖于第2层服务器。
时间服务器的最佳来源是以下列表http://www.pool.ntp.org/.该组已将公共NTP服务器收集到轮询DNS池中,从而可以轻松配置NTP。这些NTP服务器首先排列在全球列表中,然后按大陆排列,然后按国家排列。例如,如果您在加拿大,在该网站上进行简短搜索即可找到 0.ca.pool.ntp.org 、1.ca.pool.ntp.org 和 2.ca.pool-ntp.org 。我们将在以下示例中使用这些服务器,但请查找适合您所在国家的服务器,并在设置自己的时间服务时使用这些服务器。
ntpd(8)
根据时间服务器列表检查系统时钟。它对时间服务器提供的时间进行合理的平均,丢弃任何离共识太远的服务器,并逐步调整系统时间以匹配平均值。这提供了尽可能准确的系统时间,而不会对任何一台服务器要求太多,并有助于控制错误的硬件。在 /etc/ntpd.conf 中配置NTP。这是一个使用加拿大时间服务器的示例:
xxxxxxxxxx
server 1.ca.pool.ntp.org
server 2.ca.pool.ntp.org
server 3.ca.pool.ntp.org
此系统检查三个时间服务器是否有更新。如果你只列出一台服务器,ntpd(8)
会将其时钟从属于这台服务器,并分享服务器遇到的任何时间问题。使用两个时间服务器可以保证您的系统不知道现在是什么时间;记住,NTP取其时间服务器的平均值,但抛出任何超出其他值范围的值。当只有两个值可供选择时,NTP如何判断一个服务器是否错误?使用三台时间服务器是最佳选择;如果一台服务器运行异常,ntpd会识别出该服务器提供的时间与其他两台服务器提供的日期不符。(把这看作是“多数人的暴政”;一个意见与其他人不同的人根本没有发言权。)
要让ntpd在启动时执行一次性时钟同步,然后不断调整时钟,请在 /etc/rc.conf 中设置以下内容:
xxxxxxxxxx
ntpd_enable="YES"
ntpd_sync_on_start="YES"
ntpd将在启动时立即强制执行正确的时间,然后轻轻保持时钟同步。
ntpd(8)
在保持系统时钟随时间变化的准确性方面表现出色,但它只能逐渐调整本地时钟。如果您的时间按小时或几天计算(在安装时或长时间断电后不太可能),您可能希望在启动任何对时间敏感的应用程序之前正确设置时钟。ntpd(8)
也包括该功能,使用 ntpd -q
。
要对时钟执行一次暴力更正,请使用 ntpd -q
。这将连接到NTP服务器,获取正确的时间,设置系统时钟,然后退出。
xxxxxxxxxx
# ntpd -q
ntpd: time set -76.976809s
该系统的时间关闭了约77秒,但现在与NTP服务器同步。
不要随意更改生产系统上的时钟。时间敏感的软件,如许多数据库驱动的应用程序,如果时间突然向前或向后移动,就会出现问题。
如果你有一个非常好的硬件和一个优秀的振荡器,在引导时使用 ntpd -q
可以处理所有的时间问题。然而,很少有人拥有这种硬件。我们大多数人不得不凑合着用臭名昭著的劣质时钟来购买商品硬件。确保你有准确时间的最好方法是运行 ntpd(8)
,不断地轻轻调整你的时钟。
虽然ntpd不使用大量的网络带宽,但让网络上的每台服务器都查询公共NTP服务器是对网络资源的浪费——既浪费了你的资源,也浪费了时间服务器捐赠者的资源。它也可能导致您自己的网络在时间上出现非常轻微的(subsecond —— 亚秒级)差异。
可靠的时间服务器不是虚拟机。第1层NTP服务器都在真实硬件上运行,以避免时钟抖动的虚拟机受到影响。
我建议为您的网络设置三个权威时间服务器。让这些服务器将其时钟与全局NTP池同步。配置网络上的每台服务器,使其指向这些服务器进行NTP更新。这样,您网络上的每个时钟都将完全同步。您不必浏览NTP日志来尝试确定全局时间服务器池中的特定服务器是否以某种方式扰乱了您的系统时钟。最好通过网络边界的防火墙规则来执行此策略;只允许您的时间服务器与外部NTP服务器通信消除了一个常见的时间混乱源。
任何类Unix系统都会对许多不同的名称服务执行无数次检查。我们已经讨论了将主机名映射到IP地址的域名系统(见第7章),但还有密码条目查找服务、TCP/IP端口号和名称查找服务、IP协议名称和编号查找服务等。您可以使用 /etc/nsswitch.conf
配置FreeBSD系统如何进行这些查询,以及它通过nsswitch(name service switching —— 名称服务切换)使用哪些信息源。
每个名称服务都有一个 nsswitch.conf 条目,其中包括服务的类型及其使用的信息源。我们之前在第8章中看到了一个名称服务切换的示例。还记得这个主机查找条目吗?
xxxxxxxxxx
hosts: files dns
这意味着,“首先在本地文件中查找IP地址,然后查询DNS。”其他信息源的工作方式类似。FreeBSD和大多数其他类Unix操作系统一样,支持表20-1中列出的信息源的名称服务切换。
表20-1:支持名称服务切换的查找
Lookup | Function |
---|---|
groups | 组成员资格检查( /etc/group) |
hosts | 主机名和IP检查(DNS和 /etc/hosts ) |
networks | 网络条目(/etc/networks) |
passwd | 密码条目(/etc/passwd) |
shells | 检查有效shell(/etc/shells) |
services | TCP和UDP服务(/etc/services) |
rpc | 远程过程调用(/etc/rpc) |
proto | TCP/IP网络协议(/etc/protocols) |
除非你喜欢破坏系统功能,否则你不想弄乱其中的大多数。例如,如果你有一个Kerberos或NIS域,你可能想让你的FreeBSD盒子连接到它们上以获取用户和组信息——但如果你不这样做,重新配置密码查找最多会让你的系统变慢,最坏的情况是完全停止工作!
对于每个名称服务,您必须指定一个或多个信息源。这些名称服务中的许多都非常简单,默认情况下只有一个权威的信息源——一个文件。其他服务,如主机的名称服务,则更复杂,有多个来源。其中一些非常复杂,仅仅是因为有大量可用的信息以及获取这些信息的许多可能方法。由于本书不涉及Kerberos、NIS或任何其他企业级用户管理系统,因此我们不会涉及更改密码、组和shell信息源。如果您处于这样的环境中,请阅读 nsswitch.conf(5)
以了解详细信息。
大多数常见服务都有特定的有效信息来源。文件是包含服务信息的标准文本文件。例如,网络协议传统上存储在 /etc/protocols 中,网络服务存储在 /etc/services 中,密码存储在 /etc/passwd 和 friends 中。dns
意味着信息在DNS服务器上可用,这对于负责将主机名映射到IP地址的主机服务来说是典型的。密码服务通常使用 compat ,它授予与 /etc/passwd 和NIS的兼容性,但也可以使用 file 。您可以向系统添加信息源,例如,启用LDAP身份验证会添加 ldap 信息源。
按您希望尝试的顺序列出每个所需的信息源。我们的 host
条目告诉名称服务查找首先尝试本地文件,然后查询DNS服务器。
xxxxxxxxxx
hosts: files dns
如果部署像LDAP这样的中央身份验证方案,则需要添加一个适当的条目,告诉主机在LDAP中查找密码和组。重要的问题是,主机应该使用其本地密码文件然后回退到LDAP,还是从LDAP开始回退到密码文件?
xxxxxxxxxx
passwd: ldap files
在这里,我们从LDAP开始,但如果LDAP不可用,则回到密码文件。
inetd(8)
守护进程处理不太常用的网络服务的传入网络连接。大多数系统都没有稳定的FTP请求流,那么为什么FTP守护进程一直在运行呢?相反,inetd会监听网络中传入的FTP请求。当FTP请求到达时,inetd(8)
启动FTP服务器并传递请求。其他依赖inetd的常见程序有telnet、tftp和POP3。
Inetd还处理非常小且很少使用的函数,因此它们更容易在Inetd中实现,而不是通过单独的程序路由它们。这包括丢弃(将接收到的任何数据转储到 /dev/null 的黑洞中)、chargen(输出字符流)和其他函数。如今,这些服务中的大多数不仅不是必需的,而且通常被认为是有害的。例如,chargen服务主要用于拒绝服务攻击。
INETD安全 一些系统管理员认为inetd是一个具有单一安全配置文件的单一服务。其他人说inetd的安全历史很糟糕。两者都不完全正确。inetd服务器本身是相当安全的,但它为它转发请求的程序承担了一定的责任。inetd可以支持的一些服务,如ftp、telnet等,本质上是不安全的,而另一些服务则有着不安全的童年,因此会采取行动(例如popper)。像对待其他网络服务器程序一样对待inetd:除非需要,否则不要运行inetd,然后确认它只提供受信任和安全的程序!
请查看 /etc/inetd.conf 。大多数守护进程都有单独的IPv4和IPv6配置,但如果您没有运行IPv6,则可以忽略IPv6条目。让我们来看一个条目,FTP服务器配置。
xxxxxxxxxx
➊ftp ➋stream ➌tcp ➍nowait ➎root ➏/usr/libexec/ftpd ➐ftpd -l
第一个字段是服务名称➊,它必须与 /etc/services 中的名称匹配。inetd执行服务名称查找,以确定它应该侦听哪个TCP端口。如果要更改FTP服务器运行的TCP/IP端口,请在 /etc/services 中更改FTP的端口。(您也可以更改第一个字段以匹配在所需端口上运行的服务,但我发现这会使条目稍显混乱。)
套接字类型➋决定了这是什么类型的连接。所有TCP连接都是 stream
,而UDP连接是 dgram
类型。虽然你可能会找到其他可能的值,但如果你正在考虑使用它们,要么你正在阅读告诉你该使用什么的软件的文档,要么你错了。
协议➌是第4层网络协议,tcp
(IPv4 tcp)、udp
(IPv4 udp)、tcp6
(IPv6 tcp)或udp6
(IPv6 udp)。如果您的服务器同时接受IPv4和IPv6连接,请使用条目 tcp46
或udp46
。
下一个字段指示inetd是应该等待服务器程序关闭连接,还是只是启动程序然后离开➍。一般来说,TCP守护进程使用 nowait
,而UDP守护进程使用 wait
。(也有例外,但这种情况很少见。) inetd(8)
为每个传入请求启动一个新的网络守护进程实例。如果服务使用 nowait
,您可以通过在 nowait
后直接添加斜线和数字来控制inetd每秒接受的最大连接数,如下所示:nowait/5
。入侵者(通常是脚本小子)试图将服务器从互联网上删除的一种方式是打开比服务器可以处理的更多的服务请求。通过限制传入连接的速率,您可以阻止这种情况。另一方面,这意味着您的入侵者可以阻止其他人使用该服务。小心选择你的毒药!
然后,我们有服务器守护进程运行的用户➎。FTP服务器 ftpd(8)
以root身份运行,因为它必须为许多系统用户的请求提供服务,但其他服务器以专用用户身份运行。
第六个字段是连接请求到达时服务器程序inetd运行的完整路径➏。与 inetd(8)
集成的服务显示为内部。
最后一个字段给出启动外部程序的命令,包括任何所需的命令行参数➐。
虽然 /etc/inetd.conf 似乎使用了大量信息,但添加程序实际上非常简单。了解 inetd(8)
的最简单方法是用它实现一个简单的服务。例如,让我们实现一个Quote of the Day(qotd)服务。当您连接到qotd端口时,服务器会发送一个随机报价并断开连接。FreeBSD在其游戏集合中包含一个随机报价生成器 fortune(1)
。这个随机报价生成器是我们实现基于inetd的网络程序所需的全部。我们必须指定端口号、网络协议、用户、路径和命令行。
/etc/services 文件列出了端口17上的qotd。
qotd服务要求您连接到网络端口并获取数据,因此它需要通过TCP运行。记住,UDP是无连接的,不需要回复。我们必须在inetd配置中指定 tcp
,这意味着我们必须在第四个字段中指定 nowait
。
最佳实践是创建一个无特权用户来运行qotd服务,如第19章所述。对于这个例子,我们只使用普通的无特权用户 nobody,但如果你在生产环境中实现了这一点,你会想创建一个无特权用户qotd。
在 /usr/bin/fortune 上查找fortune。
fortune(6)
不需要任何命令行参数,但如果你愿意,你可以添加它们。在FreeBSD 11上,墨菲定律的信徒可以使用 fortune murphy
,而《星际迷航》的粉丝可以通过 fortune startrek
获得报价。(后者正确地只包括《一个真正的星际迷航》,而不是任何想成为续集的人。)那些对教育感兴趣的人可以使用 fortune freebsd-tips
。遗憾的是,FreeBSD 12删除了许多fortune数据库。
综上所述,/etc/inetd.conf 中qotd的条目如下:
xxxxxxxxxx
qotd stream tcp nowait nobody /usr/bin/fortune fortune
您可能认为这个例子微不足道,但在 inetd(8)
之外提供其他服务并不困难。
首先,通过在 /etc/rc.conf 中添加以下条目,在启动时启用 inetd(8)
:
xxxxxxxxxx
inetd_enable=YES
使用此设置,使用 /etc/rc.d/inted start
手动启动inetd。现在inetd正在运行,telnet到端口17测试我们的新服务:
xxxxxxxxxx
# telnet localhost 17
➊ Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
➋ It is difficult to produce a television documentary that is both
incisive and probing when every twelve minutes one is interrupted by
twelve dancing rabbits singing about toilet paper.
-- Rod Serling
Connection closed by foreign host.
它奏效了!我们有通常的TCP/IP连接信息➊和我们的随机财富➋。(作为额外的奖励,你也知道我为什么不为电视写作。)
inetd的行为因您为其设置的标志而异。默认标志打开TCP包装器,如 /etc/hosts.allow 中配置的那样(见第19章)。表20-2列出了一些有用的标志。
表20-2: inetd(8)
标志
标志 | 描述 |
---|---|
-l | 记录每个成功的连接。 |
-c | 设置每秒可以连接到任何服务的最大连接数。默认情况下,没有限制(no limit)。请注意,“unlimited”与“infinite”并不相同——你的硬件只处理这么多连接。 |
-c | 设置一个IP地址在一分钟内可以连接到单个服务的次数。默认情况下,此连接速率不受限制,但使用此连接速率可以防止人们试图垄断您的带宽或资源。 |
-R | 设置一分钟内任何一项服务可以启动的最大次数。默认值为256。如果使用 -R 0 ,则允许与任何一个服务建立无限数量的连接。 |
-a | 设置 inetd(8) 连接到的IP地址。默认情况下,inetd监听连接到系统的所有IP地址。 |
-w | 根据 hosts.allow(见第19章),对 inetd(8) 启动的程序使用TCP包装器。 |
-W | 根据 hosts.allow (见第19章),对与 inetd(8) 集成的服务使用TCP包装器。 |
举个极端的例子,如果你想使用TCP包装器,每秒只允许来自任何一台主机的两个连接,每分钟允许无限次的服务调用,并且只监听IP地址203.0.113.2,那么你可以在 /etc/rc.conf 中设置以下内容:
xxxxxxxxxx
inetd_flags="-Ww -c 2 -R 0 -a 203.0.113.2"
使用 inetd(8)
,几乎任何东西都可以成为网络服务。
动态主机配置协议(Dynamic Host Configuration Protocol —— DHCP)是向客户端计算机分配IP地址的标准方法。虽然DHCP服务没有与FreeBSD直接集成,但通常需要它们来实现无盘工作站等服务。我们将在这里介绍DHCP配置的基本知识,以便您可以设置自己的网络。
如今,每个防火墙和嵌入式设备都有一个DHCP服务器。为什么需要单独的DHCP服务器?大多数嵌入式DHCP服务器缺乏运行无盘客户端所需的功能,如网络引导服务器和VoIP电话。当它们确实支持这些功能时,这些DHCP服务器通常很难管理。服务旨在在实际服务器上运行。我们将介绍足够的DHCP,以便您配置自己的网络客户端,包括无盘主机。
FreeBSD软件包包括几个DHCP服务器。我喜欢的两个是OpenBSD的dhcpd和ISC DHCP服务器。ISC DHCP server 是行业标准,支持您可能需要的所有功能。对于小型部署,我推荐OpenBSD的 dhcpd 。OpenBSD团队采用了ISC DHCP,去掉了所有很少使用的功能,并制作了一个更小、更简单的服务器。配置文件仍然是单向兼容的;您可以在ISC的DHCP服务器上运行OpenBSD dhcpd配置而不会遇到问题。(如果你没有使用OpenBSD从服务器中剥离出来的任何功能,情况也是如此。)如果你想运行无盘FreeBSD客户端,或者如果你需要LDAP集成,切换到更复杂的ISC服务器是相当简单的。您只能安装这两种服务器中的一种。
任何一台服务器的软件包都包括 dhcpd(8)
、配置文件 /usr/local/etc/dhcpd.conf 和广泛的手册页。
流氓(rogue)DHCP服务器 每个网络应该只有一组权威的DHCP信息。如果你在已经有DHCP服务器的网络上设置了自己的DHCP服务器,比如在你的公司办公室,你可能会破坏一大堆客户端,并触发一大堆给网络团队的电话。设置一个“流氓”DHCP服务器是让网络团队从现在到永远忽略所有帮助请求的好方法。
在我们在办公室之间中继DHCP请求的大型网络中,DHCP可能非常复杂,但在本地以太网上则相当简单。每个DHCP客户端通过本地以太网发送一个广播,要求某人——任何人——提供网络配置信息。如果你的DHCP服务器在本地以太网上,它会直接应答。如果您的DHCP服务器位于另一个网段上,则该网段的路由器需要知道将DHCP请求转发到哪个IP地址。然后,DHCP服务器将配置信息借给客户端,并跟踪哪些客户端被分配了哪些IP地址。向客户端发出的配置称为租约。与您为房屋或汽车支付的租约一样,DHCP租约到期,必须偶尔续订。
客户端可以请求某些功能,例如,Microsoft客户端请求WINS服务器的IP地址,而无盘系统则询问在哪里可以找到内核。您可以根据需要设置所有这些选项。
每个客户端都由用于连接到网络的网卡的MAC地址唯一标识。ISC dhcpd在 /var/db/dhcpd.releases 文件中跟踪MAC和IP地址以及租约。在此文件中,您可以识别哪些主机具有哪些IP地址。如果主机从网络中消失一段时间并返回,如果该IP仍然可用, dhcpd(8)
会向该客户端重新发出相同的IP。
/usr/local/etc/dhcpd.conf 文件包含dhcpd的所有配置。虽然ISC dhcpd(8)
可以而且确实可以自己填满整本书,但我们将重点介绍基本小型办公室所需的功能以及本书后面的示例中使用的功能。默认的 dhcpd.conf 有很好的注释,并包含了更多的示例,而 dhcpd.conf(5)
则非常详尽。我们将假设您在网络上运行一个DHCP服务器,并且您的服务器应该应答所有DHCP服务请求。(完全有可能对dhcpd进行集群以实现容错,但这超出了我们的范围。)
使用一些客户端配置的一般规则启动 dhcpd.conf 。除非特别覆盖,否则这些规则适用于所有DHCP客户端。
xxxxxxxxxx
➊ option domain-name "mwl.io";
➋ option domain-name-servers 198.51.100.2, 198.51.100.3;
➌ option subnet-mask 255.255.255.0;
➍ default-lease-time 600;
➎ max-lease-time 7200;
每个DHCP客户端都向DHCP服务器注册其主机名,但客户端必须从服务器学习本地域名。(DHCP服务器也可以设置客户端的主机名。)使用 domain-name
选项➊进行设置。您可以为DHCP客户端提供任何您喜欢的域名;他们不需要共享服务器的域名。如果用空格分隔,则可以包含多个域,但并非所有操作系统都能识别其他域名。
每个TCP/IP客户端都需要一个或两个DNS服务器。使用 domain-name-servers
➋选项指定它们。用逗号分隔多个DNS服务器。
设置默认子网掩码➌是个好主意。单个网络可以覆盖此掩码,但全局默认值很有用。
租约的正常持续时间由 default-lease-time
选项➍给出(以秒为单位)。租约时间结束后,客户端向DHCP服务器请求新的DHCP租约。DHCP服务器通常默认为几分钟,但如果你的网络相当稳定,你可以将其延长到几小时或几天。如果客户端无法访问DHCP服务器,它将继续使用旧租约,持续时间等于租约的最长寿命(用 max-lease-time
指定)➎. 你可以把最长租用时间想象成 “如果我的DHCP服务器发生故障,这就是我必须在手机开始响铃之前更换它的时间。”给自己时间来解决这个问题。
现在定义子网。
网络上的每个子网都需要一个子网语句来标识该子网上DHCP客户端的配置信息。例如,以下是单个小型办公网络的网络声明:
xxxxxxxxxx
➊ subnet 198.51.100.0 netmask 255.255.255.0 {
➋ range 198.51.100.50 198.51.100.99;
➌ option routers 198.51.100.1;
}
每个子网声明都以标识子网的网络号和网络掩码➊开始。这里,我们有一个子网,使用IP网络号198.51.100.0和网络掩码255.255.255.0,或IP地址198.51.100.1到198.51.100.255。括号中的信息都与特定子网上的主机有关。
range
关键字➋标识 dhcpd(8)
可能向客户端发出的IP地址。在这个例子中,我们有50个IP地址可供客户端使用。如果51个DHCP客户端在任何租约到期之前连接,则最后一个主机将无法获得地址。
使用 routers
选项➌定义默认路由。请注意,您不能使用 dhcpd(8)
定义其他路由;相反,您的本地网络路由器需要有正确的路由才能到达目的地。如果您的本地网络上有多个网关,您的网关会向DHCP客户端发送ICMP重定向,为其提供更新的路由。(如果你不知道这意味着什么,那也没关系。当你需要它的时候,你会突然理解我在说什么,如果你永远不需要它,你只是浪费了两秒钟的时间把它读到一边。)
如果您有多个子网,请创建多个子网语句。其中一些子网可能需要与全局默认值不同的设置,例如网络掩码或DNS服务器。如果是这样,请使用这些相同的关键字为该子网定义这些值。
Dhcpd允许您为旧式Windows客户端设置子网掩码、引导服务器甚至WINS服务器中的任何内容。在第23章中,我们将使用这些不太常见的设置来管理无盘客户端。请参阅 dhcpd.conf(5)
以获取详尽的列表。
dhcpd(8)
Dhcpd默认监听所有网络接口以捕获DHCP请求广播。然而,我运行过许多带有多个网卡的DHCP服务器,通常希望dhcpd只监听单个接口。将所需的接口作为命令行参数。
xxxxxxxxxx
sysrc dhcpd_flags="em1"
现在启用 dhcpd(8)
本身。
xxxxxxxxxx
sysrc dhcpd_enable=YES
现在,您可以使用 service dhcpd start
启动dhcpd。
恭喜你,你准备好了!
在类Unix操作系统上打印是一个让新系统管理员哭泣的话题,而经验丰富的系统管理员则喋喋不休地谈论打印机是TTY设备的美好旧时光,以及年轻一代不知道自己有多好。最常见的打印情况是通过USB端口直接连接到计算机的打印机和连接到网络打印服务器的打印机。
如果你有一台打印机直接连接到你的FreeBSD机器上,比如通过USB电缆,我建议使用通用Unix打印系统(CUPS)。这套软件管理着许多流行的消费级和商用打印机,从低级喷墨打印机到网络级激光打印机。我不会详细介绍CUPS,因为它很复杂,而且因打印机型号而异。了解更多关于CUPS的信息,请访问http://www.cups.org/.许多品牌的打印机在CUPS中都有特殊的设置程序,例如惠普的 hp-setup
。不过,如果您的打印机支持网络连接,请尽量避免使用CUPS,而是使用网络打印。
相比之下,通过 Line printer Spooler Daemon(LPD)访问远程打印服务器或网络打印机很简单。LPD接收PostScript并生成打印输出。大多数办公室打印服务器都运行LPD。 lpd(8)
守护进程管理LPD。大多数现代网络打印机也支持LPD,可以作为自己的打印服务器。
通过连接到TCP端口515测试LPD支持;如果你有连接,设备会讲LPD。
xxxxxxxxxx
# nc -v color-printer 515
Connection to color-printer 515 port [tcp/printer] succeeded!
此设备支持LPD。我们可以通过配置 /etc/printcap 向其发送打印作业。
系统知道的每台打印机都需要在 /etc/printcap (打印机能力数据库)中有一个条目。按照现代标准,这个文件的格式相当迟钝,对于以前没有使用过 termcap(5)
的人来说,会显得非常陌生。幸运的是,要访问打印服务器,您不需要了解 printcap(5)
;您只需要使用以下模板。
要连接到打印服务器上的打印机,您必须拥有打印服务器的主机名或IP地址以及要访问的打印机的名称。按照此模板在 /etc/printcap 中输入一个条目。请特别注意冒号和反斜杠——它们至关重要。
xxxxxxxxxx
➊ lp|printername:\
➋ :sh=:\
➌ :rm=printservername:\
➍ :sd=/var/spool/output/lpd/printername:\
➎ :lf=/var/log/lpd-errs:\
➏ :rp=printername:
我们的第一行显示打印机的名称➊。如果您从LibreOffice或图形网络浏览器打印,这些名称将显示为打印机选项。每台打印机可以有任意数量的名称,用管道符号(|)分隔。任何类Unix系统上的默认打印机都称为 lp ,因此将其列为首选打印机的名称之一。另一个名称应该是打印服务器为打印机使用的名称(例如,3rdFloorPrinter
)。请注意,Microsoft打印服务器经常以几个不同的名称共享一台打印机,并使用不同的名称以不同的方式处理打印。如果您在网络上发现这种情况,请务必选择PostScript名称。
默认情况下,lpd(8)
在每个打印作业之前都有一个页面,列出作业名称、编号、主机和其他信息。除非你在一个只有一台大型共享打印机的环境中,否则这可能是浪费纸张。:sh:\
条目➋会抑制此页面。
rm
(远程机器)变量➌提供打印服务器的主机名。您必须能够按此处提供的名称ping此服务器。如果打印服务器是打印机的一部分,请在此处提供打印机的主机名。
每台打印机都需要一个唯一的卷轴(spool)目录➍,其中本地打印守护进程可以存储传输到打印服务器的文档。此目录必须由用户 root 和组 daemon 拥有。
与必须不同的spool目录不同,打印机可以共享一个公共日志文件➎。
最后,指定远程打印机名称➏,如果您直接连接到打印机,而不是中央打印服务器,则可以跳过此条目,但必须删除前一行的尾随斜线。
确保以新行结束 /etc/printcap ;不要在打印机名称后立即终止文件。此外,请注意,与此模板中的其他条目不同,最后一行不需要尾随反斜杠。
打印机有几十种选择,从每页成本到手动设置字符串来进纸。其中大部分在今天已经过时了。不过,如果你有一台旧打印机或有特殊需求,请咨询 printcap(5)
,了解足够多令人窒息的精彩细节。
在 /etc/rc.conf 中将 lpd_enable
设置为 YES
,使 lpd(8)
在启动时启动。任何时候编辑 /etc/printcap ,都必须重新启动 lpd(8)
。使用 lpq(1)
查看打印队列,并注意 /var/log/lpd-errs 中的任何问题。
让我们结束对小型网络服务的讨论,它可能是目前仍在使用的最小的网络服务,即琐碎文件传输协议(Trivial File Transfer Protocol —— TFTP)。TFTP允许您在没有任何身份验证的情况下将文件从一台机器传输到另一台机器。它也比文件复制协议(如SCP或FTP)灵活得多。TFTP仍被思科等嵌入式设备制造商用于加载系统配置和操作系统更新。我们在这里介绍它只是因为无盘客户端使用TFTP下载其操作系统内核并获取其初始配置信息。在TCP端口69上从 inetd(8)
运行 tftpd(8)
。
TFTP安全 TFTP不适合在公共互联网上使用。任何人都可以在TFTP服务器上读写文件!仅在防火墙后使用TFTP,或至少用TCP包装器严密保护它(见第19章)。
设置 tftpd(8)
服务器包括四个步骤:为服务器选择根目录,为服务器创建文件,为文件选择所有者,以及运行服务器进程。
tftpd(8)
守护进程默认使用目录 /tftpboot 。如果您只有很少访问的几个文件,这可能是合适的,但根分区最好保留给不经常更改的文件。您不希望TFTP上传因填充根分区而导致系统崩溃!如果您正在运行ZFS,请创建一个tftp数据集。在UFS上,我通常将 tftpd(8)
根目录放在 /var/tftpboot 中,并向 /tftpboot 添加一个符号链接:
xxxxxxxxxx
# mkdir /var/tftpboot
# ln -s /var/tftpboot /tftpboot
现在,您可以创建通过TFTP访问的文件。
用户可以通过TFTP读写文件。如果你想让 tftpd(8)
用户能够读取文件,那么文件必须是全球可读的:
xxxxxxxxxx
# chmod +r /var/tftproot/filename
同样,tftpd(8)
不允许任何人上传文件,除非该名称的文件已经存在并且是全球可写的。记住,程序和常规文件具有不同的权限。除了读写权限外,程序还必须具有执行权限,因此您必须为程序和文件设置不同的权限。您可以使用 touch(1)
预创建要通过TFTP上传的文件。
xxxxxxxxxx
# chmod 666 /var/tftproot/filename
# chmod 777 /var/tftproot/programname
是的,这意味着任何知道文件名的人都可以覆盖该文件的内容。将重要文件设置为只读。这也意味着你不必担心有人上传大文件并填满你的硬盘。
TFTP服务器中的文件应由具有最低权限的用户拥有。如果只间歇性运行TFTP服务器,则可以使用nobody用户。例如,如果您只需要TFTP服务器来执行偶尔的嵌入式设备升级,请让没有人的用户拥有您的文件,并在不需要时关闭 tftpd(8)
。但是,如果您运行永久TFTP服务器,最好让一个专用的TFTP无特权用户拥有这些文件。tftp用户不需要拥有 tftproot 目录,事实上,应该有一个完全不同的主目录。他只需要对用户可用的文件拥有所有权。
tftpd(8)
配置tftpd(8)
完全通过命令行参数配置,而且数量不多。有关完整列表,请阅读 tftpd(8)
,但以下是最常用的列表。
如果您创建一个用户只是为了运行 tftpd(8)
,请使用 -u
参数指定该用户。如果不指定用户,tftpd(8)
将作为nobody运行。创建无特权用户。
我建议将所有请求记录到TFTP守护进程中。-l
参数打开日志记录。tftpd(8)
使用FTP功能,您必须在 syslog.conf 中启用该功能(请参阅第21章)。
Tftpd支持带有 -s
标志的chrooting。这使您可以将 tftpd(8)
限制在所选目录中。一般来说,你不希望用户使用TFTP世界可读的文件,如 /etc/passwd ,甚至 /boot/kernel/kernel !始终chroot您的 tftpd(8)
安装。
您可以使用 -c
参数按IP地址chroot TFTP客户端。在这种情况下,您必须为每个允许连接的客户端创建一个目录。例如,假设您要授予TFTP访问权限的唯一主机是您的路由器,其IP地址为192.168.1.1。您可以创建一个目录 /var/tftproot/192.168.1.1 并使用 -c
。您还必须使用 -s
定义 /var/tftproot 的基目录。当你必须只向一两台主机提供TFTP,但你不希望全世界都能访问你的TFTP服务器时,这是一个很好的折衷方案。
您可以选择允许客户端将新文件写入TFTP服务器。这是一个坏主意,因为它让远程用户用任意文件填满你的硬盘。如果必须具有此功能,请使用 -w
标志。
例如,假设您想将所有请求记录到tftpd,chroot记录到 /var/tftpboot ,以用户tftpd身份运行服务器,并按IP地址记录chroot客户端。运行tftpd的命令如下:
xxxxxxxxxx
tftpd -l -u tftpd -c -s /var/tftpboot
按照本章前面的描述将此输入 inetd.conf ,重新启动 inetd(8)
,您就可以开始工作了!
FreeBSD作业调度程序 cron(8)
允许管理员让系统定期运行任何命令。结合系统维护调度系统, periodic(8)
,几乎可以调度任何事情。
cron(8)
如果您需要每晚备份数据库或每天重新加载名称服务器四次,cron是您的朋友。cron(8)
配置文件称为 crontab ,并使用 crontab(1)
进行管理。每个用户都有一个单独的crontab存储在 /var/cron/tabs 中,全局crontab文件是 /etc/crontab 。全局cron条目也可以放置在 /etc/cron.d 中,并将作为 /etc/crontab 的一部分运行。
/etc/crontab
的用途不同于单个用户的crontab。使用 /etc/crontab ,root可以指定哪个用户将运行特定的命令。例如,在 /etc/crontab 中,系统管理员可以说,“以root身份在周二晚上10点运行此作业,以 www 身份在上午7点运行此其他作业。” 其他用户只能以自己的身份运行作业。当然,root也可以编辑用户的crontab。
此外,任何系统用户都可以查看 /etc/crontab 。如果您有一个不想让用户知道的计划作业,请将其放置在用户crontab中。例如,如果您的数据库有一个无特权用户,请使用该无特权用户的crontab运行数据库维护作业。
/etc/crontab 被认为是FreeBSD系统文件。升级时不要覆盖它!简化升级 /etc/crontab 的一种方法是在文件末尾设置自定义条目,用几行哈希标记(#)标记。/etc/crontab 文件必须以新行结束,否则最后一行将无法解析和运行。如果你的最后一个条目是评论,那很好,但如果是命令,那就不太好了。
最后,当你用文本编辑器编辑 /etc/crontab 时,用 crontab -e
编辑用户crontab。
Crontabs在shell中运行,程序可能需要环境变量才能正确运行。您还可以在命令行上为从cron运行的每个命令指定环境变量。cron不从任何地方继承任何环境变量;程序所需的任何环境变量都必须在crontab中指定。例如,这是FreeBSD 12系统上 /etc/crontab 的环境:
xxxxxxxxxx
SHELL=/bin/sh
PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin
是的,这是非常小的!可以根据需要向用户crontab添加环境变量,但在更改 /etc/crontab 时要保守。如果你需要一个自定义环境变量,使用用户crontab而不是 /etc/crontab 是最安全的,因为 /etc/crontab 中的许多命令都是用于核心系统维护的。
在环境语句下面,用户crontab分为六列。前五列表示命令应运行的时间,按顺序为分钟、小时、日期、月份和星期几。任何列中的星号(*)表示每一个(every one),而数字表示此时(at this exact time)。一周中的分钟、小时和天以0开头,一个月和几个月中的天以1开头。此外,由于AT&T和BSD之间古老的分歧,周日可以用7或0来表示。之后,列出当时要运行的命令。
/etc/crontab 文件和 /etc/cron.d 下的文件有一个额外的列:运行命令的用户。它介于时间规范和命令本身之间。如果你愿意,可以查看 /etc/crontab 中的许多示例。
假设我们正在编辑一个无特权用户的crontab,以安排程序的维护。由于 /etc/crontab 在顶部有列标题,我们将在这里演示用户crontab。(要在 /etc/crontab 中使用这些示例,只需在命令前添加用户。)在这里,我们想在每小时后55分钟运行程序 /usr/local/bin/maintenance.sh ,每小时一次:
xxxxxxxxxx
55 * * * * /usr/local/bin/maintenance.sh
星号告诉cron每小时、每月的每一天、每月和每个工作日运行此作业。55
告诉cron只在第55分钟运行此作业。
要在每天下午1:55运行相同的作业,请使用以下命令:
xxxxxxxxxx
55 13 * * * /usr/local/bin/maintenance.sh
在这里,13
代表24小时制的下午1:00,55
代表该小时后的分钟数。
人们在使用cron时犯的一个常见错误是指定了一个大的时间单位,但忽略了小的时间单位。例如,假设你想每天早上8点运行作业:
xxxxxxxxxx
* 8 * * * /usr/local/bin/maintenance.sh
这是错误的。是的,作业将在上午8:00运行。它也将在8:01、8:02、8:03等运行,直到上午9点。如果你的作业运行时间超过一分钟,你的系统很快就会瘫痪。指定上午8:00(仅限上午8:00)的正确方法是:
xxxxxxxxxx
0 8 * * * /usr/local/bin/maintenance.sh
要指定时间范围,例如在周一至周五的上午8点至下午6点之间每小时运行一次程序,请使用以下内容:
xxxxxxxxxx
55 8-18 * * 1-5 /usr/local/bin/maintenance.sh
要指定多个确切时间,请用逗号分隔:
xxxxxxxxxx
55 8,10,12,14,16 * * * /usr/local/bin/maintenance.sh
更有趣的是,您可以指定时间分数或步骤。例如,要每5分钟运行一个程序,请使用:
xxxxxxxxxx
*/5 * * * * /usr/local/bin/maintenance.sh
您可以将范围与步骤相结合。要每5分钟运行一次程序,但比上一个示例晚1分钟,请使用以下命令:
xxxxxxxxxx
1-56/5 * * * * /usr/local/bin/maintenance.sh
使用两个字段控制作业运行的日期:几号(the day of the month)和星期几(the day of the week)。如果同时指定这两个条件,则只要满足其中任何一个条件,作业就会运行。例如,告诉cron在每月的1号和15号以及每周一运行一个作业,如下所示:
xxxxxxxxxx
55 13 * 1,15 1 /usr/local/bin/maintenance.sh
如果您的作业具有非标准环境,请在命令行上设置环境,就像在shell中一样。例如,如果你的程序需要一个LD_LIBRARY_PATH环境变量,你可以这样设置它:
xxxxxxxxxx
55 * * * * LD_LIBRARY_PATH=/usr/local/mylibs ; /usr/local/bin/maintenance.sh
cron还支持使用@符号的特殊调度,例如每年(annually )或每天(daily)。这些术语中的大多数最好不要使用,因为它们可能含糊不清。虽然机器确切地知道它们的意思,但人类往往会误解!每当系统启动时(whenever the system boots),一个有用的crontab条目是 @reboot
。这允许无特权用户在系统启动时运行作业。使用 @reboot
标签而不是时间字段:
xxxxxxxxxx
@reboot /usr/local/bin/maintenance.sh
Crontabs和 cron(8)
允许您以任何您喜欢的方式安排工作,从而消除了许多日常维护任务中的人力。
一些系统维护作业应该只在特定的系统上运行,但它们在所有主机上的运行方式应该是相同的。这就是 periodic(8)
的作用所在。
periodic(8)
命令按计划运行系统函数,如 cron(8)
所确定的。定期检查目录中要运行的脚本集。FreeBSD包括几个用于定期任务的目录: /etc/periodial/daily、/etc/periodical/week、/etc/periterial/monthial 和 /etc/periodity/security 。根据您安装的软件包,您可能在 /usr/local/etc/periodic 中有相应的目录。当cron每天定期运行时, periodic(8)
会检查每个 periodical/daily 目录中的每个脚本,看看是否应该运行它。
当你有空闲时间时,我建议你仔细阅读 periodic(8)
脚本。您可能会发现禁用的维护脚本对您的环境很有用。
应该运行哪些脚本?默认设置列在 /etc/defaults/periodic.conf 中,但您可以在 /etc/periodic.conf 中覆盖它们。
一旦 periodic(8)
运行,它就会将脚本的结果邮寄给本地计算机上的root。将root的邮件转发给真正阅读它的人。
为什么使用 periodic(8)
?这一切都是为了系统维护 /etc/crontab 用于配置您自己的系统管理作业。使用单独的脚本允许系统升级过程替换任务和包以添加和删除它们。
不过,所有 periodic(8)
作业都以root身份运行。如果您有应由权限较低的用户运行的计划作业,请从用户的crontab运行它们。
现在您已经对FreeBSD提供的常见小型服务有了很好的了解,让我们继续讨论性能。