gpt4 book ai didi

ssl - 如何使用代理将 boost::asio 连接到 HTTPS 服务器?

转载 作者:行者123 更新时间:2023-12-04 22:36:57 25 4
gpt4 key购买 nike

在我们的应用程序中,我们使用 boost::asio 通过 HTTP 和 HTTPS 进行连接。我们也可以使用 HTTP 代理。
现在我需要添加对使用代理的 HTTPS 服务器的支持。
我研究了很多样本​​,发现所需的步骤似乎是:

  • 创建到代理的 HTTP 连接
  • 发送 CONNECT myhost.com:443到代理
  • 然后继续使用连接作为 SSL 隧道

  • 我面临的问题在于第 3 步。我可以使用未加密的 HTTP 进行连接,也可以使用 SSL/HTTPS 进行连接。如果我在握手之前使用 HTTPS 连接(为了发送 CONNECT)失败,以及为普通 HTTP 连接执行 SSL 握手。
    这里的这篇文章包含一些片段 - 但它不包含我缺少的步骤:
    Connect SSL server via HTTP proxy using boost
    任何提示我缺少什么?
    示例代码:
    using boost::asio::ip::tcp;
    namespace ssl = boost::asio::ssl;
    typedef ssl::stream<tcp::socket> ssl_socket;

    // Create a context that uses the default paths for
    // finding CA certificates.
    ssl::context ctx(ssl::context::sslv23);
    ctx.set_default_verify_paths();


    // Open a socket and connect it to the remote host.
    boost::asio::io_context io_context;
    ssl_socket socket(io_context, ctx);
    boost::asio::connect(socket.lowest_layer(), resolver.resolve(query));
    socket.lowest_layer().set_option(tcp::no_delay(true));
    socket.set_verify_callback(ssl::host_name_verification(...));
    boost::system::error_code error = boost::asio::error::host_not_found;

    boost::asio::streambuf request2;
    std::ostream request_stream2(&request2);

    boost::asio::streambuf response2;

    request_stream2 << "CONNECT " << in_server << ":443 HTTP/1.0\r\n";
    request_stream2 << "Host: " << in_server << ":443 \r\n";
    AddBasicUserAuthHeader(request_stream2, testUrl);
    request_stream2 << "Proxy-Connection: keep-alive\r\n";
    request_stream2 << "Connection: keep-alive\r\n\r\n";

    // Send the request - this will fail with "write: uninitialized"
    boost::asio::write(socket, request);

    ... wait and process response
    socket.set_verify_mode(ssl::verify_none);
    socket.handshake(ssl_socket::client);
    此代码在 boost::asio::write 中失败,并显示“write: uninitialized”。
    此时我无法弄清楚如何将连接用作普通的 HTTP/TCP。
    反过来——首先创建一个普通的 HTTP 连接在尝试切换到 HTTPS 时失败。

    最佳答案

    钱币。那是一些参差不齐的代码。清理丢失的东西和拼写错误的东西,我注意到:

  • 您可能需要显式或隐式刷新 ostream(真的只是好习惯)
  • 您在握手之前写入 ssl 流?如果需要,只需写入底层套接字:
     boost::asio::write(socket, request);
    应该
     boost::asio::write(socket.next_layer(), request);

  • 也就是说,在您获得代理响应之前,我可能不会构建 ssl 流。我还会使用 Beast 编写请求,以排除手动处理实现细节时的任何意外。

    Live Demo
    #include <boost/asio.hpp>
    #include <boost/asio/ssl.hpp>
    #include <boost/beast.hpp>
    #include <boost/beast/ssl.hpp>
    #include <iostream>

    using boost::asio::ip::tcp;
    namespace ssl = boost::asio::ssl;
    namespace beast = boost::beast;
    namespace http = beast::http;
    using ssl_socket = ssl::stream<tcp::socket>;
    using Request = http::request<http::empty_body>;
    using Response = http::response<http::empty_body>;
    using BodyResponse = http::response<http::string_body>;

    int main()
    {
    std::string const in_server = "example.com";
    boost::asio::io_context io_context;
    tcp::resolver resolver(io_context);
    tcp::resolver::query query{"localhost", "8888"};

    // Create a context that uses the default paths for
    // finding CA certificates.
    ssl::context ctx(ssl::context::sslv23);
    ctx.set_default_verify_paths();

    // Open a socket and connect it to the remote host.
    ssl_socket socket(io_context, ctx);
    boost::asio::connect(socket.lowest_layer(), resolver.resolve(query));
    socket.lowest_layer().set_option(tcp::no_delay(true));
    socket.set_verify_callback(ssl::host_name_verification(in_server));

    {
    Request request(http::verb::connect, in_server + ":443", 10);

    request.set(http::field::host, in_server+":443");
    request.set(http::field::proxy_connection, "keep-alive");
    request.set(http::field::connection, "keep-alive");
    request.set(http::field::proxy_authorization, "basic aGVsbG86d29ybGQ=");
    request.prepare_payload(); // no body, but still good practice

    // Send the request
    http::write(socket.next_layer(), request);
    }

    Response proxy_response;
    //... wait and process response
    {
    http::response_parser<http::empty_body> p;
    beast::flat_buffer buf;
    // Only headers expected
    http::read_header(socket.next_layer(), buf, p);

    proxy_response = std::move(p.get());

    assert(buf.size() == 0); // no excess data should be received
    }

    std::cout << proxy_response << "\n";
    if (proxy_response.result() == http::status::ok) {
    socket.set_verify_mode(ssl::verify_none);
    socket.handshake(ssl_socket::client);
    std::cout << "Handshake completed" << std::endl;
    } else {
    return 1; // TODO handle errors
    }

    {
    Request request(http::verb::get, "/", 10);
    request.set(http::field::host, in_server);
    http::write(socket, request);
    }

    {
    beast::flat_buffer buf;
    BodyResponse http_res;
    http::read(socket, buf, http_res);
    std::cout << http_res;
    }
    }
    在我的机器上打印
    HTTP/1.0 200 Connection established
    Proxy-agent: tinyproxy/1.8.4


    Handshake completed
    HTTP/1.0 200 OK
    Age: 214958
    Cache-Control: max-age=604800
    Content-Type: text/html; charset=UTF-8
    Date: Mon, 25 Oct 2021 23:11:37 GMT
    Etag: "3147526947+gzip+ident"
    Expires: Mon, 01 Nov 2021 23:11:37 GMT
    Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT
    Server: ECS (bsa/EB23)
    Vary: Accept-Encoding
    X-Cache: HIT
    Content-Length: 1256
    Connection: close

    <!doctype html>
    <html>
    <head>
    <title>Example Domain</title>

    <meta charset="utf-8" />
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <style type="text/css">
    body {
    background-color: #f0f0f2;
    margin: 0;
    padding: 0;
    font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;

    }
    div {
    width: 600px;
    margin: 5em auto;
    padding: 2em;
    background-color: #fdfdff;
    border-radius: 0.5em;
    box-shadow: 2px 3px 7px 2px rgba(0,0,0,0.02);
    }
    a:link, a:visited {
    color: #38488f;
    text-decoration: none;
    }
    @media (max-width: 700px) {
    div {
    margin: 0 auto;
    width: auto;
    }
    }
    </style>
    </head>

    <body>
    <div>
    <h1>Example Domain</h1>
    <p>This domain is for use in illustrative examples in documents. You may use this
    domain in literature without prior coordination or asking for permission.</p>
    <p><a href="https://www.iana.org/domains/example">More information...</a></p>
    </div>
    </body>
    </html>

    关于ssl - 如何使用代理将 boost::asio 连接到 HTTPS 服务器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69713739/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com