使用 boost::asio(同步调用)通过 HTTP 代理在 HTTPS TLS 握手中出现流截断错误

stream truncated error on HTTPS TLS handshake via a HTTP proxy using boost::asio (synchronous calls)

我正在研究一些 HTTP 代码以连接到 REST 端点。我在公司网络中工作,与外界的连接必须通过 HTTP 代理,而端点在 HTTPS 上。

现在,我已经成功地使用 Python requestscurl 进行了这些调用,但是在 C++ 中进行相同的调用一直很痛苦。

我正在尝试使用以下代码通过此代理执行握手(连接到示例 Postmen 端点),该代码改编自以下示例:

#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>

#include <boost/beast.hpp>

#include <boost/beast/http.hpp>
#include <boost/beast/http/empty_body.hpp>
#include <boost/beast/http/fields.hpp>
#include <boost/beast/http/message.hpp>
#include <boost/beast/http/string_body.hpp>

#include<boost/certify/https_verification.hpp>

#include <iostream>

using tcp = boost::asio::ip::tcp;
namespace http = boost::beast::http;

// https://postman-echo.com/post see https://docs.postman-echo.com/?version=latest
static const std::string
        server_endpoint = "/post",
        hostname = "postman-echo.com",
        target = "https://postman-echo.com:443",
        port_no = "443",
        authorization_token =
        "Auth: "
        "c3RhdGljIGNvbnN0IHN0ZDo6c3RyaW5nIGF1dGhvcml6YXRpb"
        "25fdG9rZW4gPSAiQXV0aDogIj"
        "sK",
        client_name = "User-Agent: demo program 0.01",
        req_str = R"(name=blabla&password=bloblo)";

int main() {
    boost::asio::io_service io_service;
    boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);

    // Establish TCP base socket to Proxy
    tcp::socket base_sock{io_service};
    tcp::resolver resolver(io_service);

    {
        // Connect socket via proxy
        const boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> proxy_hosts = resolver.resolve("PROXY_ADDR", "PROXY_PORT");
        if (proxy_hosts.empty()) {
            throw std::range_error("Proxy cannot be resolved.");
        }
        std::cout << "Proxy IP address: " << proxy_hosts->endpoint().address() << std::endl;

        //boost::asio::ip::tcp::socket::lowest_layer_type& socket = base_sock.lowest_layer();
        base_sock.connect(proxy_hosts->endpoint());
    }

    {
        // Converts request to transparent TCP/IP tunnel. To facilitate TLS communications
        // through HTTP proxy.
        http::request<http::string_body> req1{http::verb::connect, target, 11};
        req1.set(http::field::host, target);
        http::write(base_sock, req1);

        boost::beast::flat_buffer buffer;

        http::response<http::empty_body> res;
        http::parser</* isRequest */ false, http::empty_body> http_parser(res);

        /** Set the skip parse option. */
        http_parser.skip(true); // see 

        http::read_header(base_sock, buffer, http_parser);

        // Write the message to standard out
        std::cout << "target_host response: " << res << std::endl;
    }

    ctx.set_verify_mode(boost::asio::ssl::verify_peer);
    //ctx.load_verify_file("/** ssl/cacert from python requests library */");
    //ctx.add_verify_path("/** CA certificates from Curl via strace https://serverfault.com/questions/485597/default-ca-cert-bundle-location */");
    //ctx.load_verify_file("/** CA certs from curl via calling endpoints with --verbose */");
    //ctx.set_default_verify_paths(); 
    boost::certify::enable_native_https_server_verification(ctx); // from lib https://github.com/djarek/certify
    ctx.set_options(boost::asio::ssl::context::default_workarounds |
                    boost::asio::ssl::context::no_sslv2 |
                    boost::asio::ssl::context::no_sslv3);

    boost::asio::ssl::stream<boost::asio::ip::tcp::socket&> ssl_socket(base_sock,
                                                                       ctx);

    {
        //ssl_socket.handshake(boost::asio::ssl::stream_base::client);
        ssl_socket.handshake(boost::asio::ssl::stream<tcp::socket&>::client);

        /** Make REST calls here */
    }
}

运行 上面的代码在握手步骤失败,出现“流被截断”错误。

到目前为止我的尝试是:

虽然我在编写网络代码方面的经验有限,但错误很可能是我的逻辑某处而不是不正确的环境。

想知道是否有人可以指出代码可能在哪里不正确?

经过更多试验,我注意到问题出在 target 变量中。设置 target = "postmen-echo.com:443"; - 删除 https 前缀,并传入适当的 CA 证书(例如来自 Python 或 Curl)可解决此问题。