c++ - 在与 Asio 和 OpenSSL 握手期间,*某些*网站上出现错误的版本号错误

标签 c++ ssl boost-asio sslhandshakeexception

我正在尝试使用 Asio 和 OpenSSL 发送 https 网络请求。我的代码在我尝试过的大多数网站上运行良好,但在其他一些网站上,握手期间出现错误 handshake: wrong version number (SSL routines, ssl3_get_record) .
我发现有些人遇到这个问题是因为他们在代理后面,或者因为他们试图连接到端口 80 而不是端口 443,但这里不是这种情况(据我所知),因为完全相同的代码(见下文举个例子)适用于我尝试过的大多数网站。
我试图用wireshark检查,看看我是否能发现有错误的案例和没有错误的案例之间的区别。这是我发现的:

  • 当它工作时,使用 TLSv1.2 或 1.3,当它不工作时,它是 TLSv1
  • 当它不起作用时,DNS 查询会显示 cloudfront cname 重定向,但用于套接字的端点匹配重定向

  • 基于这些观察,我知道我的代码能够使用 TLSv1.3,并且我认为使用 TLSv1 是问题所在。所以我试图通过 asio::ssl::context::tlsv13_client 强制 asio 对 TLS 使用 > 1 的版本。创建上下文时,或添加 asio::ssl::context::no_tlsv1到 set_options,但 wireshark 仍然显示使用了 TLSv1 协议(protocol)。
    对于第二点,我对网络东西不太熟悉,所以我不确定我能得出什么结论,或者即使它与问题相关。
    最小的工作示例:
    #include <asio.hpp>
    #include <asio/ssl.hpp>
    
    #include <iostream>
    
    int main(int argc, char* argv[])
    {
        try
        {
            asio::io_context io_context;
            asio::ip::tcp::resolver resolver(io_context);
            asio::ip::tcp::resolver::results_type endpoints = resolver.resolve("google.com", "https"); //not working with "api.minecraftservices.com" for example
    
            asio::ssl::context ctx(asio::ssl::context::sslv23); // also tried tlsv13_client to force v1.3, without success
            ctx.set_default_verify_paths();
            ctx.set_options(asio::ssl::context::default_workarounds | asio::ssl::context::verify_none);
    
            asio::ssl::stream<asio::ip::tcp::socket> socket(io_context, ctx);
            socket.set_verify_mode(asio::ssl::verify_none);
            socket.set_verify_callback([](bool, asio::ssl::verify_context&) {return true; });
            asio::connect(socket.lowest_layer(), endpoints);
            socket.handshake(socket.client);
        }
        catch (const std::exception& e)
        {
            std::cout << e.what() << std::endl;
            return -1;
        }
    
        return 0;
    }
    

    最佳答案

    您需要更具体地了解您尝试连接的服务器:
    Live On Coliru

    #include <boost/asio.hpp>
    #include <boost/asio/ssl.hpp>
    #include <iostream>
    
    namespace ssl = boost::asio::ssl;
    using boost::asio::ip::tcp;
    
    int main() {
        try {
            boost::asio::io_context io_context;
            tcp::resolver           resolver(io_context);
    
            ssl::context ctx(ssl::context::sslv23); // also tried tlsv13_client to
                                                    // force v1.3, without success
            ctx.set_default_verify_paths();
            ctx.set_options(ssl::context::default_workarounds |
                            ssl::context::verify_none);
    
            ssl::stream<tcp::socket> socket(io_context, ctx);
            socket.set_verify_mode(ssl::verify_none);
            socket.set_verify_callback([](auto&&...) { return true; });
    
    #ifndef COLIRU
            connect(socket.lowest_layer(), resolver.resolve("d7uri8nf7uskq.cloudfront.net", "https"));
    #else
            socket.lowest_layer().connect({boost::asio::ip::address_v4::from_string("65.9.84.220"), 443});
    #endif
            std::cout << "Connected to " << socket.lowest_layer().remote_endpoint() << "\n";
            socket.handshake(socket.client);
        } catch (std::exception const& e) {
            std::cout << e.what() << std::endl;
            return -1;
        }
    }
    
    打印
    Connected to 65.9.84.220:443
    
    更新
    事实上,使用 api.minecraftservices.com:443 确实可以打印
    Connected to 65.9.78.95:443
    handshake: wrong version number (SSL routines, ssl3_get_record) [asio.ssl:336130315]
    
    原来你需要SNI :
    SSL_set_tlsext_host_name(socket.native_handle(), "api.minecraftservices.com");
    
    然后它就可以工作了(使用不同的 IP 分辨率)
    Connected to 65.9.78.23:443
    

    关于c++ - 在与 Asio 和 OpenSSL 握手期间,*某些*网站上出现错误的版本号错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71080735/

    相关文章:

    tomcat - 将非 SSL 流量正确重定向到 SSL 流量

    c++ - 错误: ‘io_context’不是 ‘boost::asio’的成员,错误: ‘steady_timer’不是 ‘boost::asio’的成员

    c++ - boost::asio 与标准 C socket 接口(interface)的配合

    c++ - 将 Boost::Beast 用于 CPU 密集型 REST API,我应该使用异步还是同步方式来实现它们以获得更好的延迟?

    c++ - 如何将 gdb 的完整堆栈跟踪传输到文件?

    c++ - C++17 是否提供生成器或其他内置方式来并行转换非实例化序列?

    security - iOS 11 : ATS (App Transport Security) no longer accepts custom anchor certs?

    c# - DotNet Linux 错误 - 无法配置 HTTPS 端点。未指定服务器证书

    boost-asio - ICMP IPv6 数据包的最大大小

    c++ - 将数组传递给函数以显示井字棋盘