SSL3_READ_BYTES:tlsv1 警报内部错误,安全套接字,OpenSSL,C,获取 HTTPS 页面

新手上路,请多包涵

我想写一个简单的应用程序,它抓取 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);

它有效。但是,当使用安全套接字( #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;
}

原文由 Katie 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.5k
1 个回答

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);

原文由 Steffen Ullrich 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题