如何让服务端同时支持WebSocket和SSL加密的WebSocket

摘要:

要服务端同时支持ws与wss并不容易,其难点主要在于:wss通道必须在TCP连接刚建立时(收发消息前)就要先进行SSL加密,否则,后续的通信将无法正常进行。如此一来,当TCP连接刚建立时,服务器就无法具体分辨哪个是ws客户端哪个是wss客户端。那怎么办了?

自从HTML5出来以后,使用WebSocket通信就变得火热起来,基于WebSocket开发的手机APP和手机游戏也越来越多。我的一些开发APP的朋友,开始使用WebSocket通信,后来觉得通信不够安全,想要对通信进行加密,于是自然而然地就想从ws升级到wss。在升级的过程中,就会存在旧的ws客户端与新的wss客户端同时连接到同一个服务器的情况。所以,如果同一个服务端,能同时支持ws和wss,那就太方便了。

一. 实现方案   但是,要服务端同时支持ws与wss并不太容易,其难点主要在于:wss通道必须在TCP连接刚建立时(收发消息前)就要先进行SSL加密,否则,后续的通信将无法正常进行。如此一来,当同时存在ws和wss客户端时,服务器在尚未通信之前就无法具体分辨哪个是ws哪个是wss。那怎么办了?我们的解决方案,是采用试探法,该方案已经在 ESFramework 通信框架中实现。

(1)由于wss通道必须在TCP连接刚建立时(收发消息前)就要先进行SSL加密,否则,后续的通信将无法正常进行。

(2)基于(1),在没有收发任何消息时,服务端就无法将wss客户端与其它客户端区分开来。

(3)为此采用的办法是:对于任何刚建立的TCP连接,先都不加密它,等收到的第一个消息来判断其消息的头标志。

(4)如果头标志不是ESFramework所规定的标志,则表示这第一个消息是密文,无法被解析,从而说明这个客户端是wss。于是将该客户端的ip放到cache中,并断开该连接。

(5)wss客户端会重新连上来,此时服务端从cache中发现已经存在目标ip,则判定其为wss客户端,于是立即使用SSL加密该通道,之后,该wss客户端就可以正常通信了。

(6)由于wss 客户端 IP在cache中的过期时间是 6秒左右,所以,如果一个客户端IP刚登录了wss客户端,那么在同一个IP上登录第二个客户端(任何客户端类型),就需要相隔6秒之后。

   基于以上方案实现服务端后,我们接下来基于 ESFramework入门demo 来具体讲解一下如何在实际应用中同时支持ws和wss。

二. 服务端实现 1. 数字证书

  为测试方便,我们可以使用 CertificateCreator 制作一个用于本地测试的数字证书。  运行 CertificateCreator.exe, 然后输入Common Name(比如Test)、密码、保存路径(比如D:\server.pfx),我们就可以得到包含私钥的证书server.pfx 。双击server.pfx ,即可安装证书。 
  1. 服务端引擎设置 在服务端RapidServerEngine初始化之前,添加如下代码设置其 WssOptions 属性: WssOptions wssOptions = new WssOptions( new X509Certificate2("D:\server.pfx", "password") ,SslProtocols.Default ,false); rapidServerEngine.WssOptions = wssOptions;

三. 客户端实现 1. 信任测试用的数字证书

    由于上述生成的数字证书仅仅是用于测试的,而是不被正式认可的,所以,需要在浏览器设置中,将目标数字证书加入到信任列表。    比如, 在FireFox中,设置如下:

将服务器的地址(https://127.0.0.1:4530)添加到例外中。

  1. 客户端引擎设置 打开入门demo的Web端源码中的index.js文件,找到engine的Initialize方法,将 useWss 参数由false修改为true。然后将Web端的 index.html 文件拖入浏览器中运行即可。

四. 运行效果 登录一个wss客户端,一个ws客户端和一个.NET客户端,服务端的UI显示如下:

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏云计算

Kubernetes的服务网格(第3部分):对通信进行加密

在本文中,我们将展示如何在不修改当前应用代码的前提下来为所有的服务到服务的(service-to-service) HTTP 调用提供 TLS 支持。

4038
来自专栏网络

如何使用Burp和Magisk在Android 7.0监测HTTPS流量

HTTPS拦截的基本方法 在Android平台上拦截HTTPS流量其实并不复杂,它只需要几步便可以实现: 1.将Burp设置为我们的代理; 2.访问http:/...

5617
来自专栏电光石火

无人值守,检测程序正常运行,遇故障则重启服务

在某些情况下,如系统负载过大server无法申请到内存而挂掉、server底层发生段错误、server占用内存过大被内核Kill,或者被某些程序误杀。那se...

1905
来自专栏程序员宝库

SSH 登录流程分析

本文首发于 https://jaychen.cc 作者:jaychen(https://segmentfault.com/u/chenjiayao) 写一篇短文...

5148
来自专栏Linyb极客之路

HTTPS安全最佳实践

HTTPS对于保护你的网站至关重要。但是你还需要避免许多陷阱 1. 没有混合内容

1763
来自专栏FreeBuf

Oracle数据库漏洞分析:无需用户名和密码进入你的数据库

摘要 一般性的数据库漏洞,都是在成功连接或登录数据库后实现入侵;本文介绍两个在2012年暴露的Oracle漏洞,通过这两种漏洞的结合,可以在不掌握用户名/密码...

3196
来自专栏魏艾斯博客www.vpsss.net

LNMP 1.4 正式版安装测试记录及自动生成 Let’s Encrypt 免费证书

1762
来自专栏漏斗社区

CTF| 吃个鸡,一起破流量分析题吧!

流量分析题是CTF杂项类常见的一种考点,考察我们分析网络流量包的能力。一般flag隐藏在某个数据包里面,或者需要从中提取一个文件出来等等,还有wifi的握手包,...

5175

Kubernetes的服务网格(第3部分):加密一切数据

在本文中,我们将向您展示如何使用linkerd作为服务网格,将TLS添加到所有服务到服务的HTTP调用中,而不用修改任何应用程序代码。

2229
来自专栏云计算教程系列

如何在CentOS上使用双重身份验证

在本教程中,您将学习如何在CentOS 7上使用一次性密码进行SSH上的双重身份验证。

2053

扫码关注云+社区

领取腾讯云代金券