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

2024-05-07

在我们的应用程序中,我们使用 boost::asio 来使用 HTTP 和 HTTPS 进行连接。我们还可以使用 HTTP 代理。 现在我需要使用代理添加对 HTTPS 服务器的支持。

我研究了相当多的样本,发现所需的步骤似乎是:

  1. 创建到代理的 HTTP 连接
  2. Send CONNECT myhost.com:443到代理
  3. 然后继续使用该连接作为 SSL 隧道

我面临的问题在于步骤 3。我可以使用未加密的 HTTP 连接或使用 SSL/HTTPS 连接。如果我在握手之前使用 HTTPS 连接(为了发送 CONNECT),则会失败,并且对普通 HTTP 连接执行 SSL 握手。

这篇文章包含一些片段 - 但它不包含我缺少的步骤:使用 boost 通过 HTTP 代理连接 SSL 服务器 https://stackoverflow.com/questions/44939973/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 编写请求,以排除手动处理实现细节时出现的任何意外。


现场演示 http://coliru.stacked-crooked.com/a/6c12bc92e8b1f876

#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>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用代理将 boost::asio 连接到 HTTPS 服务器? 的相关文章

  • 通过 https 负载均衡器的 WCF http 服务

    我有一个可以通过 http 端点访问的 WCF Web 服务 现在 该服务应通过 https 与负载均衡器一起发布 客户端是通过 svcutil exe 在 Net 中创建的 但 Java 客户端也需要 WSDL 我的理解是 Web 服务在
  • .NET 中有什么方法可以以编程方式侦听 HTTP 流量吗?

    我正在使用浏览器自动化来测试网站 但我需要验证来自浏览器的 HTTP 请求 即图像 外部脚本 XmlHttpRequest 对象 有没有一种方法可以以编程方式实例化代理以供浏览器使用以查看其发送的内容 我已经在使用 Fiddler 来监视流
  • 将 boost::assign 与嵌套在 std::map 内的 std::set 一起使用

    我正在尝试使用boost assign模拟 C 11 的初始化std map含有一个std set include
  • boost::make_zip_iterator 的 decltype?

    我有以下代码 std vector
  • Boost 文件系统非常慢?

    我目前正在学习 Boost 框架 并且我已经找到了如何列出系统上的所有文件夹和文件 使用 include
  • AWS ACM 证书管理 删除正在使用的证书

    我想删除 AWS Certificate Manager 中正在使用的 AWS 证书 为此 我使用建议的 AWS CLI 和以下命令 aws iam delete server certificate server certificate
  • 如何使用 python 日志记录的 SMTPHandler 和 SSL 发送电子邮件

    我正在开发一个烧瓶应用程序 我想在其中将错误级别日志记录发送到电子邮件地址 我尝试设置典型的错误处理程序 mail handler SMTPHandler mailhost app config MAIL SERVER app config
  • 如何让 Sinatra 通过 HTTPS/SSL 工作?

    正如标题所示 谷歌没有提供任何与此相关的有用信息 如何为 Sinatra 应用程序设置和配置 HTTPS SSL 如何创建 HTTPS 路由 我以前从未在我的应用程序中使用过 HTTPS 也没有调整 Rack 其他内容的经验 所以我很欣赏详
  • 使用 urllib 下载 HTTPS 页面,错误:14077438:SSL 例程:SSL23_GET_SERVER_HELLO:tlsv1 警报内部错误

    我正在使用最新的Kubuntu with Python 2 7 6 我尝试下载一个https使用以下代码的页面 import urllib2 hdr User Agent Mozilla 5 0 X11 Linux x86 64 Apple
  • Android 2.3.4 SSL问题

    升级到 Android 2 3 4 后 出现以下异常 javax net ssl SSLException Read error ssl 0x I O error during system call Connection timed ou
  • HTTP:为什么在 get 请求中发送用户名和密码是错误的?

    一般做法是 当您登录或执行其他需要您的用户名和密码的操作时 您将其发送到发布请求的正文中 此外 为了增加安全性 应使用 https 在 get 请求中 这些参数作为 URL 的一部分发送 但据我了解 在 https 中 正文和标头都是加密的
  • 从 HTTP 登录到 HTTPS

    我的网站默认使用 HTTP 我确实有一个启用 HTTPS 的证书 但只有其上的某些区域强制建立安全连接 登录是通过 Ajax 处理的 我想开始使用 SSL 即使请求来自 HTTP 我尝试强制请求的地址具有 HTTPS 并且它完美地回复 然而
  • 将混合内容重定向到 HTTPS 的正确 htaccess 规则是什么

    当通过 HTTPS 访问网站时 是否有一种方法可以使用 htaccess 重定向条件和重定向来捕获通过 HTTP 调用的内容 如果通过 HTTPS 访问网站 http 内容将被重定向到 https 等效 url 本质上 当我的网站通过 HT
  • 使用 Boost::Spirit 解析 time_period 表达式

    我需要使用 Boost Spirit 解析以下 EBNF 表达式 period date part time part date part time part time part hours minutes seconds date par
  • 通过插件管理器在 Notepad++ 中配置代理设置

    我想在 Notepad 中配置代理设置 以允许通过代理从互联网下载 在从网上搜索如何执行此操作后 我了解到我需要通过 设置 按钮在插件管理器中执行此操作 当我转到插件 gt 插件管理器 gt 显示插件管理器 gt 设置时 我看到下面的对话框
  • 如何使环境变量可用于 docker-compose 中的 Docker RUN 命令?

    我有一个 Dockerized 应用程序 我想在代理和非代理主机环境中运行 我试图通过将普通环境变量 例如 http proxy 复制到容器中 当且仅当它们存在于主机中时 来解决此问题 我可以通过跑步完成 90 的任务 set grep i
  • HttpClient SSLException

    我尝试向 Web 服务发送 https 请求 经过几次成功的尝试后 我开始不断收到此错误 这个错误是什么意思 为什么它第一次发生 javax net ssl SSLException java lang RuntimeException C
  • 如何在 64 位中构建 Boost 1.64?

    我运行的是 Windows 10 并在我的笔记本电脑上安装了 Visual Studio 2017 Community Edition 我有一些旧程序在 64 位 Boost 1 62 0 的 VS 2015 中编译得很好 由于一些非常奇怪
  • ApiGee OAUTH 授权

    我是 Apigee 的新手 我需要在代理中进行标注以从谷歌融合表中获取数据 FT 服务要求使用誓言 2 0 进行安全呼叫 我已经使用自定义代理创建了此工作流程 没有任何 OAUTH 策略 并在键值映射中存储令牌 刷新令牌和过期时间 我还制作
  • 从 WildFly 安全地调用 EJB

    我正在尝试以企业 业务 方式重写我的旧应用程序 因此 我有一个带有登录模块的 Swing 客户端和从头开始创建的我自己的服务器 客户端使用ssl证书加密与服务器的TCP连接 我检查服务器上的客户端证书和客户端上的服务器证书 然后服务器使用数

随机推荐

  • Gradle 在 Android Studio 中应用插件(导航栏的 safeargs)

    我正在尝试学习 Android studio 并遵循官方教程 但在有关 Gradle 的部分遇到了障碍 因为该指南似乎已经过时了 指南是here https developer android com codelabs build your
  • 寻找 Dagger 辅助注射的示例

    From 匕首讨论 https groups google com forum topic dagger discuss QgnvmZ dH9c 我有一个类 它从对象图中获取一些依赖项 并在运行时从调用者获取其他依赖项 public cla
  • 如何使用手写笔在 HTML5 画布上绘图

    我使用 onmousedown onmousemove 和 onmouseup 事件在 HTML5 画布对象上使用 JavaScript 进行绘制 一切正常 现在我想用手写笔替换鼠标 Wacom Intuos Pro 因此我用 onpoin
  • 如何检查 Node.js 中是否设置了环境变量?

    我想检查我的环境变量是否设置快递JS https www npmjs com package express服务器并根据是否设置执行不同的操作 我试过这个 if process env MYKEY undefined console log
  • 显示选定的文件而不回发

    我有一个
  • 应用程序启动计数

    我正在开发一个应用程序 其中用户打开该应用程序 5 次后 在第 6 次尝试时 该应用程序应该询问用户的反馈 我尝试使用活动OnStart OnResume 但它不起作用 因为即使在离开并重新进入活动之后 这些方法也会被调用 另外 根据 An
  • 使用 VBA 设置 Sharepoint 标签/属性

    是否可以使用 VBA 设置 Sharepoint 文档 特别是 Excel 的标签 目前我知道处理此问题的唯一方法是将文件保存到 Sharepoint 在出现提示时设置标签 然后再次下载该文件并将其用作模板 然而 我需要使用这些标签的几种不
  • 如何裁剪图像的任意选定区域并将其保存到服务器?

    我用一张图来总结一下这个场景 我正在尝试在我的网站中创建一个设置个人资料图片的功能 我想要一个页面在图像字段中以原始尺寸显示上传的图像 但个人资料图片的大小应该是 200 153 所以我想要用户可以调整图片大小 也可以将一个框架 框架大小为
  • Asp.Net Web 服务:我想返回错误 403 禁止

    我有一个用 c asp net 编程的网络服务 WebService Namespace http example com WebServiceBinding ConformsTo WsiProfiles BasicProfile1 1 S
  • 如何在 Windows 7 中模拟内存不足的情况

    我有一个用 C 编写的应用程序 运行良好 但有时在现场会出现错误 我们认为这些错误是由于内存不足或与垃圾收集器的交互造成的 如果有人感兴趣 这里有描述 无法将 NHibernate Impl ExpandedQueryExpression
  • 字符集和排序规则到底是什么意思?

    我可以阅读MySQL文档而且非常清楚 但是 如何决定使用哪种字符集呢 校对对什么数据有影响 我要求解释这两者以及如何选择它们 来自 MySQLdocs http dev mysql com doc refman 5 0 en charset
  • 为什么 mmap 在 iOS 上失败?

    我正在尝试使用 mmap 在 iOS 上读取和播放音频文件 它适用于最大约 400MB 的文件 但当我尝试 500MB 文件时 出现 ENOMEM 错误 char path NSBundle mainBundle pathForResour
  • 如何在android studio中使用maven

    我想用底部栏 https github com roughike BottomBar我的项目中的库 当我添加正确的gradle命令在build gradle文件和sync 我收到此错误 Failed to resolve com rough
  • MediaStream 未处理的承诺拒绝:[object DOMError](在 Safari 11 中)

    在下面初始化 WebRTC 的方法中 我在 Safari Tech Preview 11 中遇到了未处理的承诺拒绝 具体来说 当我分配MediaStream像这样的视频元素 video srcObject event stream 堆栈跟踪
  • C++ 递归变量

    我想我的问题真的很简单 但我现在尝试解决它几个小时 但我似乎不明白 我有一个 ast 树 用 boost library 创建 并通过递归迭代它 我将所有节点保存在 NodeDescriptions 列表中 其中包含实际节点的编号 实际节点
  • 如何在 Rails 2 中正确使用 OmniAuth

    我正在尝试为我的应用程序使用 OmniAuth 0 2 6 策略 架构为 Rails 2 3 10 Rack 版本为 1 1 OmniAuth 需要此版本或更高版本 出现的问题是 Rails 无法识别我重定向到 auth provider
  • python字典应该如何存储在pytables中?

    pytables 本身不支持 python 字典 我处理它的方法是创建以下形式的数据结构 tables dict key tables StringCol itemsize 40 value tables Int32Col 请注意 我确保键
  • 如何检测C中的ESC键?

    我写了一段代码来检测箭头键使用 getch 我也希望检测 esc 键 但我实际上不知道我应该使用哪些数字 因此不胜感激 include
  • 当我使用 yymore() 时,在 EOF 处出现 Flex 错误“缓冲区末尾丢失”

    我正在编写一个 Flex 程序来处理字符串常量 当输入文件在字符串中遇到 EOF 时 我想返回一个 ERROR 标记 文件遇到 EOF 并打印 ERROR 后出现以下错误 致命的 Flex 扫描仪内部错误 缓冲区末尾丢失 这是我的代码 可以
  • 如何使用代理将 boost::asio 连接到 HTTPS 服务器?

    在我们的应用程序中 我们使用 boost asio 来使用 HTTP 和 HTTPS 进行连接 我们还可以使用 HTTP 代理 现在我需要使用代理添加对 HTTPS 服务器的支持 我研究了相当多的样本 发现所需的步骤似乎是 创建到代理的 H