C++ 将 TCP 套接字转换为 BIO (OpenSSL)

标签 c++ sockets ssl openssl

首先,我确实搜索了我的问题,但要准确找到该主题的答案并不容易。

我编写了一个小型 C++ 程序,通过 SOCKS5 代理连接到 HTTP 网站。这一切都很好。现在我想连接到一个 HTTPS 网站,这引起了一些麻烦..

问题是我无法直接创建 BIO* 并连接到 SOCKS5 代理,我需要先使用未加密的套接字执行 SOCKS5 协议(protocol),然后将其转换为 BIO*。我这样做对吗?

所以我为正常的 TCP->SOCKS5-> 网站内容截取了这段代码:

SOCKS5_Greeting_Response socks_gresp;
SOCKS5_Command_Response socks_cresp;
int sock = createSocket();

socketConnect(sock, "127.0.0.1", 9050);

socks_gresp = socketWriteSOCKS5Greeting_TOR(sock);

if(socks_gresp.Version == 5){

    std::cout << "[i] Version match!" << std::endl;

}

socks_cresp = SOCKS5_Connect(sock, get_IPv4("www.google.de"), 80);

if(socks_cresp.Reply == 0){

    std::cout << "[i] Connection success!" << std::endl;

}
else if(socks_cresp.Reply == 1){

    std::cout << "[i] General server error" << std::endl;

}
else if(socks_cresp.Reply == 3){

    std::cout << "[i] Network not reachable" << std::endl;

}
else if(socks_cresp.Reply == 5){

    std::cout << "[i] Connection refused!" << std::endl;

}

在那之后我可以读/写 socks ,我不想发布所有的子功能,因为它太多了......

好吧,我在这里阅读:Link 1我应该使用 BIO_new_socket()SSL_set_bio() 我在这里找到了一段代码:Link 2

所以这里是我当前的代码片段,试图将 TCP 套接字转换为 BIO*(没有所有错误处理的东西,我在一切正常时包括它):

SSL_library_init();

SOCKS5_Greeting_Response socks_gresp;
SOCKS5_Command_Response socks_cresp;
int sock = createSocket();

socketConnect(sock, "127.0.0.1", 9050);

socks_gresp = socketWriteSOCKS5Greeting_TOR(sock);

if(socks_gresp.Version == 5){

    std::cout << "[i] Version match!" << std::endl;

}

socks_cresp = SOCKS5_Connect(sock, get_IPv4("www.google.de"), 443);

if(socks_cresp.Reply == 0){

    std::cout << "[i] Connection success!" << std::endl;

}
else if(socks_cresp.Reply == 1){

    std::cout << "[i] General server error" << std::endl;

}
else if(socks_cresp.Reply == 3){

    std::cout << "[i] Network not reachable" << std::endl;

}
else if(socks_cresp.Reply == 5){

    std::cout << "[i] Connection refused!" << std::endl;

}

//--

BIO* sslsock = BIO_new_socket(sock, BIO_NOCLOSE);
SSL_CTX * ctx = SSL_CTX_new(SSLv23_client_method());
SSL_CTX_load_verify_locations(ctx, "/path/to/cacert.pem", NULL);
SSL* ssl = SSL_new(ctx);

SSL_set_bio(ssl, sslsock, sslsock);

std::cout << "[i] SSL Write: " << SSL_write(sslsock, generate_basic_GET_request("www.google.de","Mozilla","")) << std::endl;

std::cout << SSL_read(sslsock) << std::endl;

SSL_Close_Connection(sslsock);

//--

closeSocket(sock);

我的 SSL_write() 将在错误时打印出 < 0,否则将发送字节。这是我的输出:

[i] Version match!
[i] Connection success!
[i] SSL Write: 191
F

我应该在那里看到 HTML 源代码或 HTTP 响应,而不是“F”。我很确定我在创建 BIO* 时做了一些错误的事情,但我不知道是什么。这里有人可以吗?

最佳答案

您所要求的与其他需要以未加密方式开始然后稍后升级到 SSL/TLS 的情况没有什么不同,例如 SMTP 上的 STARTTLS。所以是的,有一些方法可以使用 OpenSSL 的 BIO API 来实现。

OpenSSL 有它自己的 SSL_write()SSL_read() 函数,需要 SSL* 作为输入。您正在调用以 BIO* 作为输入的 SSL_write()SSL_read() 函数,并且正在读取/写入 std: :string 值直接。所以你显然已经用自定义函数重载了 native 函数。事实上,您正在传递一个 BIO* 让我认为您可能在这些函数中调用了 BIO_write()BIO_read() .使用SSL_set_bio()时,需要使用原生的SSL_write()SSL_read()函数,直接用进行读写>SSL*。在内部,它们将根据需要将关联的 BIO* 用于较低级别的套接字 I/O。

话虽如此,虽然上述方法可行,但它也不是针对这种情况使用 BIO API 的唯一方法。另一种方法是使用 BIO_new_ssl_connect() 创建一个由 SSL/TLS BIO 和套接字连接 组成的 BIO 链BIO链接在一起。调用 BIO_do_connect() 连接到 SOCKS 代理,然后使用 BIO_find_type(BIO_TYPE_SOCKET) 从链中检索套接字 BIO* 并使用 BIO_read()BIO_write() 以根据需要执行未加密的 SOCKS I/O。准备就绪后,调用 SSL/TLS BIO* 上的 BIO_do_handshake() 以启动 SSL/TLS 握手(这将通过已连接的套接字 BIO* ),然后在SSL/TLS BIO*上使用BIO_read()BIO_write()进行加密I/O根据需要。

关于C++ 将 TCP 套接字转换为 BIO (OpenSSL),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35209767/

相关文章:

c++ - 在 native Windows 应用程序的资源中嵌入文本文件

c - 接收网站的简单套接字程序(断言错误)

Android 在测试期间信任自签名证书

java - Apache tomcat : Importing already existing certificates into keystore

ssl - React-native websocket TLS 连接

c++ - 如何仅在输入变量后而不是立即开始使用 getline?

c++ - 使用检测惯用法来确定类型是否具有带有特定签名的构造函数

c++ - 将 Stack.top() 添加到 vector 中?

sockets - UDP 正在向数据报的末尾添加字节?

javascript - Python Web 服务器 HTML 渲染