首先,我确实搜索了我的问题,但要找到这个主题的答案并不容易。
我写了一个小的C ++程序,它通过SOCKS5代理连接到HTTP网站。这一切都运作良好。现在我想连接到一个HTTPS网站,这会造成一些麻烦......
问题是我无法直接创建BIO *并连接到SOCKS5代理,我需要首先使用未加密的套接字执行SOCKS5协议,然后将其转换为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;
}
之后我可以读/写袜子,我不想发布所有的子功能因为它太多了......
我在这里读到:Link 1我应该使用BIO_new_socket()
和SSL_set_bio()
我在这里找到了代码剪辑:Link 2
所以这是我当前的代码被剪切,尝试将TCP Socket转换为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()将打印出来&lt;错误时为0,否则发送字节。这是我的输出:
[i] Version match!
[i] Connection success!
[i] SSL Write: 191
F
而不是'F'我应该在那里看到HTML源代码或HTTP响应。我很确定我在创建BIO *时做了一些虚假的事情,但我不知道是什么。这里的任何人都可以吗?
答案 0 :(得分:1)
您所要求的与其他需要开始未加密然后再升级到SSL / TLS的情况没有什么不同,例如SMTP上的STARTTLS
。所以,是的,有很多方法可以通过OpenSSL的BIO API实现这一目标。
OpenSSL有自己的SSL_write()
和SSL_read()
函数,期望SSL*
作为输入。您正在调用以SSL_write()
作为输入的SSL_read()
和BIO*
函数,并且正在直接读取/写入std::string
值。因此,您已经使用自定义函数明显重载了本机函数。而且你传递BIO*
的事实让我认为你可能会在这些函数中调用BIO_write()
和BIO_read()
。使用SSL_set_bio()
时,您需要使用原生SSL_write()
和SSL_read()
函数直接使用SSL*
进行读/写。在内部,他们将根据需要使用关联的BIO*
作为较低级别的套接字I / O.
话虽如此,虽然上述方法有效,但它也不是在这种情况下使用BIO API的唯一方法。另一种方法是使用BIO_new_ssl_connect()
创建一个BIO
链,其中包含链接在一起的SSL / TLS BIO
和套接字连接BIO
。调用BIO_do_connect()
连接到SOCKS代理,然后使用BIO_find_type(BIO_TYPE_SOCKET)
从链中检索套接字BIO*
,并使用BIO_read()
和BIO_write()
执行未加密SOCKS I / O根据需要。准备就绪后,在SSL / TLS BIO_do_handshake()
上调用BIO*
以启动SSL / TLS握手(将通过已连接的套接字BIO*
),然后使用{{1}并且SSL / TLS BIO_read()
上的BIO_write()
和BIO*
可以根据需要执行加密I / O.
答案 1 :(得分:-2)
简短回答:不要使用OpenSSL BIO,而是使用libcurl。