握手错误(无共享密码) 具有反向代理的 HTTPS 服务器 ASIO C++

handshake errors (no shared cipher) https server with reverse proxy ASIO c++

提问人:IH8CODINGBUTILOVEIT 提问时间:11/7/2023 更新时间:11/7/2023 访问量:33

问:

嘿,我在握手过程中遇到了问题,握手失败/没有共享密码或未知证书。这是一个反向代理服务器,我正在尝试创建它数周。我目前无法通过这个阶段。请帮忙。

法典:


    asio::ssl::context ctx_server(asio::ssl::context::tlsv12_server);
    ctx_server.set_options(asio::ssl::context::default_workarounds
        | asio::ssl::context::no_sslv2
        | asio::ssl::context::no_sslv3
        | asio::ssl::context::no_tlsv1_1
        | asio::ssl::context::tlsv12_server);
    add_windows_root_certs(ctx_server);

    ctx_server.set_verify_mode(asio::ssl::verify_peer | asio::ssl::verify_fail_if_no_peer_cert);

    std::filesystem::path cert_path = std::filesystem::current_path() / "server.crt";
    std::filesystem::path key_path = std::filesystem::current_path() / "server.key";
    std::filesystem::path csr_path = std::filesystem::current_path() / "server.csr";
    

    ctx_server.set_password_callback([](auto, auto) -> std::string { return "195709059"; });
    ctx_server.use_certificate_chain_file(cert_path.string());
    ctx_server.use_private_key_file(key_path.string(), asio::ssl::context::pem);
    
    auto ioc = std::make_shared<asio::io_context>();
    auto ioc2 = std::make_shared<asio::io_context>();

    asio::ip::tcp::acceptor acceptor{ *ioc, asio::ip::tcp::endpoint(asio::ip::tcp::v4(), 40000)};

    while (1) {
        asio::streambuf streambuffer;
        std::error_code ec;

        asio::ssl::stream<asio::ip::tcp::socket> socket{ *ioc, ctx_server };
    
        acceptor.accept(socket.lowest_layer());
        acceptor.set_option(asio::ip::tcp::acceptor::reuse_address(true));
        socket.lowest_layer().set_option(asio::ip::tcp::socket::keep_alive(true));
        socket.lowest_layer().set_option(asio::ip::tcp::no_delay(true));

        std::string repquest, repsponse;

        while (socket.lowest_layer().is_open()) {
            // read http status
            auto length = asio::read_until(socket.next_layer(), streambuffer, "\n", ec);

            if (!ec) {
                if (length <= 0) {
                    std::cout << "do_read_http_status empty length" << std::endl;
                    break;
                }

                std::istream iss(&streambuffer);
                std::string temp;
                std::string host, port;

                // Process the response headers.
                while (std::getline(iss, temp) && temp != "\r")
                {
                    size_t i = temp.find("Host: ");
                    if (i != std::string::npos) {
                        std::string t = temp.substr(6);
                        size_t j = t.find(":");
                        host = t.substr(i, j);
                        port = t.substr(j + 1, t.size());
                        repquest += temp + '\n';
                    }
                }

                std::cout << repquest << std::endl;

                ctx_server.set_verify_callback(asio::ssl::rfc2818_verification(host));

                std::cout << "host: " << host << std::endl;

                ready = false;

                auto query = asio::ip::tcp::resolver::query(host,/*port == "443" ? "https" : "http"*/"https");

                asio::ip::tcp::resolver resolver{ *ioc };

                asio::error_code ec;
                asio::ip::tcp::resolver::results_type results = resolver.resolve(query, ec);

                if (ec || results.empty()) {
                    std::cout << "failed to resolve dns: " << ec.message() << std::endl;
                    socket.lowest_layer().shutdown(asio::socket_base::shutdown_both);
                    break;
                }
                
                std::string h =
                    "HTTP/1.1 200 OK\n"
                    "Connection: close\n"
                    "\n";

                // establish TLS
                socket.set_verify_mode(asio::ssl::verify_peer);

                socket.set_verify_callback([&](bool preverified, asio::ssl::verify_context& ctx)
                    {
                        char subject_name[256];
                        X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle());
                        X509_NAME_oneline(X509_get_subject_name(cert), subject_name, 256);
                        std::cout << "Verifying:\n" << subject_name << std::endl;

                        return preverified;
                    });

                // Set SNI Hostname (many hosts need this to handshake successfully)
                if (!SSL_set_tlsext_host_name(socket.native_handle(), "..."))
                {
                    std::error_code ec{ static_cast<int>(::ERR_get_error()), asio::error::get_ssl_category() };
                    throw asio::system_error{ ec };
                };      

                std::shared_ptr<connection> connection(std::make_shared<connection>(*ioc2, ctx_client, results));

                // initializes a connection (connect to a socket)
                connection->init();

                std::thread contextThread2([&ioc2]() { ioc2->run(); });

                std::this_thread::sleep_for(1s);

                if (!connection->isRunning()) {
                    std::cout << "connection couldn't establish properly.. " << std::endl;
                    socket.lowest_layer().shutdown(asio::socket_base::shutdown_both);
                    break;
                }

                // send CONNECT response..
                auto sz = asio::write(socket.next_layer(), asio::buffer(h, h.size()), ec);
                if (sz <= 0 || ec) {
                    std::cout << "error writing back connect response" << std::endl;
                    socket.lowest_layer().shutdown(asio::socket_base::shutdown_both);
                    break;
                }

                socket.handshake(asio::ssl::stream_base::server, ec);
                if (ec) {
                    std::cout << "handshake failed" << ec.message() << std::endl;
                    break;
                }

输出:

主机:www.google.com 早期连接成功 172.217.22.4 握手连接成功 握手失败SSLv3 警报证书未知(SSL 例程)

openssl 输出:

asiotest/server.crt -key D:/source/repos/httpasiotest/httpasiotest/server.key
>>
Enter pass phrase for D:/source/repos/httpasiotest/httpasiotest/server.key:
CONNECTED(00000148)
300A0000:error:0A000126:SSL routines:ssl3_read_n:unexpected eof while reading:ssl\record\rec_layer_s3.c:304:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 304 bytes
Verification: OK
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)

请帮忙!我严重迷路了。

C++ 服务器 HTTPS 代理 ASIO

评论

0赞 user207421 11/7/2023
这通常意味着服务器没有或找不到私钥。
0赞 IH8CODINGBUTILOVEIT 11/7/2023
如何进一步调查?因为我正在读取私钥,它不会产生任何错误

答: 暂无答案