ESFramework 开发手册(10) -- 安全机制

       在分布式通信系统中,安全无疑是非常重要的。

       ESFramework/ESPlus作为应用层的开发框架,在这里我们只讨论应用层的安全问题,因为如果黑客是在网络层或链路层进行攻击,位于应用层的系统几乎是无能为力的。从应用层来说,安全的重要性主要体现在以下几个方面:

(1) 防止恶意用户使用格式不正确的消息来试探服务端。

(2) 防止通信的消息被恶意用户截获,或者,即使被恶意用户截获,也无法破解其内容。

(3) 防止恶意用户在未成功登录前,就向服务器发送格式正确的伪装消息。

(4) 防止恶意用户使用巨大数量的空连接来消耗服务器的资源。

       ESFramework内置了一些安全机制,以对上述的安全性提供一些保障,下面我们一一说明。 

一. 消息格式验证

       ESFramework定义了通信消息的总体格式,ESPlus则定义了消息的详细格式。

       当网络引擎(无论是服务端的还是客户端的)从网络上接收到一批二进制数据时,会尝试去解析它。如果解析时发现,这批二进制数据的格式不是我们定义好的消息的格式时,将会认为其是非法消息。此时,网络引擎将会丢弃非法数据,并关闭对应的连接(如果引擎是基于TCP协议的),然后再触发INetEngine接口的InvalidMsgReceived事件。

     ///<summary>
    /// 当接收到不完整或无法解析的数据时触发该事件
    ///</summary>
    event CbGeneric<UserAddress, MessageInvalidType> InvalidMsgReceived;

    public enum MessageInvalidType
    {
        ///<summary>
        /// 正常消息。
        ///</summary>
        Valid = 0, 

        ///<summary>
        /// 消息尺寸溢出。
        ///</summary>
        MessageSizeOverflow,

        ///<summary>
        /// 无效的消息头
        ///</summary>
        InvalidHeader,

        ///<summary>
        /// 无效的标识符
        ///</summary>
        InvalidToken,

        ///<summary>
        /// 数据包长度不够
        ///</summary>
        DataLacked,

        ///<summary>
        /// 无效的客户端类型
        ///</summary>
        InvalidClientType
    }

       事件的参数UserAddress说明了非法消息来源于哪个用户地址;而MessageInvalidType参数则说明了非法消息的类型,从该枚举可以看出,网络引擎收到的数据无法解析的原因有几种:消息尺寸超过规定的大小,消息头无效、消息的标识符无效等。

二. 消息加密

       对于一些关键的信息,是绝对不允许以明文的形式在网络上进行传送的。所以,消息在发送之前,必须进行加密。

       在使用ESPlus提供的Rapid引擎中,内部组装骨架流程时,是没有使用加密组件的,但是,我们仍然可以在发送自定义信息时,保证信息的安全。还记得我们是使用ICustomizeOutter发送自定义信息的,以Send方法为例:

   ///<summary>
   /// 向服务器发送信息。
   ///</summary>
   ///<param name="informationType">自定义信息类型</param>
   ///<param name="info">信息</param>
   void Send(int informationType, byte[] info);

      在调用Send方法之前,我们可以先将要发送的内容info进行加密,然后再发送加密后的结果。

      而在接收方,会调用ICustomizeHandler的HandleInformation方法来处理接收到的信息:

  ///<summary>
  /// 处理来自客户端的自定义信息。
  ///</summary>
  ///<param name="sourceUserID">发送该信息的用户ID</param>
  ///<param name="informationType">自定义信息类型</param>
  ///<param name="info">信息</param>
  void HandleInformation(string sourceUserID, int informationType, byte[] info);

       在实现HandleInformation方法时,我们可以先解密info,然后再进行正常的业务处理。

       在发送或接收自定义信息时,手动加解密信息,都要注意一点,那就是加解密都是要消耗CPU和内存资源的,对于那些高频通信的消息来说,这个开销是绝不可忽视的。所以,我们应该尽可能的只加密那些极其重要的消息/信息(根据nfomationType来进行区分),而不是将所有的消息/信息一视同仁。

三. 验证未登录的消息

       有的恶意用户,在破解了消息的格式之后,会尝试在不登录的情况下,向服务器发送其他类型的请求消息。ESFramework支持在服务端对每个连接上收到的消息进行验证,如果验证通不过,则将关闭对应的连接。     

       ESPlus提供的Rapid引擎,其内部已经保证,恶意用户在在未登录的情况下无法进行其它类型的业务请求。

四. 绑定连接

       当Logon消息中的帐号密码通过服务端的验证之后,服务端会将该帐号与对应的TCP连接绑定起来,构成一个完整的Session。如果该连接上接收到的后续消息中,只要发现消息头中的UserID与该TCP连接绑定的帐号不一致,则认为该消息为非法消息,此时,服务端网络引擎将会关闭对应的TCP连接。如此,可以防止用一个帐号登录成功后,再用另一个帐号来请求服务。

五. 空连接

       到这里,我们已经解决了本章开始提出的前三个问题,这就保证了恶意用户无法向服务器发送恶意的消息了。但是,恶意用户在应用层还可以做一件事情,就是消耗服务端的TCP连接。对于每个已成功建立的TCP连接,服务端都要为其分配一定的资源并对其进行管理。如果恶意的用户和服务器之间建立很多空闲的连接,对服务器资源的消耗也是不可忽视的。

       ESFramework支持一个特性:某个TCP连接连上后,如果在指定的时间内,服务端网络引擎都接收不到来自该连接的任何数据,则将关闭该连接。

       我们可以指定这个时间为一个较短的时间(如3s),来减轻空连接的影响。之所以说是“减轻”,而不是“消除”,是因为在应用层系统中,无法完全规避这个问题,就按照3秒钟的超时来说,你服务端关闭连接的速度一定赶不上恶意用户建立连接的速度。

       这种情况在应用层来处理就非常的吃力。解决这个问题的更好办法,应该是在防火墙上做相关的策略设定,比如屏蔽掉恶意用户的IP地址,过滤由该地址发出TCP握手请求的Syn包,等等。

 

下一篇:ESFramework 开发手册(11) -- 服务端信息处理模型

上一篇:ESFramework 开发手册(09) -- ACK机制、同步调用、回复异步调用

-----------------------------------------------------------------------------------------------------------------------------------------------   

下载免费版本的ESFramework 以及 demo源码  

阅读 更多ESFramework开发手册系列文章

Q Q:168757008

官网:www.oraycn.com

导航

首页

官方网站

立即咨询 

站内搜索

ESFramework 通信框架

详细说明

SDK下载

ESFramework FAQ

版本变更记录

OMCS 语音视频框架

详细说明

SDK下载

OMCS FAQ

版本变更记录

OrayTalk 企业即时通讯系统

详细说明

客户端下载

傲瑞实用组件

SDK下载

NPush 消息推送组件

StriveEngine 轻量级的通信引擎

MFile 语音视频录制组件

MCapture 语音视频采集组件

MPlayer 语音视频播放组件

OAUS 自动升级系统

傲瑞组件 FAQ

授权

授权流程

产品授权说明

产品选购指南

授权SDK使用说明

其它

SDK使用技巧

联系我们

电话:027-87638960

Q Q:168757008

邮件:master@oraycn.com