November 2011 Archives

DNSSEC 是一种验证域名信息真实性的协议扩展。个人之前一直觉得这事相当的蛋疼:DNS协议本身是不安全的,而DNSSEC无非是增加了数字签名验证,而这验证还依赖于相当复杂的密钥更新和分发机制,这一切都给它的推广带来了困难。

最近闲着没事把几台自己的机器上的 unbound 配置了 DNSSEC 支持。 unbound 是一款 NLnet Labs 开发和维护的 DNS 缓存(解析)服务器实现,它内建了对 DNSSEC 的验证支持。与比较常用的 BIND 相比, unbound 性能更好,并且在设计时充分考虑了安全问题,在安全方面有很好的记录。

在 FreeBSD 上可以使用 port 来安装 unbound:

# cd /usr/ports/dns/unbound
# make install

在 /etc/rc.conf.local 中启用 unbound:

# echo 'unbound_enable="YES"' >> /etc/rc.conf.local

配置 unbound,如果需要对外提供服务,在 /usr/local/etc/unbound/unbound.conf 中的 server 小节添加:

	interface: 0.0.0.0	# 监听所有IPv4地址
	interface: ::0		# 监听所有IPv6地址

(20130423增加) 注意! 如果监听所有 IPv4 和 IPv6 地址的话,就必须限制允许访问的 IP 地址范围。假设一台主要针对内网,同时为 202.96.0/24 服务的服务器,应配置如下 ACL:

        access-control: 0.0.0.0/0 deny # 禁止除下列地址之外的所有IPv4地址
        access-control: 202.96.0/24 allow
        access-control: 10.0.0.0/8 allow # RFC 1918
        access-control: 172.16.0.0/12 allow # RFC 1918
        access-control: 192.168.0.0/16 allow # RFC 1918
        access-control: 127.0.0.0/8 allow # 允许本机查询
        access-control: ::0/0 deny  # 禁止除下列地址之外的所有IPv6地址
        access-control: (自己的IPv6网段) allow
        access-control: ::1 allow # 允许本机查询
        access-control: ::ffff:127.0.0.1 allow # 允许本机查询

当然,对于对内网服务的机器来说,应单独指定内网的 IP 地址而不是监听全部可用 IP 地址,以避免暴露攻击面。此时还应配置 outgoing-interface,具体请参见配置文件中的说明。

然后是获得 trust anchor,这和根证书的意思类似。unbound-anchor 可以创建和更新 trust anchor。用下面的命令来下载和立即检查trust anchor的完整性,这个检查是使用 unbound-anchor 内建的 ICANN 证书进行的,如果不确认的话,还应检查它的完整性,包括 unbound-anchor -l 和检验源代码,不过由于 FreeBSD 的 portsnap 系统采用了数字签名验证,并对每个源码包都做 SHA256 校验,因此一般来说可以认为没有问题。

# sudo -u unbound unbound-anchor
# sudo -u unbound unbound-anchor -a "/usr/local/etc/unbound/root.key" || echo "Wrong key!"

如果一切正常,则系统不会给出任何提示。

配置 unbound 使用 DNSSEC 验证只需在 server 小节增加一行:

	auto-trust-anchor-file: "/usr/local/etc/unbound/root.key"

然后重启 unbound 即可。用 dig com. SOA +dnssec 应该可以看到 DNSSEC 验证成功(flags: ad):

% dig com. SOA +dnssec 

; <<>> DiG 9.8.1-P1 <<>> com. SOA +dnssec
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 4552
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 14, ADDITIONAL: 1
(...)

此外也可以用浏览器访问 http://dnssectest.sidn.nl/ 来测试。

目前美国联邦政府的许多网站都已经启用了 DNSSEC,但在大家的缓存服务器以及更多的商业站点支持 DNSSEC 之前,这样做并不能显著改善安全性。

netmap进 -CURRENT

| No Comments | No TrackBacks

近日, netmap 已经正式进入 -CURRENT (r227614)。目前联编带 netmap 的内核需要做下面的操作:

% cd /usr/src/sys
% patch -p0 < dev/netmap/head.diff

然后在内核联编配置中加入:

device netmap

目前,这个补丁包括了对 Intel 万兆以太网适配器 ixgbe(4)、千兆以太网适配器 igb(4) 和 em(4) 以及 Realtek 千兆以太网适配器 re(4) 的支持。由于 netmap 的设计,对其他驱动的修改也相当简单,只需增加大约 15 行左右的代码即可。

在 src/tools/tools/netmap 中提供了一系列用户态的例子,包括一个简化的 libpcap 实现(不完整,但足以支持 tcpdump 运行)、一个用户态网桥、用户态高速收发包测试,以及使用 Click 的例子(需要 netmap 的那个 libpcap 实现)。

clang静态分析工具作弊条

| No Comments | No TrackBacks

静态分析是一种辅助的代码品质提高手段,简而言之静态分析大致是走一个类似编译的过程(或者走完生成副产品),然后给出代码中可能存在的问题。

FreeBSD Ports Collection 中提供的 lang/clang-devel 内建了 clang 项目的静态分析工具。这个工具的用法非常简单,假设我们原先的联编命令是:

make -j 4 all

那么,配合clang静态分析工具来产生输出的命令便是:

scan-build -o /tmp/scan make -j 4 all

以上, /tmp/scan 是输出目录。scan-build可以设置必要的环境变量来让make使用ccc-analyzer代替${CC}来完成编译工作,并把输出保存到指定目录的一个唯一的子目录中。下面,我们可以运行:

scan-view --allow-all-hosts --no-browser --host 10.4.2.253 /tmp/scan/2011-11-17-1

上面的/tmp/scan/2011-11-17-1是scan-build在最后告诉我们的那个结果,而 10.4.2.253 是本机 IP 地址。用浏览器访问 http://10.4.2.253:8181 就可以看到编译过程中发现的问题了。

需要说明的是,静态分析工具并不总是能给出理想的输出结果。开发者需要充分分析程序逻辑之后再做修改。

FreeBSD 的 InfiniBand 支持

| 3 Comments | No TrackBacks

现时 InfiniBand 硬件已经相当廉价。有些 4x 的 InfiniBand 适配器已经可以在 $100 以内拿到。由于 InfiniBand 可以提供高带宽、低延迟的数据传输,而且点对点对联不需要交换机,因此可以以十分低廉的价格满足近实时同步,或分离存储服务这样的需求。

今年年初的时候, Isilon我厂Panasys 联合资助了 FreeBSD 上的 InfiniBand 协议栈的实现。这个实现基于 OpenFabrics Alliance 的 OFED,对基于 Mellanox 芯片的多种常见的 InfiniBand 卡都提供了支持。这些代码目前已合并至 FreeBSD 的开发主线,并将随 FreeBSD 9.0-RELEASE 发布。

目前关于 InfiniBand 在 FreeBSD 上的使用介绍还很少,并且目前 InfiniBand 相关的支持还没有默认启用,所以在这里进行一些简要的介绍:

首先是编译系统。在 /etc/make.conf 中添加:

WITH_OFED=

相关的内核配置包括:

options OFED             # OFED协议栈,必需
options OFED_DEBUG_INIT  # 调试
options SDP              # SDP (Sockets Direct Protocol) 协议
options SDP_DEBUG        # SDP 调试
options IPOIB            # IP-over-InfiniBand
options IPOIB_CM         # IP-over-InfiniBand Connection Mode
options IPOIB_DEBUG      # IPoIB-CM 调试

以及下列设备:

device  mlx4ib           # ConnectX InfiniBand支持
device  mlxen            # ConnectX 万兆以太网支持
device  mthca            # Mellanox Technologies HCA (只有IB)

如果使用的是 ConnectX 卡,则可以用 mlxen 令其呈现为一个网卡。

重新联编、安装内核和world之后,系统会提供下列函数库来供开发使用:

  • libibcm
  • libibcommon
  • libibmad
  • libibumad
  • libibverbs
  • libmlx4
  • libmthca
  • libopensm
  • libosmcomp
  • libosmvendor
  • librdmacm
  • libsdp

比较常用的是 RDMA CM 和 SDP 的库。其中,通过使用 LD_PRELOAD,libsdp可以让(二进制的) TCP 程序不加修改的直接走 SDP 协议;RDMA 适合对性能要求更高的场合。需要说明的是,如果用 SDP 协议的话,还需要运行子网管理服务 opensm。

总体上使用和 Linux 上的 OFED 差不多,现成的程序不需要做太多修改即可直接运行。

有关"非正常终止"

| 2 Comments | No TrackBacks

多年以前在 USENIX HotOS 2003 论文集中看到了 一篇 关于 "Crash only software" 的论文,当时有一些想法,但很多没有认真地实践。最近做的东西用到的这方面的设计方法比较多,总结一下写出来。

在设计系统时,很多时候我们会花很多的精力去考虑正常终止的情况,对于希望尽可能少出现 downtime 的系统来说,这很可能是不必要的。

简而言之,程序有两种终止方式,正常的和不正常的;正常的终止是可预期的,非正常终止不一定发生在什么时候----因为程序设计缺陷、系统管理员杀掉、硬件故障如电源出现问题,等等。

很多时候处理正常终止所需的代价要比非正常终止来的更大。例如在正常的 OS 关机过程中,内核需要通知所有的服务进程退出(这一点目前还是必要的,因为不是所有的程序都设计了从非正常停机中恢复)、通知其他节点自己下线了、甚至某些早期的 Windows 版本还会关闭网络连接,等等,最后还要把内存中到目前为止还没写盘的数据刷到磁盘上,然后再停止运行。而恢复时,则往往会有一些技术来帮助系统尽快地恢复到可以运行的状态,许多时候,在崩溃后引导系统和在正常关闭后引导系统所需的时间是非常接近的。

这造成了一个很奇怪的现象:一方面,我们花费了相当多的时间精力去撰写正常关机所需的代码,而另一方面,这些代码的存在往往会导致系统恢复的时间变得更慢一些。(这篇论文写于 2003 年,其中举了一些实际的例子,如 RedHat 8 正常重启所需要的时间是104秒,而非正常重启则只需75秒;JBoss 3.0分别是47秒对39秒,Windows XP则是61秒对48秒)。还有就是,增加的这些复杂的代码对于长时间运行的系统实际上是很少用到的,系统能够正常地持续运行的时间越长,这些代码就越少会执行到。

因此,对于很多互联网应用来说,既然有那么多的可能性导致异常终止没办法避免,更好的设计就应该是程序中只去考虑非正常终止的问题。程序把启动过程也作为异常终止之后的恢复来实现,而正常终止直接让程序崩溃就可以了,主要的精力应该放到"让恢复过程变得更快和更可靠"以及"让程序运行的过程中任何一个点发生的异常终止都不会导致恢复出现问题"两件事上。

如何实现

原文中列举了一些实现策略,下面是我自己的一些总结:

  • 需要持久保存的状态由专用的组件来管理,避免在应用逻辑中直接操作;
  • 持久化组件只考虑存储的一致性,可以采取 Copy-on-write 和异步写操作之前先同步写日志等方法来改善恢复速度;
  • 分布式系统中,对方未确认数据已经到了可靠的地方,就不要认为处理已经完成;远程调用皆设超时并做对应处理;调用者同时也作为监督者,在认为服务出现问题时可发起重启服务的请求;
  • 组件之间尽量隔离(当然这也是面向对象设计的相当基本的要求),避免接口以外的直接交互;
  • 对资源使用进行限制,例如通过 OS 限制进程能够使用的内存和 CPU 时间以及实际运行的最长时间等等;

做到这些以后直接将正常停止改为 kill -9 即可。当然,尽量避免程序 bug 导致的崩溃仍然是非常重要的。

Monthly Archives

Pages

OpenID accepted here Learn more about OpenID
Powered by Movable Type 5.2.3