祁磊+令晓明
摘要:在当今移动互联网环境下,为了保证数据文件在网络中传输的安全性,加密传输就显得尤为重要。具体实现了一种在嵌入式Linux系统环境下加入SSL协议,并对将要传输的数据文件利用一定的加密算法进行加密,能够较好的解决数据文件在网络环境下传输的安全性问题。同时在服务器端利用线程池技术解决了多用户多进程的问题,避免了服务器端不断创建和销毁线程所带来的资源浪费和时间开销。
关键字:Linux;文件安全传输;SSL;线程池
中图分类号:TP311 文献标识码:A 文章编号:1009-3044(2015)10-0043-04
SSL协议是在繁多的网络协议中应用比较广泛,它可以确保TCP/IP上所有协议收发双方端到端的信息安全传输,并且运用了对称加密技术对数据文件进行加密,而运用非对称加密技术对用户身份进行验证以及交换密钥。SSL协议不但可以弥补TCP/IP本身的一些缺陷,同时还可以很好的确保客户/服务器双方通信时数据的保密性、完整性,并且能 够保证双方的身份认证。在一个系统或是一个应用程序中,往往会有多个传输任务需要执行,每个任务都对应处理器一个线程,在执行多个任务时势必要不停的创建线程销毁线程,这无疑增加了处理时间,并且对传输的安全性带来一定的隐患。因此,在系统中引入了线程池技术,就可以解决该隐患。线程池是在执行任务之前就创建好一些线程,并使这些线程处于等待状态,当有新任务到来时,应用程序会激活线程池中的某一线程,当任务执行完毕后会重新变为等待状态放回线程池,等待下一次新任务的到来。
1 文件安全传输的体系结构模型
文件传输是由硬软件两部分实现的,硬件是以嵌入式平台来支撑,软件部分是以Linux网络编程加上SSL协议[1]、线程池技术以及文件安全传输的服务器/客户端程序。主要是实现不同机器上服务器与客户端之间的文件互传,服务器监听客户机的请求,并且做出相应的响应。该系统主要实现的具体要求如下:①服务器和客户端都支持用户账号和密码的验证;②客户端可以浏览本地和服务器端的文件列表;③服务器端可以实现多用户同时连接,必须是多线程的;④服务器端的系统日志可以记录文件操作的事件日志;⑤在上传和下载文件之前要先检查磁盘的大小,以确保上传和下载可以正常执行。系统结构模型如图1所示:
图1 系统结构模型
2 文件加密
2.1 服务器端的文件SSL加密
文件安全传输的主要功能由SSL协议加密来实现,SSL协议完成的主要流程是:先对SSL协议相应库的初始化,然后载入相应的加密算法模块。应用程序再回调加密算法模块即可对数据进行加密,然后载入所有SSL错误信息,该错误信息对应于在处理过程中可能会产生的所有错误。然后创建本次会话连接中所用到的所有协议,以便用于通讯双方进行通讯的连接。接下来就是申请SSL回话的环境CTX,载入数据证书,载入用户私钥,并检查用户私钥是否正确。创建套接字并开启socket监听,等待客户端的连接请求。再基于CTX产生一个新的SSL,并将连接用户的socket套接口加入SSL,建立SSL连接完成SSL握手,接收数据并做相关处理。最后关闭SSL并释放SSL、关闭socket、释放CTX等操作。服务器端的SSL加密过程如图2所示:
图2 服务器端的SSL加密过程
2.2 客户端的SSL加密
客户端文件的SSL加密过程与服务器端基本一致,主要区别是客户端不用处理并发任务,不用对端口进行监听等操作。具体的SSL加密流程如下:先对相应的SSL库进行初始化,再载入所有的SSL算法,用于在对数据处理过程中对数据的加密。然后载入所有SSL错误信息,以应付在处理过程中可能出现的各种错误。然后在创建本次会话连接所使用的协议,用于通讯双发进行通讯连接。接下来是申请会话环境CTX,创建socket用于TCP通讯,建立SSL连接完成SSL握手,对数据进行接收并做相关的处理。最后关闭连接以及释放相关的资源等操作。
2.3 SSL协议
SSL是一种协议套件,它是由握手协议、记录协议、更改密码规范协议以及警告协议,四部分协议组成。SSL协议在TCP/IP协议站中的位置以及与这四部分的关系如图3所示:
图3 SSL协议关系示意图
应用SSL协议建立的通道是透明的,服务器端与客户端之间的数据经过加密,不改变传输数据的内容。这样的透明性是基于TCP/IP的协议,然后稍加修改就可以运行在SSL之上,就可以打造一个安全通道[2]。SSL是位于应用层和传输层之间的,该协议一般是由握手协议和记录协议两部分组成,前者一般用于通信双方之间会话时的密码参数协商,记录协议一般用于数据传输前的身份验证、算法协商、交换密钥。一个基本的SSL会话应当包括握手、下发证书、密钥交换和算法协商四个阶段[5]。如图4所示:
图4 SSL会话基本步骤
3 加密模块的代码实现
3.1 传输协议的设置
客户端与服务器端进行命令交互的时候,通讯双方需要遵循一定的标准,只有这样双方才能够准确的知道来自对方的报文意义。
本系统的传输协议结构如下[3]:
在双方通讯的过程中,当要发送数据时,要调用打包函数将要发送的数据封装成协议包,在要接收数据的时候,要调用解包函数解析出有效的数据。这两个函数分别如下:
⑴ 打包函数
struct FilePackage pack (char tCmd, char* tBuf, char* tFilename, int tFilesize, int tAck,int count,char *uname)
⑵ 解包函数
struct FilePackage unpack (SSL * ,struct FilePackage )
客户端能否连接上服务器,还取决于服务器上连接的客户端数量,因此,还要对服务器的最大连接数加以设置。调用函数InitMaxClientNum()来对客户端最大连接数进行初始化。
3.2 安全链接的建立
在安全链接建立之前,我们需要提前加载可以信任的证书库。在此过程中需要进程握手协商,服务器首先要向客户机端发送一个证书,客户机端根据自己提前加载的可信任的证书库来验证服务器端的证书是否有效。并且在这个过程中通讯信双发之间需要传递密码参数从而建立安全的连接。
1) 设置安全链接
首先通过调用SSL_CTX_new()函数来创建一个类型为SSL_CTX型的指针ctx,并用该指针来保存一些与SSL相关的参数。
SSL_library_init(); //初始化SSL库
OpenSSL_add_all_algorithms(); // 将所有的SSL算法载入
SSL_load_error_strings(); // 载入错误消息
ctx = SSL_CTX_new(); // 创建SSL_CTX型的指针
2)加载可信任的证书库
调用函数SSL_CTX_use_certificate_file()来对用户的数字证书进行加载,数字证书加载完成之后,还需要调用函数SSL_CTX_use_PrivateKey_file()来对用户私钥进行加载。
SSL_CTX_use_certificate_file(ctx,temp=strcat(pwd,"/cacert.pem"),SSL_FILETYPE_PEM); //载入数字证书
SSL_CTX_use_PrivateKey_file(),SSL_FILETYPE_PEM); //载入用户私钥
3)创建连接
调用函数SSL_new()来创建一个新的ssl,然后需要将用户创建的socket对象链接到ssl,接着需要调用SSL_accept()函数等待客户端链接请求,若是没有客户端请求,程序会一直阻塞在这里,一直等到有客户端的请求到来。
ssl = SSL_new(ctx); //创建一个新的ssl
SSL_set_fd(ssl, new_fd);
SSL_accept(ssl); //建立ssl链接
3.3 客户端与服务器端进行通信
在客户端常见完socket套接字之后,调用OpenSSL API中的SSL_set_fd()函数来设置socket文件描述符来作为ssl的I/O设备,然后在调用SSL_connect()函数来请求连接服务器。通过调用两个函数,SSL_read()和SSL_write()来完成对SSL对象的数据包接收与发送操作。
SSL_set_fd (ssl, sockclient); //设置socket文件描述符
SSL_connect (ssl); //建立ssl链接
SSL_read (ssl,data,sizeof(struct FilePackage); //发送数据
SSL_write (ssl,&data,sizeof(struct FilePackage); //接收数据
4 线程池的设计
一般情况下服务器端所要承担的任务远比想象中要复杂的多,就单单拿数据文件传输来说,它可能要同时处理多个客户端的请求,服务器端要不断的创建和销毁客户端的请求进程。服务器端处理多用户关系如图5所示:
相对于进程而言,创建和销毁线程已经是很轻量级的任务了。但是如果服务器系统来频繁的执行线程的创建、销毁,对于服务器来说这也是一笔很大的资源浪费。那么线程池技术的使用就可以很大程度上减少这样的资源消耗。
调用函数CreateThreadPool()来创建线程池,线程池会把一些已经创建好的线程集中在一起,这些线程都处于等待状态。当有新任务到达时,应用程序就会去激活线程池中的某个线程。当该线程执行完成后,再去调用MoveToIdle()函数,该线程就又恢复等待状态,重新放回到回线程池中,等待下一个新任务的到达。当线程池中的每一个线程都处于忙碌状态的时候,会将其他的新任务放入等待队列中,直到线程池中有线程空闲下来,然后去执行队列中的新任务。线程池的工作过程如图6所示:
为了更进一步具体的说明,利用了线程池以后可以大大的提高资源的利用率,节约系统资源。运行了一下线程池代码thread.c加以解释。有运行结果可以看出,线程池中有3个线程0xb6e2cb70、0xb782db70、0xb642bb70被10任务重复利用。运行结果如图7所示:
5 结果测试
以Linux虚拟机作为服务器端,输入管理员的ID和密码,就可以成功登陆并进入服务器端的控制界面(如图8),并按照相应的提示完成对服务器端的操作。
输入正确的用户名和密码即可登录客户端(如图9),客户端可以显示本地目录文件,并且可以通过命令,对文件进行上传、下载已经退出客户端操作。
6 总结与分析
本文实现了在Linux环境下基于SSL协议的数据文件安全传输系统的基本框架,并且在服务器端利于了线程池技术,减小了服务器不停的创建和撤销应用线程所带来的资源浪费和时间开销[3]。但是,由于个人能力欠缺以及时间关系,该系统还存在很多的问题和不足。例如:所设计的Linux系统环境,只是在Windows下的虚拟机模拟实现,并没有实现远程网络上的传输,以及在集群服务器下的多线程处理能力的验证等,这些问题都有待进一步的研究和验证。
参考文献:
[1] 令晓静. SSL安全传输协议在网络通信中的应用研究[D].西安:西安电子科技大学,2006.
[2] 孟彦, 侯整风. 基于SSL/TLS的安全文件传输系统[J]. 计算机技术与发展, 2006,16(5):118-120
[3] 汪成林. Linux环境下基于SSL的安全文件传输系统的研究[D]. 杭州: 浙江工业大学, 2012
[4] 支超. 基于SSL协议的加密文件传输系统设计[D]. 呼和浩特:内蒙古大学,2013.4
[5] 刘明波, 候孝民. 网络化数据采集与处理系统设计[M].北京:电子工业出版社,2008.
[6] 徐立松, 郭晓金. 嵌入式Linux中安全文件传输系统的设计与实现[J]. 数字通信, 2009(12):78-82
[7] 曹江华. Linux服务器安全策略详解[M].北京:电子工业出版社, 2009.
[8] 张兴. 多线程编程技术原理[M].北京:电子工业出版社,2008.
[9] 王瑛. 基于SSL加密协议的网络终端安全研究[J].长春理工大学校报,2010(9):45-46.
[10] Mark Stamp. Information Security: Principles and Practice [M]. Wiley, 2011.