邱俊源, 张 跃
(清华大学深圳研究生院嵌入式系统与技术实验室,广东深圳518055)
网络通信模块是许多数据交互系统的基础,然而在当前严峻的网络环境之下,网络数据传输时常面临着数据窃取、数据篡改以及恶意连接的威胁。按照一般的明文传输方法,隐私数据的保密性无法得到保证,甚至数据通讯过程都有可能遭到破坏。
远程无线多生理参数实时监测与分析网络平台[1-2]是远程监护和家庭护理的一个应用,是集以心电信号为主的多生理参数采集、数据远程传输、监控分析于一体的软硬件整体解决方案。为了保障各个实时监护服务器的监护数据汇总到信息中心数据库过程中的通讯安全,本文在 OpenSSL库及WSAAsyncSelect模型基础上设计并实现了一个基于异步消息通知及SSL安全连接协议的安全通信模块,提出了通过面向对象的方式并行处理安全网络通讯的新方法,有效地解决了上述问题。
1.1.1 一般通信I/O模式及存在问题
现有的安全通信模块中,基本都是基于阻塞模型,其优势在于简单直接,适用于简单应用程序的快速原型化。采用这种模型的应用程序,在处理I/O时往往对每个连接都要建立一至两个线程,在线程中循环发出阻塞调用。这也正是这种模型的局限之处,创建多线程通常需要耗费较多的系统资源,同时如果涉及到多线程数据交互更是需要进行繁琐的同步工作,异步通知模型则可以高效解决这种情况下的并行处理问题。
1.1.2 WSAAsyncselect模型
WSAAsyncSelect(异步选择)模型是Winsock提供的一个有用的异步I/O模型,通过这个模型应用程序可以接收制定套接字上的网络事件通知,这些异步通知通过窗口消息的方式传递。要使用WSAAsyncSelect模型,须创建一个消息接收窗口,通过WSAAsyncSelect函数打开指定套接字上的消息通知。该函数定义如下:
常用网络事件类型如表1所示。
表1 常用网络事件
通过对相应消息的处理,应用程序即可实现对网络连接的控制,最突出的一方面是它可以在系统开销不大的情况下同时处理许多连接。通过 WSAAsyncSelect模型作为事件驱动,安全通信模块可以进行应用层协议的处理,并按需调用用户的事件处理函数。
按照功能定位的不同,与安全通信模块有关的共3个层次,分别为发出网络I/O事件的内核层、进行SSL协议处理的安全连接层及进行SSL I/O事件处理的用户逻辑层。图1为安全通信模块的类结构UML定义。CAsyncSocket及CAsync-SSLSocket组成了安全连接层,CUserSocket即为实现用户自定义I/O处理的用户层。
图1 类设计
CAsyncSocket封装了网络套接字 SOCKET变量,通过WSAAsyncSelect函数打开封装套接字的网络消息通知,并建立了对应的隐藏窗口接收网络消息,通过窗口消息处理函数构建了网络事件多路分解及调度框架。CAsyncSocket定义了对应各网络事件的处理接口,子类通过覆盖CAsyncSocket中的OnReceive等几个方法实现具体的事件处理。这项技术通过C++中的多态机制完成。
图2 事件处理流程
CAsyncSSLSocket是整个安全通信模块的核心,它通过继承CAsyncSocket实现对套接字I/O事件的处理,在这基础上通过封装了OPENSSL库中的SSL连接对象在套接字层上建立了SSL安全连接层,在这个类中完成了SSL连接的握手、用户明文数据至密文的转化及接收密文到用户明文的转化。
CAsyncSSLSocket中主要定义了两类接口,一是基本I/O接口,由用户或子类直接调用,另外就是SSL层I/O事件处理接口,这类接口需要用户通过继承CAsyncSSLSocket并覆盖该类接口实现自己的I/O事件处理方法,其中基本接口如下:
(1)SSL连接对象创建接口
(2)SSL发起连接接口
(3)关联SOCKET对象接口
(4)设置SSL连接对象为服务态接口
(5)设置SSL环境参数接口
SSL层I/O事件处理接口的设计与底层I/O事件处理接口设计是一致的,遵循高可扩展性的原则,各个接口如下:
(1)SSL连接建立结果通知事件接口(2)SSL连接数据可读事件处理接口
(3)SSL连接数据可发送事件处理接口
(4)SSL连接断开事件处理接口
CUserSocket类即用户自定义对象,通过覆盖父类中的SSL层I/O事件处理接口完成自定义的事务逻辑处理。用户只需调用CAsyncSSLSocket的I/O接口即可在SSL连接上进行数据通讯,SSL层的处理对用户来说是完全透明的,使用方法也与普通套接字风格一致,具有较高的易用性。
整个安全通信过程中的事件处理流程如图2所示。如前面所述,整个异步通信由内核的底层网络事件消息驱动。
首先是FD_CONNECT事件,指示套接字连接建立完成结果,如果建立完成则SSL连接层首先进行SSL连接对象的初始化,如果是客户端则要首先发起与服务端的SSL连接握手。
接着是不定次数的FD_READ及FD_SEND事件,在SSL连接握手未完成的情况下,SSL层首先进行SSL握手处理,主要内容为客户端与服务端的证书交换、合法性验证及后续通讯过程的密钥协商。完成连接握手后SSL连接进入正常通信状态,FD_READ及FD_SEND事件就指示SSL层数据可读及数据可写,由SSL层分别调用用户定义的SSL层I/O事件处理接口进行处理。
最后就是套接字连接中断事件,SSL层首先进行已分配的SSL连接对象的回收处理,最后调用用户的SSL连接中断处理接口。
SSL协议全称为SecureSocketLayer协议,最早由Netscape公司提出,它位于传输层协议与应用层协议间,用以提供安全通信保障。SSL中又包含两个协议:SSLRecordProtocol及SSL Handshake Protocol,前者可以对不同的上层应用协议进行封装,后者则为在SSLRecordProtocol之上的SSL连接握手协议,在连接开始前进行连接双方的身份验证并协商好后续连接使用的加密算法及密钥。
SSL协议提供以下特性:
(1)身份验证,连接端的身份通过非对称加密算法进行验证。
(2)数据保密性,连接双方通过握手协商的对称加密算法及密钥保障连接过程的数据不被窃听。
(3)数据完整性,通过在数据包上附加数字摘要,通过MD5,SHA1等安全摘要算法计算得到,可保障数据包不被篡改。
当前SSL协议已经有诸多版本:SSL1.0、SSL2.0、SSL3.0及TLS1.2等等,后两者是最常用的版本。
SSL握手主要进行连接双方的身份验证及密钥协商,其过程如图3所示。
握手过程首先由客户端的发起,ClientHello及ServerHello组成了握手的第一个阶段,完成两端随机数的交换,确定加密算法套件及压缩算法。
图3 SSL握手协议[3-4]
第二阶段是证书验证阶段,客户端与服务器通过Certificate报文交换数字证书,完成相互验证。其次完成密钥参数协商,在服务端证书中不包含用于协商的密钥信息时还需通过ServerKeyExchange发送相应的密钥,其内容根据密钥产生算法而不同,如使用RSA公钥算法就包含服务端的公钥,而DH算法则为服务端的DH公开参数。
第三阶段客户端及服务端将协商出后续通讯所使用的密钥。客户端首先通过随机数产生一个预主密钥(Pre master secret)通过ClientKeyExchange将用服务端公钥加密的预主密钥发送给服务端。双方将通过预主密钥及Hello阶段交换的服务端及客户端产生的随机数产生相同主密钥(master secret),随后就可以根据主密钥生成加密及计算消息验证码用的密钥参数。
最后,双方在主密钥协商结束后,将分别发送一个change cipherspec消息,这是位于SSLRecordLayer的报文,表示接下来所发送的所有数据都要使用协商的加密算法及密钥进行加密处理。紧接着发送Finished报文,其内容为开始以来所有握手数据的散列码,通过协商的算法及密钥加密。以此检验密钥交换及身份验证处理都已成功完成。至此,握手过程结束,应用层数据交换就可以开始了。
通过OpenSSL进行SSL连接主要需要两个对象,SSL_CTX及SSL对象,前者即SSL上下文,进行SSL连接参数的设定,后者即实际处理SSL连接的对象。建立SSL对象及绑定套接字的语句主要如下:
SSL*ssl_=SSL_new(sslctx_);
SSL_set_fd(ssl_,m_hSocket);
sslctx_即用户建立的SSL上下文,m_hSocket则为需要绑定的套接字连接,经过绑定后套接字的I/O模式阻塞与否将使SSL对象具有相同的I/O模式,后续一系列函数都需要按照非阻塞的模式进行处理。
握手过程主要通过SSL_set_connect_state/SSL_set_accept_state配合SSL_do_handshake完成。前者指定连接角色,后者通过若干次调用完成具体握手工作。
SSL中应用层数据通过SSL RecordLayer协议进行传输,可提供数据压缩及数据保护(数据保密性及数据完整性),使用的压缩算法和数据加密算法及密钥均在握手过程中协商得到。
数据保密性通过加密算法实现,为了保证数据处理速度,SSL使用的是对称加密算法,即给定一个明文一个密钥,加密生成的密文长度与明文一致,加解密使用相同的密钥。比较常用的加密算法有DES、3DES(三重DES加密)、RC4及目前安全性较高的AES(高级加密标准)。经过加密处理后即使密文被中途窃取,如果没有密钥就无法获得实际内容,而SSL的密钥是每个会话通过握手协商的独立的密钥,进一步提高了破译密钥的难度。
数据完整性则是通过消息鉴别码 (message authentication code,又称密码校验和)实现的,消息鉴别码即按照公开的算法及协商的密钥根据输入数据产生一个固定长度的摘要数据。特点是输入数据有微小的变化就会导致摘要数据出现剧烈变化,而且不同输入数据产生同样的摘要数据概率是十分低以致可以忽略不计。基于摘要算法的特点,接收端只要按照同样的算法及密钥对数据重新生成MAC数据检验与接收到的MAC数据是否一致就可以判断消息是否完整,有效防止了数据篡改。同时由于SSL计算MAC时同时使用了应用层数据及每个数据包的序列号,可有效抵御基于数据包序打乱的攻击。
OpenSSL中对SSL连接的数据读写通过SSL_read及SSL_write函数实现,两个接口声明如下:
int SSL_read(SSL*ssl,void*buf,int num);
int SSL_write(SSL*ssl,const void*buf,int num);
在CAsyncSSLSocket中通过SSLRecv及SSLSend封装了应用层数据读写的接口,对用户隐藏了使用OpenSSL库函数的细节。
使用 OpenSSL需要链接到指定库,win32平台下为libeay32.lib及ssleay32.lib,辅助类CUseOpenSSL实现了库的初始化及清理工作及多线程环境初始化。
SSL连接参数设置通过SSL_CTX完成,它指定了SSL连接使用的协议版本,握手过程中的验证模式,及进行密钥交换及身份验证所必要的用户证书、用户私钥、CA证书。一般在程序开始时建立SSL_CTX对象,在程序结束时删除。在CUse-OpenSSL中设计了创建 SSL_CTX对象的静态方法 Create-SSLCTX()。
创建SSL上下文的具体步骤及关键函数如表2所示。
表2 SSL_CTX创建
数字证书是SSL连接中重要组成部分,通过构建自己的CA系统就可以创建内部专用的SSL连接。证书的生成可以通过OpenSSL的实用程序完成[5],这里就不赘述了。
示例通信程序在VS2005环境下实现,通过以下功能进行模块测试:客户端与服务端间同时建立多个SSL连接,每个连接中客户端发送1MB的数据至服务端,服务端接收完毕后返回应答文本。应用层协议处理通过继承自 CAsyncSSLSocket的用户类实现,对应服务端及客户端分别为 CServer及CClient。要建立多个连接用户仅需要构建多个CAsyncSSLSocket类的实例。使用上述模块进行通讯的流程如图4所示。
100Mbps局域网带宽条件下同时建立5个连接的测试结果如图5、图6所示,每个连接使用的SSL协议版本均为SSLv3,数据加密使用AES256位加密算法,摘要算法使用SHA。
图4 通讯流程
图5 测试结果-服务端
图6 测试结果-客户端
表3列出了一些典型带宽及连接数条件下的测试结果,测试环境为WindowsXPsp2、奔腾41.5GHzCPU、1G内存。测试表明上述模块能通过单线程并行处理多个安全网络连接,避免了线程切换及同步开销,具备较高的并行处理性能,随着连接数增加,总的数据传输速率仅略微下降。高带宽条件下,数据的加密及完整性处理一定程度降低了传输速度,但在普通带宽条件下,则是网络带宽构成了性能瓶颈。示例也表明通过用面向对象的方式进行安全网络连接的处理,用户仅需关注具体的事务逻辑,可以有效简化安全通讯系统的构建。
表3 测试结果
本文结合WSAAsyncSelect套接字I/O模型及SSL协议设计并实现了一个异步消息模型驱动的安全通信模块。多层设计、多态方法的应用,将用户的应用层协议设计实现与安全连接基础功能的实现进行了有效地隔离,使通信模块具有了较高的可扩展性。SSL协议的应用,则使用户的通讯数据在数据保密性、数据完整性上都得到了较高的保证。基于消息循环的事件处理模型更是让该模块具备了在一个线程中同时管理多个安全连接的功能,同时也能与使用Windows界面的应用程序进行无缝结合。
该模块主要是面向几十数量级连接数下的通讯应用,对需要进行成千上万连接处理的需要高伸缩性的应用还需通过完成端口等其他I/O模型。目前该安全通信模块已经在多生理参数监护数据汇总系统中得到了应用,取得了较好的效果。
[1]张和君,张跃,周炳坤.远程心电监护软件系统的设计与实现[J].计算机工程与应用,2005,41(12):219-224.
[2]周炳坤,张跃,徐廷松.远程多生理参数监护系统通信协议的研究[J].计算机工程,2008,34(18):102-104.
[3]RFC 5246,Thetransportlayersecurity(TLS)protocolversion1.2[S].
[4]RFC 4366,transport layer security(TLS)extensions[S].
[5]王志海,童新海,沈寒辉.OpenSSL与网络信息安全——基础、结构和指令[M].北京:清华大学出版社,北京交通大学出版社,2007.
[6]孙海民.精通WindowsSockets网络开发:基于VisualC++实现[M].北京:人民邮电出版社,2008.
[7]邓志宏,颜君彪.基于PKI的网络信息安全模型的研究与设计[J].计算机工程与设计,2007,28(2):349-350.
[8]王宇,卢昱.信息网络的通信安全控制[J].计算机工程,2006,32(12):173-175.