OpenSSL 遇到bad record mac等错误的处理方法

OpenSSL已经广泛被接受作为加密传输的开源库 No.1,不少Linux的发行版甚至预装了OpenSSL作为系统库之一,但是,

很遗憾,可以说99%的人,包括我,不遇到致命的错误,网络上还搜索不到解决方法,是不会去看它的代码的,反正那么多人用,包括某为某宝都在依赖这个库,如果有错误,那么他们应该早就发现了,不过,倒霉的是,恐怕大家都是拿来主义,只要能解决问题,管它是怎么实现的,近日在自己的服务器代码中决定采用OPEN SSL来支持加密传输,大家都知道,TLS加密导致的性能损失是非常巨大的,作为优化之一,或者说现代编程模式,肯定会采用多线程,epoll overlap io或者非阻塞等操作,OpenSSL官方的函数也确实支持多非阻塞,可是它并没有说明如果在多线程环境里使用会有什么限制,或者说它根本没有在多线程环境里进行过足够的测试.

因为最开始也是按官方文档,参考网上的实现,成功进行了非阻塞socket在运行过程中的加密 [如果是类似https那样从开头就进行加密,那么只要多线程固定处理连接数量或者范围,是不会遇到问题的],但是考虑到性能问题,因此决定将TLS/SSL加密的握手过程独立到两个线程中去完成,防止出现阻塞或者性能突然降低问题. 代码没问题,编译一次通过,但是测试的时候,发现随机的出现tls握手失败,以为自己的代码有bug,检查了半天没有发现,不是锁的问题,因为我做了同步限制,始终保持只有一个线程操作SSL指针,然后搜索网络,看到很多人说windows平台可能会产生随机数失败,需要自己替换随机数函数,但是我这个错误明显不是随机数问题,而是 bad record mac, 也就是服务器发送的数据存在问题,类似https://stackoverflow.com/questions/29519852/openssl-decryption-failed-or-bad-record-mac-boostasio ,,还有很多的类似问题,都遇到了bad record mac,于是将思路放到了OpenSSL本身,查看OpenSSL源代码,哭了,这不是正常人能读的,到处是#if( ),放弃了从源代码查错误,但是把目标对准了OpenSSL,测试了各种步骤分别放到主和辅线程,各种奇怪的问题纷纷出现,最后决定取消多OpenSSL的多线程握手加速,将握手集中放到一个函数里,在轮循过程中进行处理,错误消失,到此,基本可以确定,1.1.0h版本OpenSSL内部加密实现的握手过程是不支持多线程加速的,这是一个天大的悲剧,

现在可以确定,OpenSSL的握手过程不是多线程安全的操作,在我写这篇文章前,网络上却始终没有一个人给出这个解答,真是悲剧,不过你很走运,如果你的软件,或者开源软件使用了OPEN SSL,使用多线程过程中出现随机的bad record mac, 或者干脆卡在tls握手阶段,恭喜你中招,解决办法只有一个,取消掉多线程握手加速,当然你想重写OpenSSL握手函数,我会非常佩服,成功了记得告诉我一声

 

 

你可能感兴趣的:(http,Linux,跨平台,c++)