【问题标题】:OpenSSL decryption failed or bad record mac boost::asioOpenSSL 解密失败或坏记录 mac boost::asio
【发布时间】:2015-06-13 17:14:13
【问题描述】:

我正在使用 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

.. 混合了无数的“短读”。如果我尝试强制使用 TLSv1.2,我会得到

block cipher pad is wrong

在读/写失败后给我这些错误,我在上游或下游套接字上调用 async_shutdown,在回调中设置错误(因此关闭失败)。

我搜索了互联网,从 apache httpd 和 nginx 等地方找到了 jira 帖子,这些地方以不同的方式修复了此错误(将读取缓冲区的大小调整为更大、openSSL 补丁、强制 SSLv3 等等)。

我认为多线程可能存在问题(我的 io 服务使用线程池),但我可以在代码中看到 boost do_init 为 openSSL 设置了锁定机制,并且我的所有 IO 都被包装成一条链。

我完全不知所措,想知道是否有人可以阐明可能发生的事情。我意识到我没有发布任何代码,那是因为我有成百上千行代码,并且不想通过大量代码转储来关闭人们。但是我意识到这是一个相当复杂的程序,因此是一个复杂的问题,所以请询问,我会尽我所能提供。

编辑
为了完整起见,我想我应该提到我在 openssl 1.0.2 和 1.0.2a、Win 8.1 x64 上都遇到了这些错误,并且我正在使用 WinDivert 通过我的代理拦截和路由 http/https 流量。

编辑 2
将整个程序减少到 1 个线程,效果相同。为每个客户端连接创建了新的客户端 CTX,同样的问题。尝试禁用 AES-NI,问题仍然存在。试过不同的电脑,效果一样。从源代码重新编译 openssl(使用预编译的二进制文件),问题仍然存在。尝试设置当前文档中描述的与降级检测、填充错误等相关的其他 OP_ 解决方法标志,问题仍然存在。我想我很快就会开始随机捣碎键盘和编译按钮。

【问题讨论】:

  • 单线程可能存在并发问题,尤其是在使用协同例程时。线程检查一些东西,做一些隐含或间接产生并允许另一个线程运行的东西,然后假设它之前检查的东西没有改变,然后做一些事情。每个 SSL 连接是否都有关联的链?是否所有可以触发组合操作的异步操作都在链上正确分派?
  • @DavidSchwartz yessir,他们确实有一个关联的链,并且所有访问连接的异步操作也都被包装了。
  • @DavidSchwartz 我修复了它,这是最荒谬的事情,来自 openSSL 的错误代码掩盖了真正的问题,当我忽略它们的控制流时,原来是解析初始请求失败,由于没有触发 async_io 操作来进行会话,导致会话过早关闭,从而导致 boost 错误代码聚合神秘但(几乎)完全不相关的“解密失败或。 ……”。谢谢你的帮助。不知道我是否应该回答这个问题。
  • 我猜你可以自己回答。

标签: c++ ssl boost openssl boost-asio


【解决方案1】:

我打算删除这个问题,但我决定回答这个问题,因为网络上没有任何地方(我可以找到)实际上指出了这个问题的正确解决方案。我已经阅读了每一份关于这个错误的报告,人们可以找到每一份报告,人们以不同的方式“解决”或“减少”了这个错误。每一个都是不同的解决方案。这就是让这个问题如此难以推理的原因,因为每个地方的每个人都有不同的潜在因果解释。

这很复杂,准备好了吗?如果您取消/中止挂起的异步 SSL 操作,则会出现此错误。头脑->繁荣()。如果你按照文档所说的去做并使用 async_shutdown 这样做会更加混乱,因为即使是对 async_shutdown 的回调也会失败(设置了错误代码),并且你的错误消息会随机出现一些愚蠢的东西,比如“解密失败或坏记录 mac”或“块密码板错误”或“SSLv3 警报!”等等等等。 当看到这样的错误时,忽略这些错误并分析你的 IO 操作的控制流,在某个地方你要么过早地结束它们,要么让它们失序。 p>

在我的情况下,过早结束是(某种)故意的,因为在这个愚蠢的重度重构期间,我决定改变问题范围之外的东西,比如我的 HTTPHeader 解析器,我把它弄出来并最终导致它几乎 100% 失败并因此中止连接。 :) 错误字符串通过告诉我加密由于某种原因而失败来掩盖真正的原因。我知道愚蠢的错误,但我很高兴成为第一个(显然)认识到它的人。 :)

【讨论】:

  • 我知道这是旧的,但是当我这样做时我遇到了同样的问题:ssl_do_handshake,它的转向 SSL_ERROR(1),以及这个确切的问题。使用 1.0.2l。
猜你喜欢
  • 1970-01-01
  • 2012-08-06
  • 1970-01-01
  • 2013-07-05
  • 2014-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-19
相关资源
最近更新 更多