Kat*_*tie 4 c++ sockets openssl
我想编写一个简单的应用程序,它抓取 HTTPS 页面的内容:https://httpbin.org/html。
我知道如何访问它的不安全(HTTP)版本(http://httpbin.org/html),我只需要使用套接字发送一个请求:
std::stringstream ss;
ss << "GET /html HTTP/1.1" << "\r\n"
<< "Host: httpbin.org\r\n"
<< "Connection: close"
<< "\r\n\r\n";
std::string request = ss.str();
// socket creation, connect
send(sock, request.c_str(), request.size(), 0);
Run Code Online (Sandbox Code Playgroud)
它有效。但是,在使用安全套接字 ( #include <openssl/ssl.h>) 时出现以下错误:error:14094438:SSL routines:SSL3_READ_BYTES:tlsv1 alert internal error尝试时result = SSL_connect(ssl);
这是代码:
#include <sys/stat.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <string>
#include <iostream>
#include <sstream>
int main(int argc, char **argv)
{
int sock;
char buff[1024];
struct sockaddr_in address;
struct hostent *host = NULL;
std::string servername = "httpbin.org";
if (!inet_aton(servername.c_str(), &address.sin_addr))
if (host = gethostbyname(servername.c_str()))
address.sin_addr = *(struct in_addr*)host->h_addr;
else
return -1;
address.sin_port = htons(443);
address.sin_family = AF_INET;
std::stringstream ss;
ss << "GET /html HTTP/1.1" << "\r\n"
<< "Host: httpbin.org\r\n"
<< "Connection: close"
<< "\r\n\r\n";
std::string request = ss.str();
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) != -1)
{
if (connect(sock, (struct sockaddr *)&address, sizeof(struct sockaddr_in)) != -1)
{
SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
SSL_CTX *ctx = SSL_CTX_new(TLSv1_2_method());
if (!ctx)
return -1;
int result = -1;
SSL *ssl = SSL_new(ctx);
SSL_set_fd(ssl, sock);
result = SSL_connect(ssl);
if (result == 0)
{
long error = ERR_get_error();
const char* error_str = ERR_error_string(error, NULL);
printf("%s\n", error_str);
return 0;
}
SSL_write(ssl, request.c_str(), request.size());
SSL_read(ssl, buff, 1024);
printf("%s\n", buff);
memset(buff, 0, 1024);
SSL_free(ssl);
SSL_CTX_free(ctx);
close(sock);
}
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
...
SSL routines:SSL3_READ_BYTES:tlsv1 alert internal error当尝试result = SSL_connect(ssl);
这意味着服务器发送回 TLSv1 警报可能是因为它不喜欢客户端在握手(ClientHello)中发送的信息。这可能是因为客户端只提供服务器不支持的密码,客户端使用的协议版本不受支持,或者经常因为服务器需要TLS SNI 扩展来确定向客户端提供哪个证书。使用其他工具进行测试表明情况确实如此。因此,可以通过使用 SNI 扩展在您的代码中解决该问题:
SSL *ssl = SSL_new(ctx);
SSL_set_fd(ssl, sock);
// ADD THIS
SSL_ctrl(ssl, SSL_CTRL_SET_TLSEXT_HOSTNAME, TLSEXT_NAMETYPE_host_name, (void*)servername.c_str());
result = SSL_connect(ssl);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
13839 次 |
| 最近记录: |