Boost SSL验证过期和自签名证书 [英] Boost SSL verifies expired and self-signed certificates

查看:323
本文介绍了Boost SSL验证过期和自签名证书的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Boost的asio通过HTTPS连接到站点.我希望只有在证书有效,未过期,未自签名等情况下才能成功.不幸的是,无论如何它似乎总是可以工作.这是我的代码:

I'm using Boost's asio to connect to a site via HTTPS. I want this to only succeed if the certificate is valid, not expired, not self-signed, etc. Unfortunately it seems to always work regardless. Here is my code:

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);

以此类推.如果我使用set_verify_callback()并从回调中返回false,则连接确实会失败,但是即使对于preverified似乎总是正确的rel ="nofollow"> https://self-signed.badssl.com/.当然不对吗?

And so on. If I use set_verify_callback() and return false from the callback, the connection does fail, but preverified always seems to be true, even for https://self-signed.badssl.com/. Surely that isn't right?

推荐答案

此处的问题是服务器名称指示(SNI):

The issue here is Server Name Indication (SNI):

服务器名称指示(SNI)是TLS计算机的扩展 客户端用来指示主机名的网络协议 在握手过程开始时尝试连接.这 允许服务器在同一IP上显示多个证书 地址和TCP端口号,因此允许多个安全(HTTPS) 网站(或任何其他基于TLS的服务)使用同一IP进行服务 地址,而无需所有这些网站都使用相同的证书.

Server Name Indication (SNI) is an extension to the TLS computer networking protocol by which a client indicates which hostname it is attempting to connect to at the start of the handshaking process. This allows a server to present multiple certificates on the same IP address and TCP port number and hence allows multiple secure (HTTPS) websites (or any other Service over TLS) to be served off the same IP address without requiring all those sites to use the same certificate.

当您没有SNI连接时,badssl.com服务器正在发送带有正确链的证书.如果与SNI连接,则将发送自签名证书.您可以通过在命令行上通过观察两个命令之间的差异来使用OpenSSL进行验证:

The badssl.com server is sending a certificate with a proper chain when you connect with no SNI. If you connect with SNI then the self-signed certificate will be sent. You can verify this with OpenSSL on the command line by observing the difference between the two commands:

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

boost::asio没有添加SNI的API,但我认为您可以通过使用基础的OpenSSL API和

boost::asio has no API to add SNI, but I think you can do it by using the underlying OpenSSL API and the native_handle() method on your stream. It should be something like this:

SSL_set_tlsext_host_name(socket.native_handle(), "self-signed.badssl.com");

我确实注意到您正在使用sslv3_client配置上下文.由于SNI是TLS扩展(即不是SSLv3),因此如果不配置TLS上下文,这可能无法正常工作.

I do note that you are configuring your context with sslv3_client. As SNI is a TLS extension (i.e. not SSLv3), this may not work without configuring a TLS context.

这篇关于Boost SSL验证过期和自签名证书的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆