我正在使用boost :: asio + openSSL编写一个透明的拦截HTTPS功能的代理。我有一个默认服务器上下文,我在其中指定服务器是TLSv1.2服务器,当客户端连接时,我从hello中提取主机并使用SSL_set_SSL_CTX
来设置上下文(已经存在或我'我只是在欺骗上游证书后创建它并启动服务器(下游)读/写凌空以及上游。
在我开始存储和共享上下文之前,这是有效的。在每个新的传入连接上,我创建了一个新的客户端套接字和上下文,将ca-bundle加载为验证文件,然后创建新的服务器上下文,获取欺骗性证书。它正在运行,但我开始开发EC_KEY对象被双重释放等问题。 I learned from another question of mine我以错误的方式解决这个问题并开始重构以回收和共享CTX对象。具体来说,我正在使用一个单独的客户端CTX,它在程序启动时加载CA-Bundle进行验证。
但是,由于这个重构,我在客户端和服务器上都得到了这个:
decryption failed or bad record mac
与pjjillion“短读”混合在一起。如果我试图强制所有TLSv1.2,我得到
block cipher pad is wrong
在读/写失败后给我这些错误,我在上游或下游套接字上调用async_shutdown
,在回调中设置错误(因此关闭失败)。
我已经搜索了从apache httpd和nginx这样的地方找到jira帖子的网站,其中这个错误以不同的方式修复(调整读取缓冲区大小,openSSL补丁,强制SSLv3,等等)。
我认为多线程可能存在问题(我的io-service使用线程池)但我可以在代码中看到提升do_init为openSSL设置锁定机制,并且我的所有IO都被包装成单个链。 / p>
我完全失去了,我想知道是否有人可以了解可能发生的事情。我意识到我没有发布任何代码,因为我已经有数百行了,并且不希望通过巨大的代码转储来解决问题。我意识到这是一个相当复杂的程序,因此是一个复杂的问题所以请问,我会尽我所能。
修改
我想我应该提一下,我在openssl 1.0.2和1.0.2a,Win 8.1 x64上都遇到了这些错误,并且我通过我的代理用WinDivert拦截和路由http / https流量。
编辑2
将整个程序减少到1个线程,效果相同。为每个客户端连接创建了新的客户端CTX,同样的问题。尝试禁用AES-NI,问题仍然存在。试过不同的电脑,效果一样。从源代码重新编译openssl(使用预编译的二进制文件),问题仍然存在。尝试设置与降级检测,填充错误等相关的当前文档中描述的其他OP_变通方法标志,问题仍然存在。我想我会马上开始随机混搭键盘和编辑按钮。
答案 0 :(得分:11)
我打算删除这个问题,但我决定回答这个问题,因为网上没有任何地方(我能找到)实际上指出了这个问题的正确解决方案。我已经阅读了关于这个错误的每一份报告,人们可以找到这些报告,并且每一个报告,人们以不同的方式“解决”或“减少”了这个错误。每一个,一个不同的解决方案。这有助于使这个问题难以推理,因为每个地方的每个人都有不同的潜在因果解释。
这很复杂,准备好了吗?如果取消/中止挂起的异步SSL操作,则会出现此错误。 Mind->吊杆()。如果你按照文档说的那样做并且使用async_shutdown这样做会更加令人困惑,因为即使回调到async_shutdown也会失败(设置错误代码)并且你的错误信息会随机变成像“解密失败或者解密”这样的愚蠢行为坏记录mac“或”块密码垫错误“或”SSLv3警报!“等等等等。 当看到这样的错误时,忽略错误并分析IO操作的控制流程,在某个地方,您要么过早地结束它们,要么让它们无序。
在我的情况下,过早的结果是(有点)有意的,因为在这个愚蠢的重型重构期间,我决定改变问题范围之外的东西,比如我的HTTPHeader解析器,我偷偷摸摸并最终导致它几乎100%失败,从而中断了连接。 :)错误字符串通过告诉我由于某种原因加密失败来掩盖真正的原因。我知道,这是一个愚蠢的错误,但我很幸福成为第一个(显然)认识它的人。 :)