FreeBSD的优势,其实是在一次偶然的局域网测试中意外发现的。当时我们模拟了一个互联网环境,用一台Windows客户端分别向Windows Server、Linux Server以及一台FreeBSD服务器发送Syn Flood数据包——这是DDoS攻击中最常见的手段。结果如何?Windows服务器在接收10个数据包后直接瘫痪;Linux服务器在10个包时连接开始异常;而FreeBSD却硬生生扛住了超过100个攻击包。这一结果确实令人眼前一亮。很快,这个方案被全面采纳,公司内的所有Web服务器都迁移到了FreeBSD平台。
迁移到FreeBSD后,系统确实平稳运行了一段时间。然而好景不长,最近又有用户反馈网站访问异常,表现为页面加载缓慢,甚至直接提示“找不到网站”。通过 netstat -a 检查发现,来自某个IP的连接正好达到50个,状态清一色显示为 FIN_WAIT 1——这是典型的DDoS攻击特征。看来,没有防火墙的FreeBSD也并非无懈可击,于是安装防火墙这件事再次被提上日程。
查阅大量资料后发现,FreeBSD下最常见的防火墙是IP FireWall,简称IPFW。但问题在于,启用IPFW需要先编译系统内核。而且出于安全考虑,IPFW在编译完成后默认会拒绝所有网络服务——包括对系统本身的访问。这就麻烦了:对于远程服务器,总不能伸手碰到吧?这里需要特别提醒,配置时稍有不慎,就可能让服务器拒绝一切服务。本次测试是在一台安装了FreeBSD 5.0 Release的服务器上进行的。
二、配置IPFW
实际上,可以把安装IPFW理解为一次软件升级。在Windows中升级软件,通常是下载安装包然后运行;在FreeBSD中类似,只不过这次要启用的功能是系统自带的,只需打开开关即可。但在开启之前,还需做一些准备工作。
下面进入配置环节。
第一步:准备工作
在命令提示符下执行以下操作:
# cd /sys/i386/conf
如果提示没有该目录,说明系统未安装ports服务,需要先安装。
# cp GENERIC ./kernel_IPFW
第二步:内核规则
用编辑器打开 kernel_IPFW 文件,在末尾添加以下四行内容:
options IPFIREWALL
options IPFIREWALL_VERBOSE
options IPFIREWALL_VERBOSE_LIMIT=10
options IPFIREWALL_DEFAULT_TO_ACCEPT
简单解释这些选项的作用:
- options IPFIREWALL:将包过滤代码编译进内核。
- options IPFIREWALL_VERBOSE:启用通过Syslogd记录的日志。如果不加此项,即使规则中设置了记录,也不会真正记录。
- options IPFIREWALL_VERBOSE_LIMIT=10:限制每条规则通过Syslogd记录的条数。当服务器遭受攻击时,防火墙日志会大量生成,此选项可防止日志撑爆系统。
- options IPFIREWALL_DEFAULT_TO_ACCEPT:这一项至关重要。它将默认规则从“拒绝”改为“允许”。也就是说,在默认状态下,IPFW相当于不存在,接受所有数据。待安装完成后再根据需要添加具体规则。
保存文件并退出。
三、编译系统内核
FreeBSD和Linux一样,都是开源操作系统,并不像Windows那样代码封闭。系统内核持续迭代升级,为了使用新功能或定制更高效的运行环境,我们经常需要编译内核。这里编译的目的,是获得一个更稳定、性能更优的系统,而非单纯追求新版本功能。
编译过程中可能会遇到一些错误提示。为了减少报错,配置文件已尽可能精简。如果仍有提示,建议仔细检查是否存在拼写错误等小问题。
接下来在命令行执行:
# /usr/sbin/config kernel_IPFW
执行后会看到如下提示:
Kernel build directory is ../compile/kernel_IPFW
Don't forget to do a `make depend`
# cd ../compile/kernel_IPFW
这里需要注意:FreeBSD 4.x 版本路径为 ../../compile/kernel_IPFW,而 FreeBSD 5.0 版本路径为 ../compile/kernel_IPFW,两者不同。
# make
# make install
编译时间取决于系统性能,双P4 Xeon、1GB内存的服务器大约5分钟即可完成。
四、加载启动项
编译完成后,还需要让系统在启动时自动运行IPFW并记录日志。
第一步:编辑 /etc/rc.conf
加入以下参数:
firewall_enable="YES" # 激活防火墙
firewall_script="/etc/rc.firewall" # 防火墙默认脚本
firewall_type="/etc/ipfw.conf" # 防火墙自定义脚本
firewall_quiet="NO" # 是否显示规则信息;规则不再改动时可设为"YES"
firewall_logging_enable="YES" # 启用日志记录
第二步:编辑 /etc/syslog.conf
在文件末尾添加:
!ipfw
*.* /var/log/ipfw.log
这条规则的作用是将IPFW日志写入 /var/log/ipfw.log,当然也可以指定其他路径。
完成以上步骤后,重启系统。
五、使用并保存规则
重启后,你会发现已经可以通过SSH登录远程服务器了。
第一步:测试
刚登录时可能感觉不到明显变化。但试着运行以下命令:
# ipfw show
会看到类似这样的输出:
65535 322 43115 allow ip from any to any
这表明IPFW已成功启用,当前允许所有连接。
第二步:使用
在命令提示符下输入:
# ipfw add 10001 deny all from 218.249.20.135 to any
这条命令会拒绝来自IP 218.249.20.135 的所有服务。执行之后,来自该IP的所有请求都会被拦截。
第三步:保存
将上面的规则添加到 /etc/rc.firewall 文件中:
ipfw add 10001 deny all from 218.249.20.135 to any
注意,保存到 rc.firewall 时,前面不要加#。然后运行:
# sh /etc/rc.firewall
该命令会重新载入IPFW规则。或者直接重启系统,IPFW就会生效。只要不手动解除规则,来自 218.249.20.135 的所有信息都将被拒绝。
