欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  科技

基于SPI的协议加固透明传输工具

程序员文章站 2022-08-13 16:17:27
一.背景 随着计算机网络技术的日益发展和普及,远程网络数据传输的安全性显得越来越重要。—般地,运行的应用程序发送的数据包都以明文方式发送,接收方也将直接获得明文数据,但这样发出的数据很容易被截获并进行分析,从而进行网络攻击。只有少数应用会为自己发出数据进行加密。然后再在接收方进行解密操作。随着网络的 ......

一.背景

随着计算机网络技术的日益发展和普及,远程网络数据传输的安全性显得越来越重要。—般地,运行的应用程序发送的数据包都以明文方式发送,接收方也将直接获得明文数据,但这样发出的数据很容易被截获并进行分析,从而进行网络攻击。只有少数应用会为自己发出数据进行加密。然后再在接收方进行解密操作。随着网络的日益普及,网络数据发送的安全也变得很重要。但是,只有较少的应用程序为网络收发数据进行了加密传输,仍然有大量的应用直接采用明文方式通讯。这些应用包括采用了一些特定协议进行通讯,也包含一些特殊用途的客户端程序,比如监控系统和内外网的客户端访问。如欲对这些应用的网络通讯内容进行加固来防止攻击者的监听和攻击,则需要对这一款应用程序进行升级,即增加加密和解密功能。如果一个系统中使用了多种应用结合的方式进行通信,则需要各应用生产商间进行协商。来确保系统中各应用的正常通信。

本工具利用Windows提供的SPI服务,在应用层对应用程序网络通信的数据进行加密,在接收方收到数据前进行解密。整个过程应用程序并未有任何更改。实现了通信数据的透明加密。

二.工具原理

1. Winsock 2 SPI简介

Winsock是为上层应用程序提供的一种标准网络接口。上层应用程序不用关心Winsock实现的细节,它为上层应用程序提供透明的服务。Winsock 2引入的一个新功能就是打破服务提供者的透明,让开发者可以编写自己的服务提供者接口(Service Provider Interface,SPI)程序,即SPI程序。Winsock 2 SPI除了有完成网络传输的传输服务提供者,还提供了友好名字服务的名字空间服务提供者。其中,传输服务提供者能够提供建立通信、传输数据、流量控制和错误控制等服务。Winsock 2提供的服务其结构如图1所示。

基于SPI的协议加固透明传输工具

1 Winsock 2 SPI结构

SPI以动态链接库的形式出现,工作在TCP/IP协议的应用层,为上层API调用提供接口函数。由于SPI工作在TCP/IP协议的应用层,因此对基于应用层的数包SPI都可以截获。

2.传输模型

基于SPI的文件加密传输系统的工作模型如图2所示。在发送方,用户层通信程序发送的网络封包被自定义的SPI程序所截获,SPI程序将数据包的IP地址、端口等信息提取出来,经过规则判断函数判断之后,如果需要加密,则调用加密函数完成加密工作,并在封包中设置加密标志。数据接收方在Windows核心层将接收的网络封包上传给用户层接收程序之前,自定义的SPI程序又将此数据封包截获,规则判断函数首先检查网络封包中的加密标志,若数据包是加密的数据包,则调用解密函数进行解密,最终将解密后的数据包向上传送给用户层的接收程序。

基于SPI的协议加固透明传输工具

2 基于SPI的网络数据加密传输模型

三.功能介绍

1.加密规则和加解密方案

是否对应用层的某一应用程序的网络数据包进行加密传输取决于加密规则。加密规则包括应用程序的名称、IP地址和端口号。

SPI程序会依靠通信双方建立连接时获得的对方IP地址、端口号和本应用程序的名称来决定是否对本次建立的Socket连接进行加密通讯。SPI程序一旦判断本次回话需要加密传输则本次建立的通信双方都会采用加密方式进行通信。

加解密方案则采用128位的AES对称加密作为加密方式。加解密的秘钥分为主密钥和会话秘钥。主密钥由使用者进行设定,会话秘钥则在通信双方建立会话时动态分配。并且,会话秘钥由主密钥生成。

AES加密算法是对称加密算法的一种,其最短秘钥为128比特,就目前的计算机处理速度而言,即使是128位的秘钥,要想通过暴力破解方式获得秘钥是不可能的。因此采用AES对消息进行加密。

本工具对应用层发送的原始数据进行加密传输的过程如图3所示。

基于SPI的协议加固透明传输工具

3 消息加密过程

在加密过程中,SPI程序首先获得待发送的明文消息,然后对其添加时间戳、消息特征和特征码,将原始消息进行重组。然后对时间戳和原始数据部分进行AES加密。最后将重组后的消息发送。接收方应用程序收到消息后,接收方的SPI程序将对收到的消息进行解密并校验,然后将解密出的原始数据转交给接收程序。

2.防止重放攻击

在每次通信双方建立通信连接后,通信双方将进行时间同步,一同开始计时。在建立连接的双方收发数据期间,工具将在重组的消息中添加时间戳,该时间戳也会被加密,加密完成后将被接收方的SPI程序进行解密。从中获得时间戳内容,并判断消息的时间是否在允许的时间误差内,如果超出误差则认为受到了重放攻击。否则,将被判定为合法数据,将数据发送给上层的接收方应用程序。

另外,为了抵御会话长时间通信导致的时间溢出情况,程序将设定定时自动更新会话秘钥的方法来解决这种功能可能带来的潜在问题。

3.日志和权限管理

日志模块将根据程序运行中的运行状况分等级记录运行中的各种状态,比如收发的数据包,建立通信会话的信息,数据包错误,攻击等信息。

权限管理可以给不同设备之间通信加以限制,该功能需根据具体的应用层协议进行定制。该模块可具有以下功能:限制一些功能码的使用、限制指定节点的指定内存地址不可访问等权限限制。

四.安装和环境

1.安装

将工具复制到Windows的指定目录下后,通过安装程序可进行一键安装。

2.环境

工具需安装在Windows XP版本及以上的Windows操作系统之上,对于64位系统则需额外安装64位版本。基于SPI的协议加固透明传输工具

 

  1 int WSPAPI WSPRecvFrom(
  2     _In_    SOCKET                             s,
  3     _Inout_ LPWSABUF                           lpBuffers,
  4     _In_    DWORD                              dwBufferCount,
  5     _Out_   LPDWORD                            lpNumberOfBytesRecvd,
  6     _Inout_ LPDWORD                            lpFlags,
  7     _Out_   struct sockaddr                    *lpFrom,
  8     _Inout_ LPINT                              lpFromlen,
  9     _In_    LPWSAOVERLAPPED                    lpOverlapped,
 10     _In_    LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
 11     _In_    LPWSATHREADID                      lpThreadId,
 12     _Inout_ LPINT                              lpErrno
 13 )
 14 {
 15     DWORD reinforince = SessionUdp(s, lpFrom);
 16     int ret = 0;
 17     *lpErrno = 0;
 18     LPWSABUF lpBuffersRecvTmp = NULL;
 19     if (reinforince != 0)
 20     {
 21         lpBuffersRecvTmp = (LPWSABUF)HeapAlloc(m_hHeapOverlappedSessionRecv, HEAP_ZERO_MEMORY, sizeof(WSABUF)*dwBufferCount);
 22         for (DWORD i = 0; i < dwBufferCount; i++)
 23         {
 24             lpBuffersRecvTmp[i].buf = (char*)HeapAlloc(m_hHeapOverlappedSessionRecv, HEAP_ZERO_MEMORY, sizeof(char)*(lpBuffers[i].len + EXTENDDATALENGTH));
 25             lpBuffersRecvTmp[i].len = lpBuffers[i].len + EXTENDDATALENGTH;
 26         }
 27         if (lpCompletionRoutine != NULL)
 28             ret = m_NextProcTable.lpWSPRecvFrom(s, lpBuffersRecvTmp, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpFrom, lpFromlen, lpOverlapped, CompletionRoutineRecv, lpThreadId, lpErrno);
 29         else
 30             ret = m_NextProcTable.lpWSPRecvFrom(s, lpBuffersRecvTmp, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpFrom, lpFromlen, lpOverlapped, lpCompletionRoutine, lpThreadId, lpErrno);
 31     }
 32     else
 33     {
 34         if (lpCompletionRoutine != NULL)
 35             ret = m_NextProcTable.lpWSPRecvFrom(s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpFrom, lpFromlen, lpOverlapped, CompletionRoutineRecv, lpThreadId, lpErrno);
 36         else
 37             ret = m_NextProcTable.lpWSPRecvFrom(s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpFrom, lpFromlen, lpOverlapped, lpCompletionRoutine, lpThreadId, lpErrno);
 38     }
 39 
 40     if (*lpErrno == WSA_IO_PENDING && ret == SOCKET_ERROR)//异步模式
 41     {
 42         POVERLAPPEDSESSIONRECV pOverlappedSession = (POVERLAPPEDSESSIONRECV)HeapAlloc(m_hHeapOverlappedSessionRecv, HEAP_ZERO_MEMORY, sizeof(OVERLAPPEDSESSIONRECV));
 43         pOverlappedSession->dwBufferCountRecv = dwBufferCount;
 44         pOverlappedSession->lpBuffersRecvBack = lpBuffers;
 45         pOverlappedSession->lpBuffersRecvTmp = lpBuffersRecvTmp;
 46         pOverlappedSession->lpCompletionRoutineRecv = lpCompletionRoutine;
 47         pOverlappedSession->s = s;
 48         pOverlappedSession->dIsReinforce = reinforince;
 49         EnterCriticalSection(&m_csOverlappedSessionRecv);
 50         {
 51             if (m_OverlappedSessionRecv.find(lpOverlapped) != m_OverlappedSessionRecv.end())//删除之前的记录,如果存在的话
 52             {
 53                 if (m_OverlappedSessionRecv[lpOverlapped]->dIsReinforce != 0)
 54                 {
 55                     for (DWORD i = 0; i < m_OverlappedSessionRecv[lpOverlapped]->dwBufferCountRecv; i++)
 56                     {
 57                         HeapFree(m_hHeapOverlappedSessionRecv, 0, m_OverlappedSessionRecv[lpOverlapped]->lpBuffersRecvTmp[i].buf);
 58                     }
 59                     HeapFree(m_hHeapOverlappedSessionRecv, 0, m_OverlappedSessionRecv[lpOverlapped]->lpBuffersRecvTmp);
 60                 }
 61                 HeapFree(m_hHeapOverlappedSessionRecv, 0, m_OverlappedSessionRecv[lpOverlapped]);
 62                 m_OverlappedSessionRecv.erase(lpOverlapped);
 63             }
 64             m_OverlappedSessionRecv.emplace(lpOverlapped, pOverlappedSession);
 65         }
 66         LeaveCriticalSection(&m_csOverlappedSessionRecv);
 67     }
 68     else//阻塞形式接收、重叠当时接收但立即完成 或者 接收出现错误
 69     {
 70         if (reinforince != 0)
 71         {
 72             if (ret == 0)
 73             {
 74                 //加固的 记录传输的字节数
 75                 EnterCriticalSection(&m_csSession);
 76                 {
 77                     if (m_Session.find(s) != m_Session.end())
 78                     {
 79                         m_Session[s]->ulRecvData += *lpNumberOfBytesRecvd;
 80                     }
 81                 }
 82                 LeaveCriticalSection(&m_csSession);
 83             }
 84             //释放多个缓冲区
 85             ReinforceRecv(s, lpBuffersRecvTmp, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd);
 86             for (DWORD i = 0; i < dwBufferCount; i++)
 87             {
 88                 HeapFree(m_hHeapOverlappedSessionRecv, 0, lpBuffersRecvTmp[i].buf);
 89             }
 90             HeapFree(m_hHeapOverlappedSessionRecv, 0, lpBuffersRecvTmp);
 91         }
 92         else if (ret == 0)//不加固,而且未出错
 93         {
 94             //记录日志
 95             EnterCriticalSection(&m_csSession);
 96             {
 97                 m_Session[s]->ulRecvData += *lpNumberOfBytesRecvd;
 98                 DWORD transfer = *lpNumberOfBytesRecvd;
 99                 DWORD len = 0;
100                 //EnterCriticalSection(&m_csLocalGlob);
101                 {
102                     if (m_LocalGlobVar.allRecv != 0)
103                     {
104                         for (int i = 0; i < dwBufferCount; i++)
105                         {
106                             len = lpBuffers[i].len;
107                             AddLogMsg(LOG_COMMENT, "RecvFrom data", m_Session[s], 0, TRUE, lpBuffers[i].buf, transfer > len ? len : transfer);
108                             if (transfer > len)
109                                 transfer -= len;
110                             else
111                                 break;
112                         }
113                     }
114                 }
115                 //LeaveCriticalSection(&m_csLocalGlob);
116             }
117             LeaveCriticalSection(&m_csSession);
118         }
119     }
120     return ret;
121 }

 

五.优势

本工具具有以下优势:

  1. 安装简单:一键安装。
  2. 管理简单:只需通过加密管理程序即可进行设置主密钥、IP加密规则、端口加密规则、进程加密规则。
  3. 加密效率高,强度高:采用AES加密算法,暴力破解几乎不可能。
  4. 透明加密传输网络数据:SPI工作在应用层的下层,与应用程序通信丝毫不会影响应用程序的工作。
  5. 解决工作系统的整体加密传输问题:在一个采用了多种软件相协调工作的系统而言,要想加密网路数据,则需要对每一个软件进行升级,而使用本工具,则无需对每一款软件升级,即可完成整个系统的数据加密传输升级。