作者简介:练良伟,中通信息安全团队软件开发工程师,负责中通内部安全通讯产品的开发工作,专注于服务端开发相关的技术研究。
1.项目背景
中通快递目前拥有几万个快递网点、代理点和承包区,这些网点分布在全球各地。每天网点与网点、网点与集团总部之间都需要传输大量的信息,信息类型包括文本、图片、文件、语音等。在研发内部安全通讯软件之前,主要使用QQ、微信、钉钉等公众即时通讯类软件传输信息,导致公司的私密信息直接暴露在公共网络以及私人设备上,无法进行有效管控,存在严重的信息泄露安全风险。因此我们迫切需要一款有安全保障的即时通讯软件作为公司内部的信息交流通道。
2.需要解决的问题
在开始软件产品设计之前,我们要先调研用户的实际需求,并从中总结出产品在设计过程中需要解决的主要问题,下面是中通快递使用即时通讯软件交流信息的几个典型应用场景。
- 中通内部网点与网点、网点与总部之间每天都会在网络上传输包含银行账户、个人身份等私密资料的信息,万一泄露有可能给用户造成一定的损失。
- 快递业作为服务行业,客户与网点、网点与网点之间每天都会产生需要总部仲裁、申诉才能解决的争议,这时总部工作人员会要求网点提供文字、图片等相关证明材料,这些消息如果在传输途中丢失,将会导致后续的申诉、仲裁流程无法进行。
- 中通快递每天都会产生大量的订单、工单,订单、工单都是具有时效性的,网点希望能够通过即时通讯系统定时推送提醒消息以便能及时处理订单和工单。因此有可能会造成较短时间内需要转发大量消息的场景,这就要求即时通讯服务具有高可用性,能够在面对流量突增的情况下保持系统的稳定运行。
综合上面的几个应用场景,我们可以很容易的总结出内部安全即时通讯需要解决的三个主要问题
- 如何保护消息内容的机密性,即消息内容不被泄漏
- 如何保障消息的完整性,即接收方与发送方的消息内容是一致的,中途没有丢失或者被非法篡改
- 如何提高系统的可用性,即保障即时通讯服务随时可用,能够满足24小时不间断稳定运行的要求
3.设计方案
针对上面这三个问题,谈谈我们具体的设计方案,图1是我们的系统架构图,结构分层比较简洁,不作赘述。
图1. 系统架构图
3.1 消息机密性设计
一般在网络中传输的数据,都可以认为是存在潜在的安全风险的。用一句话来概括就是:“任何在网络中传输的明文数据都存在安全性威胁”,目前通常采用对数据加密的手段防止信息内容泄漏。
3.1.1 选择合适的算法
加密算法根据密钥的的对称性分为对称加密和非对称加密两大类:
非对称加密的密钥分为公钥和私钥,公钥用于加密,私钥用于解密。常用的有RSA加密算法,非对称加密速度较慢,适合小数据量的加解密或作为固定密钥的加密算法。对称式加密算法加密和解密使用相同的密钥,常用的有以下几种- DES(Data Encryption Standard):数据加密标准,速度较快,适用于加密大量数据的场合。
- AES(Advanced Encryption Standard):高级加密标准,是下一代的加密算法标准,速度快,安全级别高。
- BLOWFISH:每次加解密8字节数据,加密和解密的过程基本上由ADD和XOR指令运算组成,速度最快。
使用哪种加密算法需要综合考虑使用场景、安全需求等方面的因素。在我们的系统中,每天需要传输的数据包数量众多但单个数据包的长度较短,为了提高即时通讯服务端的消息处理能力,加解密速度是我们选择算法时重要的考量指标,因此在我们的消息加解密中选用了BLOWFISH算法。
BLOWFISH算法由于使用固定密钥加解密,在实际应用中还存在以下两个安全隐患:- 如果密钥以硬编码的方式保存在客户端,那么一旦客户端被逆向破解就可能会造成密钥泄漏
- 如果使用动态密钥,发送方需要将密钥一起发送给接收方,接收方才能正常解密,传输过程中存在被非法拦截和破解的风险
为了解决上面的两个安全问题,我们采用了一人一密+本地生成动态密钥的组合加密方式。一人一密+本地生成动态密钥避免了在客户端硬编码密钥的风险,同时本地生成动态密钥也使密钥不再需要在网络上传输,保护了密钥的安全。
3.1.2 一人一密+本地生成动态密钥的加密方案
客户端与服务端的TCP会话成功建立后,通讯双方分别根据预先约定的算法生成初始化密钥。每个密钥只能够使用一次,下一个数据包的加解密必须使用新的密钥。新的密钥生成规则:包的序列号+消息的MD5散列码+上一次密钥。服务端接收到数据包后,首先使用本地密钥进行解密,然后使用与客户端相同的规则生成下一次加解密的密钥。
图2. 消息加解密流程
3.2 消息完整性设计
消息完整性包含两方面的内容,一是指信息安全方面的完整性,指消息内容在传输过程没有被非法篡改及伪造;二是消息传输的可靠性,即保证用户发送的消息能够完整到达接收方,在传输过程中不会丢失消息。
下面将详细描述我们是如何实现消息完整性需求的
3.2.1. 使用数据签名保护消息完整性
使用一人一密+本地生成动态密钥的加解密方案解决了消息机密性的问题,但是我们还不能防止包在传输过程中被非法篡改及伪造。MD5的一个典型应用场景是对一段Message(字节串)产生fingerprint(指纹),用来防止消息内容被“篡改、伪造”,从而达到保护消息完整性的目的。接下来简单介绍下我们的数据签名流程。
首先需要计算出消息内容的MD5散列码,然后使用RSA加密算法生成签名信息。最后将签名信息与消息内容一起发送到服务端,服务端使用解密后的消息内容重新生成签名信息,如果消息在传输途中被篡改,我们就会发现新生成的签名信息与接收到的签名信息不一致,服务端将立即断开与客户端的连接,并将异常行为上报到中通安全监控系统。
3.2.2. 使用确认、重传机制保障消息传输可靠性
由于网络环境复杂,七层网络模型里面的任何一层出问题都有可能导致数据包丢失。例如在我们的消息从客户端A传输到客户端B的场景中,下面的几个原因都会导致在传输过程中丢包。
- 即时通讯服务器崩溃,包未成功转发
- 网络抖动,包被网络设备丢弃
- 客户端B崩溃,包未被成功接收
结论是悲观的:客户端B是否有收到消息,客户端A完全不可控,那我们要如何来保障消息的可靠性呢?我们一起来看看关于网络传输协议的描述:UDP是一种不可靠的传输层协议,TCP是一种可靠的传输层协议,TCP是如何做到可靠的?答案是:使用超时、重传、确认三种机制。既然这种方案已经被证明是切实可行的,那我们为什么不借鉴使用呢?
中通内部即时通讯软件传输协议使用的是TCP协议,既然TCP协议是可靠的,那我们只需要在应用层也实现类似传输层的确认、重传、去重机制,就可以保障消息的可靠投递。
应用层的确认机制,即:要想让客户端A能够确认客户端B成功收到了消息,必须让客户端B在收到消息后回复一个确认报文。这里还有一个场景,就是当客户端B不在线的情况下,这时服务端将在成功持久化离线消息后,伪造一份确认报文发送给客户端A(之后的可靠性由离线消息接收机制保障)。
图3. 待确认报文的消息发送流程
使用确认机制就能保证消息可靠性了吗?事实是还不够,我们还需要考虑因服务端奔溃、网络抖动、客户端奔溃而导致无法收到确认报文等场景。
这个时候就需要使用到下面的超时重传机制了。
客户端A发出了消息报文,在一个设定的超时等待时间内,如果没有收到来自客户端B的确认报文,客户端A会尝试将消息重发。如果客户端A在这个时间段同时发出了很多消息,将会导致无法区分哪条消息需要重发,因此客户端A需要在本地维护一个“等待确认队列”,并配合timer超时机制来记录哪些消息没有收到确认报文,以便定时重发。一旦收到了确认报文,说明客户端B成功收到了消息,这时可以将对应的消息从“等待确认队列”中移除。如果一个消息超时重发次数超过3次,则在客户端会话窗口显示发送超时等提示信息。
由于超时重传机制有可能导致客户端收到两条重复的消息,这个时候我们的去重机制就该上场了。我们的解决方案是,由发送方负责生成一个消息去重的消息ID(必须保证唯一性),保存在“等待确认队列”里,同一条消息使用相同的消息ID来重传,以便客户端去重从而不会影响用户体验。
以上考虑的都是客户端A与客户端B同时在线的情况下,如果客户端B不在线,那么服务端会将消息存储在离线消息队列中。客户端B成功上线后,会首先向服务端拉取所有未接收的离线消息,然后向服务端回复成功接收的确认报文,服务端只有收到每条消息的确认报文后,才会将离线消息从服务端移除。
3.3 高可用设计
作为面向互联网应用的即时通讯服务,在实际的运行中面对的环境是非常复杂的,业务上的流量突增、依赖服务的不稳定、物理资源损坏等方方面面都会对系统的运行带来大大小小的冲击,只有具备高可用的服务才能在面对这些冲击时还能不间断稳定运行。
下面我们将通过对服务的扩展能力、故障隔离、监控报警等三个方面的优化设计来提升系统的可用性。
3.3.1 分层设计的可水平伸缩的架构
良好的扩展能力能让系统在面对突发事故时只需通过增加部署节点的方式就能解决问题,而将系统合理分层能使各层之间的服务互不依赖,让各层只专注自己职责,可以提高服务的可扩展性和可维护性。
我们将内网通讯服务分为请求入口层、应用层、缓存层、数据库层四个层级(图2),每个层级的服务都要求能够支持多节点部署。
图4. 服务端分层架构
请求入口层
请求入口层负责客户端所有连接的接入功能,对应这个层级的是系统的负载均衡服务。一个负载均衡服务后面可以对应多个应用服务,负载均衡服务会根据负载均衡算法选择一个应用服务分配给客户端。目前常用的负载均衡算法主要有以下几种:
- 轮询: 将请求顺序循环地发到每个服务器
- 最少连接数:根据后端服务器当前的连接情况,动态的选取其中当前积压连接数最少的一台服务器来处理当前请求,尽可能的提高后台服务器利用率,将负载合理的分流到每一台服务器
- 哈希: 将客户端的源地址,端口进行哈希运算,根据运算的结果转发给一台服务器进行处理
- 随机:通过系统随机函数,根据后台服务器列表的大小值来随机选取其中一台进行访问
具体采用哪种算法要根据应用的实际场景来确定,例如在我们的应用场景中,客户端与服务端之间使用的是TCP长连接,一旦连接成功建立后,双方之间的数据传输都将在这个TCP通道里面完成。所以服务端连接数可以比较直观的反应当前机器的负载压力,因此最小连接数是最适用于我们系统的负载均衡算法。
应用层
应用层包含即时通讯服务的所有业务处理逻辑,是整个系统的核心服务,同时也是系统中最容易出现故障的部分。在本层中我们主要通过对服务扩展能力和故障隔离能力的设计来实现服务的高可用。
实现服务良好扩展性的一个重要原则就是无状态化设计。一个有状态的服务需要在内部存储当前用户会话及登录状态等上下文信息,在新加节点后需要面临数据同步问题,无法做到即插即用。而无状态化设计由于将上下文信息单独存储在分布式缓存(例如Redis)中,更有利于实现节点的水平扩展。
既然故障是不可避免的,那么我们需要考虑的就是当故障发生时,如何将产生的影响降低到最小范围。我们的做法是将一个大的服务按业务逻辑拆分成多个只具有单一功能的子服务,每个子服务都有相应的处理逻辑和轻量通讯机制,并运行在自己的独立进程之内,避免单个业务功能的Bug或性能瓶颈影响到整个系统的正常运行。
缓存层
使用缓存是服务实现中经常采用的一种提高性能的方法,既可以提高单个请求的响应速度,又可以降低数据库层的压力。应用层服务需要获取数据时优先从缓存中读取,如果缓存没有命中,再从后端的数据库中查询。这里要注意处理好缓存穿透问题,如果在缓存中没有对应的数据,并且DB也没有查询到数据,此时大量的请求都会直接到达DB,导致DB承载高并发的问题。解决缓存穿透的问题可以对DB也没有的数据返回一个空标识的数据,并将其回写到缓存中。
哪些数据适合保存中缓存中呢?一般来说系统中的临时数据、中转数据、不经常变更且经常访问的数据都适合存储在缓存中,例如本系统中的用户状态、会话列表、离线消息等。数据库层
在数据库层面实现高可用,通常是在软件层面来做。我们使用的是MySQL数据库,MySQL是最适合互联网的数据库,免授权、高效稳定、可控性高。在实际的生产环境中,由单台MySQL作为独立的数据库是完全不能满足实际需求的,无论是在安全性,高可用性以及高并发等各个方面。因此,一般来说都是通过主从复制(Master-Slave)的方式来同步数据,再通过读写分(MySQL-Proxy)来提升数据库的并发负载能力的方案来进行部署与实施。
3.3.2 使用监控服务提高系统的可维护性
通过前面的设计我们已经极大的提高了服务的可用性,但在实际的日程运行中,网络原因、硬件损坏、程序内部Bug等意外情况都有可能造成服务的奔溃。我们的服务是部署在阿里云ECS主机上的,因此可以使用阿里云提供的云监控服务。云监控服务可以收集阿里云资源的监控指标或用户自定义的监控指标,并探测服务的可用性以及针对指标设置警报,使系统管理员能够全面了解阿里云上的资源使用情况、业务的运行状况和健康度,保证服务的顺畅运行。
除此之外我们还开发了针对应用层的监控服务,能够针对业务组件服务进行实时监控。如果发现有服务处于异常停止状态,监控服务将尝试重新启动该服务,并以短信的形式向系统管理员推送告警信息。4.方案落地效果
按照前面的设计方案我们成功开发了中通内部安全通讯系统,目前该产品已经在中通总部及下属网点大批量安装部署。全网每天日活人数达到三万左右,每天推送订单、工单等具有实效性的任务提醒和文本消息数百万条,发送申诉、仲裁类相关图片两万余张。系统上线以来运行稳定初步达到了我们的预期设计目标。
下面简单的介绍下安全通讯客户端
4.1 登录页面
集成了SSO登录授权认证机制的登录页面(图5),用户必须使用中通宝盒(中通安全客户端)扫码的方式登录安全通讯客户端。我们取消了原有的用户名、密码登录方式,进一步增强了产品的安全性。
图5. 登录页面
4.2 主面板
用户登录成功后将进入到客户端的主面板,主面板上半部分显示的是用户自定义头像、个性签名以及搜索功能,搜索功能够支持联系人及网点信息查找。中间部分展示的是最近联系人列表。在主面板的底部集成了中通常用的几款应用并能支持单点登录,方便了用户的使用。
图6. 主窗口
4.3 对话窗口
在最近联系人列表里面双击即可打开对话窗口(图7),在对话窗口里面可以发送和接收文本、图片、文件、表情等消息。
图7. 对话窗口
5.未来展望
未来我们希望将内部安全通讯系统的安全通讯能力开放给中通集团各个子公司及子业务,通过统一的内部安全通讯系统,打通和对接各子业务系统及基础设施,提供统一的有访问控制的消息和文件上传下达及分发服务,将最终用户、网点业务员、网点客服、网点管理员、总部客服、总部职能部门、总部领导连接起来,形成一个安全的高效沟通和便捷处理问题的信息交换网络,提高业务协作效率和客户服务水平的同时有效保障信息安全。
团队介绍
中通信息安全团队是一个年轻、向上、踏实以及为梦想而奋斗的大家庭,我们的目标是构建一个基于海量数据的全自动信息安全智能感知响应系统及管理运营平台。我们致力于支撑中通快递集团生态链全线业务(快递、快运、电商、传媒、金融、航空等)的安全发展。我们的技术栈紧跟业界发展,前有 React、Vue,后到 Golang、Hadoop、Spark、TiDB、AI 等。全球日均件量最大快递公司的数据规模也将是一个非常大的挑战。我们关注的方向除了国内一线互联网公司外,也关注 Google、Facebook、Amazon 等在基础安全、数据安全等方面的实践。
声明:本文来自中通安全应急响应中心,版权归作者所有。文章内容仅代表作者独立观点,不代表安全内参立场,转载目的在于传递更多信息。如有侵权,请联系 anquanneican@163.com。