我正在为第三方客户端应用程序编写一个 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,服务器在握手期间提示“未知协议(protocol)”。
我不想修改 pion 源使其只支持 sslv2。我可以获得底层的 ssl::context 对象,如何修改它以支持 sslv2?
我查看了 boost/asio/ssl/impl/context.ipp,ssl::context 是不可复制的,并且不能使用辅助函数。
有什么想法吗?
谢谢。
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
....
{}
它不起作用, boost 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()
);
最佳答案
您的问题不在于您显示的 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);
拒绝 SSLv2 连接的是 ssl::context::no_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,因为该协议(protocol)已被弃用很长时间(将近 20 年!),因为它不安全。
关于c++ - 如何更改 boost::asio::ssl::context 的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25368869/