在大多数开发环境中,并不是在产品的整个生命周期中都考虑安全性而是在出现安全性问题后才采取补救措施。但是采取措施并不一定很可靠。例如可以写一段代码,建立网络连接,然后连接到一个库 — 该库用执行加密和认证的版本代替所有的传统网络调用。实际上,这种集成的容易性是安全套接字层,或称为 SSL(用于 secure HTTP 连接的协议)的最初目的之一。SSL 的几种实现已经在试图顺便替代标准 Berkeley UNIX socket API,或者带有尽可能相似接口的库。
OpenSSL 库(请参阅参考资料)是尝试后一种方法的一个很好的示例。在 OpenSSL 库中,相似的 API 模仿传统的套接字调用,使用 SSL 上下文对象代替文件描述符。例如,传统的写入套接字的调用具有以下特征:
/* Returns the number of characters successfully written */
size_t write(int file_descriptor, void *buf, size_t len)
OpenSSL 更改每个参数的类型,但每个参数的语义不变:
/* Returns the number of characters successfully written */
int SSL_write(SSL *socket_info, char *buf, int len)
实际上,除 SSL 对象之外,其它所有的类型与初始调用都是兼容的。理想情况下,开发者能够对程序进行较小的修改,只需添加一些代码从文件描述符初始化 SSL 上下文即可。而事实上,SSL 库都不容易使用。例如,开发者要写许多附加代码才能使 OpenSSL 在多线程环境下工作。实际上,为将这个库集成到代码中去,大多数开发组织花费的精力都比他们预计的要多的多,而结果还常常是一片混乱。
幸运的是,有一种方法可以将加密功能无缝添加到网络连接中,而不会将您原来的代码段基址搞乱。Stunnel 是一个程序,可以使用 OpenSSL 库对任意 TCP 会话进行加密。它作为服务器运行在程序外部。Stunnel 服务器主要执行两个功能:一,首先,接收未加密的数据流,进行 SSL 加密,然后将其通过网络发送;二,对已进行 SSL 加密的数据流进行解密,并将其通过网络发送给另一个程序(该程序通常驻留在同一机器上,以避免本地网络上的窥探攻击)。这样,在必要时,您就可以很容易地运行未加密的程序,当您想要“嗅探”网络,看看到底有什么东西正在通过网络时,这一点很有用。
即使您是一个系统管理员,而不是一个开发者,Stunnel 对您来说也是一个强大的武器,因为它可以向不启用 SSL 的服务器端软件添加 SSL。例如,我已经使用 Stunnel 来保护 POP、SMTP 和 IMAP 服务器。唯一不太尽人意的地方是要使用这些服务器的安全版本,客户机必须是可识别 SSL 的。Stunnel 要求已经安装了 OpenSSL。它已被移植到了 Windows,以及大多数 UNIX 平台。一旦安装了 Stunnel,用它来保护服务器就很轻松。例如,您可以通过将常规服务绑定到本地主机使 IMAP 服务器启用 SSL,然后在外部 IP 地址(假设 IMAP 服务器已经在运行,且外部地址为 192.168.100.1)运行 Stunnel:
stunnel -d 192.168.100.1:imap2 -r 127.0.0.1:imap2
-d 标志指定我们希望用来运行自己的安全服务的端口。imap2 字符串指定使用标准 IMAP 端口;我们也可以将其设为 143。Stunnel 检查 "/etc/services" 文件以便将符号名映射到端口号。并非所有的机器都拥有这个文件(有些机器并不列出所有的标准服务),所以使用数字比使用服务名更方便。
-r 标志指定未加密的 IMAP 服务器运行所在的端口。
这个解决方案要求您的 IMAP 服务器只在回送(loopback)接口上侦听。如果 IMAP 服务器绑定到 IP 地址“0.0.0.0”,那么它将侦听机器上每个 IP 地址上的信息,包括 192.168.100.1;这会导致出现一条出错消息,指出我们的安全服务端口已在使用中。大多数服务都可以配置为只绑定到一个接口。不然的话,可能要更改一行代码。
另外,您可以将一个未加密的服务器设在一个非标准端口上。例如,您可以在端口 1143 上运行 IMAP,然后将安全的 IMAP 数据流转发到该端口。一般情况下,您不希望其它机器上的用户访问您未加密的服务。运行服务的机器上的个人防火墙可以加强这种策略。
使用 Stunnel 来保护如 IMAP 等服务面临的一个问题是服务器只接收来自我们提供的 Stunnel 服务器的连接。因此,所有的连接都看起来好象是来自本地机器。在 Linux 上,可以通过传递 -T 标志避开这个问题,传递 -T 标志可以使 Stunnel 服务器透明地代理信息包,这样真正的服务器就可以得到接收到的所有信息包中的正确的源地址。
安全性问题要比我们想象的困难的多。理想情况是,我们单击一下按钮就可保证自己的应用程序安全。在对网络连接加密时,值得称赞的是 Stunnel 接近了“单击 — 安全”的理想境界,允许我们向在其它方面已经完整的应用程序添加安全性。不幸的是,Stunnel 有一些局限性。在服务器端,它当前只能够透明地代理 Linux 客户机。在客户机端,不容易执行充分的证书验证。
尽管如此,Stunnel 仍是实用价值很高的实用程序,应该成为程序员,同样也是系统管理员的看家法宝。如果您正在开发自己的软件,应该能够很容易地将 Stunnel 集成到程序中。服务器代码不需修改,使用本文中提供的框架通常可以很容易地对客户机代码进行改写。