【问题标题】:how to change the method of boost::asio::ssl::context如何更改 boost::asio::ssl::context 的方法
【发布时间】:2014-08-18 17:30:58
【问题描述】:

我正在为第三方客户端应用程序编写一个 https 服务器。我正在使用pion c++网络库来实现服务器,

棘手的是:客户端使用 sslv2 而 pion 使用 sslv23 作为上下文方法。这是构造函数:

server::server(...)
    : .....
    m_ssl_context(m_active_scheduler.get_io_service(),
                        boost::asio::ssl::context::sslv23), // <--- not configurable
    ....
{}

我了解 sslv2 存在安全问题,因此 pion 默认使用 sslv23,但客户端仅使用 sslv2。使用 sslv23,服务器在握手期间抱怨“未知协议”。

我不想修改 pion 源使其仅支持 sslv2。我可以获得底层的 ssl::context 对象,如何修改它以支持 sslv2

我查看了 boost/asio/ssl/impl/context.ipp,ssl::context 是 noncopyable,并且没有任何辅助函数可以与它一起使用。

有什么想法吗?

谢谢。

UPDATE_1

这里有一些测试

测试 1

我修改了pion源码并重新编译了,只是注释掉no_sslv2这一行

    m_ssl_context.set_options(
        boost::asio::ssl::context::default_workarounds
        //| boost::asio::ssl::context::no_sslv2 <------ remove this
        | boost::asio::ssl::context::single_dh_use);

并让它使用 sslv23(构造函数中有四个 sslv23)

server::server(...)
    : .....
    m_ssl_context(m_active_scheduler.get_io_service(),
                        boost::asio::ssl::context::sslv23), // left it as sslv23
    ....
{}

它不起作用,提升 error_code.message() :

peer error no cipher

测试 2

如果我不碰 no_sslv2

    m_ssl_context.set_options(
        boost::asio::ssl::context::default_workarounds
        | boost::asio::ssl::context::no_sslv2 <------
        | boost::asio::ssl::context::single_dh_use);

将四个sslv23改为sslv2

server::server(...)
    : .....
    m_ssl_context(m_active_scheduler.get_io_service(),
                        boost::asio::ssl::context::sslv2), // change from sslv23 to sslv2
    ....
{}

然后它工作正常。我想实际上重要的是构造函数中的 sslv23 方法。在上下文的构造函数中:

context::context(context::method m)
  : handle_(0)
{
  switch (m)
  {
  ...
  case context::sslv2:
    handle_ = ::SSL_CTX_new(::SSLv2_method());
    break;
  ...
  case context::sslv23:
    handle_ = ::SSL_CTX_new(::SSLv23_method());
    break;
  }
  ....
}

SSLv23_method 与 SSLv2_method 不兼容?

而且我认为客户端使用 sslv2,因为我使用 openssl 对其进行了测试:

测试 3

openssl s_server -accept 443 -key server.pem -cert server.pem -ssl2

这使得 openssl 充当服务器,然后将客户端连接到它,它工作正常。根据 openssl 的文档,尾随 -ssl2 强制它使用 sslv2。 -ssl3-tls1 都不起作用,openssl 说:“版本号错误”

UPDATE_2

我试过了,好像也可以,不知道会不会导致内存泄漏。

    SSL_CTX_set_ssl_version( // use the native handle
        m_server_443->get_ssl_context_type().native_handle(), ::SSLv2_method()
    );

【问题讨论】:

  • 正如 rhashimoto 回答的那样,SSLv23_method 的问题不是。这实际上是构建上下文的方式。你从 2/3 方法开始,然后去掉你不想要的东西,比如 SSLv2、SSLv3 和压缩。例如,请参阅 OpenSSL wiki 上的 SSL/TLS Client

标签: c++ ssl boost boost-asio


【解决方案1】:

您的问题不在于您展示的m_ssl_context 的构造。 ssl::context::sslv23 的规范意味着您的服务器接受 SSLv2 或更高版本以开始协商安全连接。不允许 SSLv2 的限制在同一个文件中,但在此之后:

m_ssl_context.set_options(boost::asio::ssl::context::default_workarounds
                          | boost::asio::ssl::context::no_sslv2
                          | boost::asio::ssl::context::single_dh_use);

ssl::context::no_sslv2 选项拒绝 SSLv2 连接。

您可以像这样重置这些选项:

SSL_CTX_clear_options(m_server->get_ssl_context_type().native_handle(), SSL_OP_NO_SSLv2)
SSL_CTX_set_cipher_list(m_server->get_ssl_context_type().native_handle(), "TLSv1:SSLv3:SSLv2");

这两行使用底层 OpenSSL API 来 (1) 清除在 set_ssl_key_file() 成员函数中设置的 no_sslv2 选项,以及 (2) 确保启用 SSLv2 密码。使用 set_options() 成员函数不起作用,因为它无法清除先前设置的选项,因此必须使用 OpenSSL API 函数 SSL_CTX_clear_options()

奇怪的是,您有一个仅使用 SSLv2 的客户端,因为该协议在很长一段时间内(近 20 年!)都被认为不安全而被弃用。

【讨论】:

  • @aj3423 我认为您可以在不修改库源代码的情况下使SSLv23_method 工作。 “无密码”错误消息意味着握手正在工作,但客户端和服务器无法就密码达成一致。我怀疑默认情况下 OpenSSL 不接受很多 SSLv2 密码,除非您明确要求 SSLv2。尝试添加类似SSL_CTX_set_cipher_list(m_server_443-&gt;get_ssl_context_type().native_handle(), "TLSv1:SSLv3:SSLv2"); 的呼叫(除了set_options() 呼叫)。这将允许来自这三个协议的所有密码。
  • 我试过set_ssl_key_file -> set_options -> SSL_CTX_set_cipher_list,好像不行,错误信息是“未知协议”
  • @aj3423 啊,doc 说:“这些选项与选项的任何现有值按位或运算。”因此,一旦设置了no_sslv2,似乎就无法使用 Boost API 取消设置。您必须使用 OpenSSL API 做一些事情,例如 SSL_CTX_clear_options(m_server_443-&gt;get_ssl_context_type().native_handle(), SSL_OP_NO_SSLv2)
  • 这就是关键。它适用于SSL_CTX_clear_options + SSL_CTX_set_cipher_list。非常感谢rhashimoto。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-06-08
  • 2015-03-31
  • 2022-01-09
  • 1970-01-01
  • 1970-01-01
  • 2023-01-26
相关资源
最近更新 更多