Tim*_*mmm 3 ssl boost openssl ssl-certificate boost-asio
我正在使用Boost的asio通过HTTPS连接到网站.我希望这只有在证书有效,没有过期,没有自签名等情况下才能成功.不幸的是,似乎无论如何总是有效.这是我的代码:
try
{
asio::io_service ioService;
asio::ssl::context sslContext(asio::ssl::context::sslv3_client);
sslContext.load_verify_file("cacert.pem");
asio::ip::tcp::resolver resolver(ioService);
asio::ip::tcp::resolver::query query("self-signed.badssl.com", "443");
asio::ip::tcp::resolver::iterator endpointIterator = resolver.resolve(query);
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket(ioService, sslContext);
ioService.run();
// Enable SSL peer verification.
socket.set_verify_mode(asio::ssl::verify_peer | asio::ssl::verify_fail_if_no_peer_cert);
asio::connect(socket.lowest_layer(), endpointIterator);
socket.handshake(asio::ssl::stream_base::client);
boost::asio::streambuf request;
std::ostream requestStream(&request);
requestStream << "GET / HTTP/1.0\r\n";
requestStream << "Host: self-signed.badssl.com\r\n";
requestStream << "Accept: */*\r\n";
requestStream << "Connection: close\r\n\r\n";
asio::write(socket, request);
Run Code Online (Sandbox Code Playgroud)
等等.如果我使用set_verify_callback()并false从回调中返回,连接确实会失败,但preverified似乎总是如此,即使对于https://self-signed.badssl.com/也是如此.当然那不对?
这里的问题是服务器名称指示(SNI):
服务器名称指示(SNI)是TLS计算机网络协议的扩展,客户端通过该协议指示在握手过程开始时它尝试连接的主机名.这允许服务器在相同的IP地址和TCP端口号上呈现多个证书,因此允许多个安全(HTTPS)网站(或任何其他TLS服务)从同一IP地址提供服务,而无需所有这些站点使用相同的证书.
当您连接没有SNI时,badssl.com服务器正在发送带有正确链的证书.如果您使用SNI连接,则会发送自签名证书.您可以通过观察两个命令之间的差异,在命令行上使用OpenSSL验证这一点:
openssl s_client -connect self-signed.badssl.com:443 -showcerts
openssl s_client -connect self-signed.badssl.com:443 -servername self-signed.badssl.com -showcerts
Run Code Online (Sandbox Code Playgroud)
boost::asio没有用于添加SNI的API,但我认为您可以通过在流上使用基础OpenSSL API和native_handle()方法来实现.它应该是这样的:
SSL_set_tlsext_host_name(socket.native_handle(), "self-signed.badssl.com");
Run Code Online (Sandbox Code Playgroud)
我注意到你正在配置你的上下文sslv3_client.由于SNI是TLS扩展(即不是SSLv3),因此如果不配置TLS上下文,这可能无法工作.
| 归档时间: |
|
| 查看次数: |
1685 次 |
| 最近记录: |