C++ boost asio和SSL的消息大小过大
我目前正在使用SSL保护传输的服务器上工作。在接受一个协议后,服务器进行hadshake,如果成功,它将向客户端发送一个数据包 我的代码在Windows上运行得非常好,但当我在Debian 7上运行它时,当我尝试编写该数据包时,会出现“消息大小过大”错误 我非常确定它不是来自我的证书,因为我尝试使用相同的证书运行boost asio SSL示例,它工作得非常好 代码如下: 服务器的初始化:C++ boost asio和SSL的消息大小过大,c++,boost,ssl,C++,Boost,Ssl,我目前正在使用SSL保护传输的服务器上工作。在接受一个协议后,服务器进行hadshake,如果成功,它将向客户端发送一个数据包 我的代码在Windows上运行得非常好,但当我在Debian 7上运行它时,当我尝试编写该数据包时,会出现“消息大小过大”错误 我非常确定它不是来自我的证书,因为我尝试使用相同的证书运行boost asio SSL示例,它工作得非常好 代码如下: 服务器的初始化: Server::Server(configuration::Configuration const &am
Server::Server(configuration::Configuration const & conf, utils::Logger & log): _cmds(conf, log), _conf(conf), _logger(log), _ctx(boost::asio::ssl::context::sslv23)
{
tcp::endpoint endpoint(tcp::v4(), conf.getPort());
configuration::SSL_conf ssl = conf.getSLLInfos();
try
{
this->_ctx.set_options(boost::asio::ssl::context::default_workarounds
| boost::asio::ssl::context::no_sslv2
| boost::asio::ssl::context::single_dh_use);
this->_ctx.set_password_callback(boost::bind(&Server::_getPass, this, _1, _2));
this->_ctx.use_certificate_file(ssl.certificate.string(), boost::asio::ssl::context_base::pem);
this->_ctx.use_private_key_file(ssl.key.string(), boost::asio::ssl::context_base::pem);
this->_ctx.use_tmp_dh_file(ssl.certificate.string());
this->_acceptor.reset(new tcp::acceptor(this->_service, endpoint));
this->_logger.logMsg(3, "Starting listen on port " + std::to_string(endpoint.port()));
for (int i = 0; i < 256; ++i)
this->_c.push_back(std::shared_ptr<Client>(new Client(this->_service, this->_cmds, conf, log, i, this->_ctx)));
this->_acceptor->async_accept(this->_c.front()->getSocket(),
boost::bind(&Server::_handleAccept, this,
this->_c.front(),
boost::asio::placeholders::error));
}
catch (boost::system::system_error & err)
{
this->_logger.logErr(err.what());
}
}
handhsake回调:
void Client::handleHandshake(boost::system::error_code const & err)
{
if (!err)
{
memset(&this->_header, 0, sizeof(protocol::header));
this->_keepAlive = this->_conf.getKeepAlive();
this->_header.keepAlive = 1;
this->_logger.logStruct<protocol::header>("Client [" + std::to_string(this->_id) + "] Sending handhsake: ", this->_header);
boost::asio::async_write(this->_socket, boost::asio::buffer(&this->_header, sizeof(protocol::header)),
boost::bind(&Client::handleWrite, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
else
this->kill();
}
正如我所说,handleWrite回调接收到一个值为“消息大小过大”的错误。我真的不明白为什么,因为我对boost asio的使用非常标准,而且我的证书是自签名的,可以与其他应用程序一起使用
谢谢您的帮助。根据您的描述,问题不在于SSL握手本身,而在于
Client::handleHandshake
中对async\u write
的调用中的缓冲区
我建议记录sizeof(_header)
和sizeof(protocol::header)
,并在两种实现中比较它们
顺便问一下,您在哪里为
\u头分配内存?它是在构造函数中完成的吗?因为它不是在Client::init()
中完成的,所以正如在一篇评论中所说的,问题在于出于某种原因,让客户端和服务器决定选择哪个版本似乎会把事情搞砸。通过强制使用SSLV3,它解决了这个问题。谢谢大家的帮助。尝试配置特定的SSL协议版本(例如,仅SSLv3)。这将减少要发送的项目列表
也可以考虑发送一个最小化的证书包(在服务器上的证书文件中),因为客户不会对链中的大多数根证书感兴趣,除非它已经知道了。它表示我正在使用的协议的数据包的报头。顺便说一下_header的类型是protocol::header,它的大小在windows和debian上都是一样的。由于它不是指针,系统在对象构造时分配内存。在这种情况下,问题可能是由于Windows和Debian编译器对protocol::header的字节布局使用不同的对齐方式造成的。应使用说明符或相应的
#pragma
来确保结构的布局。否则,编译器可以随意填充它。感谢您提供的提示,但是我尝试发送一个经典缓冲区(char*)而不是结构,问题仍然存在。请尝试配置特定的SSL协议版本(例如,仅SSLv3)。这将减少要发送的项目列表。另外,考虑发送一个最小化的证书包(在服务器上的证书文件中),因为客户端不会对链中的大多数根证书感兴趣,除非它已经知道它们在任何方向上摇摆!我真不敢相信这解决了它。我所做的只是将ssl_上下文的初始化参数从sslv23更改为sslv3,它就像一个符咒。谢谢你,伙计!我把它贴出来作为一个回答:/这可能不是关于“强迫选择”,只是缩小选择的范围会使实际的握手包变小
void Client::handleHandshake(boost::system::error_code const & err)
{
if (!err)
{
memset(&this->_header, 0, sizeof(protocol::header));
this->_keepAlive = this->_conf.getKeepAlive();
this->_header.keepAlive = 1;
this->_logger.logStruct<protocol::header>("Client [" + std::to_string(this->_id) + "] Sending handhsake: ", this->_header);
boost::asio::async_write(this->_socket, boost::asio::buffer(&this->_header, sizeof(protocol::header)),
boost::bind(&Client::handleWrite, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
else
this->kill();
}
void Client::handleWrite(boost::system::error_code const & err, std::size_t)
{
if (!err && this->_keepAlive)
{
clearBuff(this->_outBuff);
boost::asio::async_read(this->_socket, boost::asio::buffer(&this->_header, sizeof(protocol::header)),
boost::bind(&Client::handleHeaderRead, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
else
{
this->_logger.logErr("Client [" + std::to_string(this->_id) + "] write failed : " + err.message());
this->kill();
}
}