标签 unix 下的文章

最近准备重新回归运维,很好。前一阵子易先生打电话说服务器上 session 失效,他在公司又不方便 ssh 上去看。于是我为了自己的博客勉为其难上去看了一下,结果发现 /var 下面居然爆满溢出了。

www# df -h
Filesystem     Size    Used   Avail Capacity  Mounted on
/dev/ad0s1a    989M     59M    851M     7%    /
devfs          1.0K    1.0K      0B   100%    /dev
/dev/ad0s1d    989M    2.2M    908M     0%    /tmp
/dev/ad0s1e     19G    1.6G     16G     9%    /usr
/dev/ad0s1f    989M    910M   -384K   100%    /var
/dev/ad0s1g    124G    1.7G    113G     2%    /www
/dev/ad2s1d    9.7G    1.4G    7.5G    16%    /database
/dev/ad2s1e    139G     42G     85G    33%    /backup
在啧啧称赞之外,准备找出在 /var 下面所有大于 1MB 的文件:

www# find /var -xdev -size +2048 -ls| sort -r +6 这个搜索结果是相当的恐怖,可以用眼花缭乱来形容当时的屏幕滚动。强行中止后发现绝大部分文件都集中在 /var/spool/clientmqueue 这个目录下面。那么这到底是个什么目录呢?

原来,当使用 sendmail 发邮件,或者系统默认要发邮件(譬如 crontab)的时候,首先会把邮件复制到这个目录里,然后等待 MTA 处理。MTA 做的事情就是把这个目录中的邮件转移到 /var/spool/mqueue,然后再发往目的地。

在 /var/spool/clientmqueue 下产生大量文件的情况,通常是因为没有合适的 MTA 来发送邮件,于是都堆积在这里了。假如这里的邮件并不是你需要的,比如由 crontab 产生的信,你可以简单地删除。

还有一种情况,当这个目录下面的文件数量足够多的时候,直接 rm -f * 的话会被提示 Argument list too long。没事,下面两个命令会帮助你搞定问题:

find /var/spool/clientmqueue/ -type f –delete 或者

find /var/spool/clientmqueue/ -type f -exec rm {} \+ 不过这两条命令要求 find 的版本较新,如果你的文件版本较低,可尝试:

find /var/spool/clientmqueue/ -type f -exec rm {} \; 到这里,我们已经搞明白 /var 爆满的原因。可以判断的是,易先生服务器的问题就在于系统中有用户启用了 crontab,且 crontab 中执行的程序有输出内容。这些内容会以邮件形式发给 crontab 的用户,而 sendmail 又没有启动,所以就大量产生了这些队列文件。

解决的办法很简单,在 crontab 中命令的最后加上:

>/dev/null 2>&1 这样输出的内容会被直接抛弃,问题就得以解决了。

最后也顺便提一下禁用 sendmail 的事情。本地 MTA 正确工作是 Unix 系统正确工作的一个必要条件。盲目禁止 sendmail 意味着对安全的不关注。如果你不打算启动任何邮件服务,就不应该使用 sendmail_enable="NONE",而应使用 sendmail_enable="NO"。

当然,你也可以考虑用下面的办法来彻底消除其影响,但我认为没什么必要。在 /etc/make.conf 中加入:

NO_SENDMAIL=yes
INSTALL=install
然后 make buildworld installworld,然后用 find 删除 lib、libexec、usr/bin、usr/sbin 等目录中没有被碰过的文件,最后删除 /etc/mail、/etc/rc.d/sendmail 等文件。这个方法来源于网络,没有亲自实验,请谨慎操作。

又是一个不眠之夜,写点东西好了。

上个月托管在某电信机房的服务器遭受ARP 欺骗,虽然不是我的服务器中毒,但还是受到了一定程度的影响。事后我认识到双向绑定的重要性,于是和机房联系做了双绑。

对于双向绑定,我的理解是在下级客户端与上级网关上分别知道自己与对方的 IP 及其 MAC 地址,并且这是一个静态的关系。ARP 协议中,默认的关系是 dynamic,而且这与使用 DHCP 与否没有关系。我们来做个实验:

C:\>arp -a
Interface: 192.168.0.201 --- 0x10003
  Internet Address      Physical Address      Type
  192.168.0.1           00-14-78-99-3d-a9     dynamic
  192.168.0.50          00-0b-2f-10-12-ab     dynamic
C:\>arp -d
C:\>arp -s 192.168.0.1 00-14-78-99-3d-a9
C:\>arp -a
Interface: 192.168.0.201 --- 0x10003
  Internet Address      Physical Address      Type
  192.168.0.1           00-14-78-99-3d-a9     static
  192.168.0.50          00-0b-2f-10-12-ab     dynamic
这个例子已经说明了问题。绑定后的状态一直都是 static,直到系统下次重启。

如果服务器处于双线机房,或者由于其他原因,具有一个以上的 IP 地址,其操作方式雷同。我的服务器上有两个 IP 地址,arp -a 后的结果是这样的:

C:\>arp -a
Interface: 60.12.104.24 --- 0x10003
  Internet Address      Physical Address      Type
  60.12.104.1           00-11-bb-3e-62-3f     dynamic
  122.225.96.1          00-11-bb-3e-62-3f     dynamic
我设计了以下的脚本。将它放入计划任务,并设置为每次系统启动时启动该脚本,配合机房在网关设备上对该服务器 IP 与其 MAC 地址的绑定,就可以使 Windows 操作系统的服务器具备防止 ARP 欺骗的能力:

@echo off
arp -d
arp -s 122.225.96.1 00-11-bb-3e-62-3f
arp -s 60.12.104.1 00-11-bb-3e-62-3f
exit
对于类 Unix 操作系统的操作也基本相似。首先通过 arp -a 获取当前信息:

#arp -a
? (60.12.104.1) at 00:11:bb:3e:62:3f on em0 [ethernet]
? (60.12.104.31) at 00:0e:0c:3c:7d:ba on em0 permanent [ethernet]
? (122.225.96.1) at 00:11:bb:3e:62:3f on em0 [ethernet]
nstech (122.225.96.31) at 00:0e:0c:3c:7d:ba on em0 permanent [ethernet]
然后执行单向绑定,注意类 Unix 系统下对 MAC 地址的书写方式:

#arp -s 122.225.96.1 00:11:bb:3e:62:3f
#arp -s 60.12.104.1 00:11:bb:3e:62:3f
服务器上操作完成后,要求机房在网关设备上对该服务器 IP 与其 MAC 地址的绑定,就实现了传说中的双向绑定。

如果服务器当前正在遭受 ARP 欺骗攻击,在机房没有对中毒服务器实施断网处理前,我们只能每隔一段时间就执行一下上面的操作。为了方便起见,我们可以这样做:

#vi /etc/ipmac 将需要做绑定的网关 IP 与其 MAC 地址写入这个文件。每行一个,中间用空格隔开:

122.225.96.1 00:11:bb:3e:62:3f
60.12.104.1 00:11:bb:3e:62:3f
然后:

#crontab -e 添加一行:

*/1 * * * * /usr/sbin/arp -f /etc/ipmac 这里的“*/1”代表每隔 1 分钟执行一次,可以根据实际情况调整。和平时期,我一般设置为 10 分钟执行一次:

* */6 * * * /usr/sbin/arp -f /etc/ipmac 战争时期就设置为 5 秒执行一次:

*/12 * * * * /usr/sbin/arp -f /etc/ipmac 对于 Windows 操作系统,只要重新设置一下计划任务的属性,让它每隔一段时间执行一下脚本就可以了。

咳咳,综上所述,这个解决方案是一个临时性解决方案,比较适用于非战时的防御。如果真的遭遇 ARP 欺骗攻击,第一件事还是通过 arp -a 找到源头,然后将信息报告给机房,让机房尽快将中毒的机器断网才是上策。

听说 FreeBSD 系统下面有一个软件叫做“ipguard”,可以有效防御 ARP 欺骗。有空研究一下。