【问题标题】:"tlsv1 alert unknown ca" when creating server with OpenSSL API使用 OpenSSL API 创建服务器时出现“tlsv1 alert unknown ca”
【发布时间】:2021-09-27 13:02:29
【问题描述】:

我正在使用 C 语言中的 OpenSSL API 创建一个 Web 服务器,一切正常,我可以通过浏览器访问我的网站,但是当我在 Discord 上共享链接时,我收到了以下错误消息: 1568:error:14094418:SSL routines:ssl3_read_bytes:tlsv1 alert unknown ca:ssl\record\rec_layer_s3.c:1544:SSL alert number 48

我想要的是 Discord 集成显示链接的预览,如下所示:Discord integration example

这就是我所做的:

#define CA_CERT_FILE     "cacert.pem"
#define SERVER_CERT_FILE "cert.pem"
#define SERVER_KEY_FILE  "key.pem"

SSL_CTX *create_context() {
    SSL_CTX *ctx = SSL_CTX_new(SSLv23_server_method());
    if(!ctx) {
        wprintf(L"Unable to create SSL context");
        ERR_print_errors_fp(stderr);
        exit(EXIT_FAILURE);
    }

    SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); //Tested with a callback function that return 1, still not work
    SSL_CTX_set_verify_depth(ctx, 4);
    SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION);
    SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(CA_CERT_FILE));

    if(!SSL_CTX_load_verify_locations(ctx, CA_CERT_FILE, NULL)) {
        printf("SSL_CTX_load_verify_locations error!\n");
        ERR_print_errors_fp(stderr);
        exit(EXIT_FAILURE);
    }

    if(SSL_CTX_use_certificate_file(ctx, SERVER_CERT_FILE, SSL_FILETYPE_PEM) <= 0) {
        printf("SSL_CTX_use_certificate_file error!\n");
        ERR_print_errors_fp(stderr);
        exit(EXIT_FAILURE);
    }

    if(SSL_CTX_use_PrivateKey_file(ctx, SERVER_KEY_FILE, SSL_FILETYPE_PEM) <= 0) {
        printf("SSL_CTX_use_PrivateKey_file error!\n");
        ERR_print_errors_fp(stderr);
        exit(EXIT_FAILURE);
    }

    if(!SSL_CTX_check_private_key(ctx)) {
        printf("SSL_CTX_check_private_key error!\n");
        ERR_print_errors_fp(stderr);
        exit(EXIT_FAILURE);
    }

    return ctx;
}

【问题讨论】:

    标签: c ssl server openssl


    【解决方案1】:
    if(SSL_CTX_use_certificate_file(ctx, SERVER_CERT_FILE, SSL_FILETYPE_PEM) <= 0) {
      ...
    

    这仅设置服务器证书,但不设置任何中间证书。我认为可以假设您使用的是公开颁发的证书(例如来自 Let's Encrypt),在这种情况下,很可能有一个(或多个)中间证书需要与服务器证书一起发送,以便 TLS client can build the trust chain to the locally trusted root certificate.

    如果由于无法建立信任链而导致证书验证失败,客户端可能会生成类似 unknown ca 的 TLS 警报并关闭连接。这个收到的 TLS 警报是您当前在服务器端看到的。

    如果缺少这些中间证书,一些 TLS 客户端将解决此错误配置并自行填写缺少的中间证书。但这通常只由浏览器完成,而不是由 Python、Java、C 等编程语言中的 TLS 堆栈完成。因此,您的服务器可能在浏览器中工作,但在被不同的 TLS 客户端访问时无法工作,即使两者都使用同一组受信任的根证书。

    解决方法是发送中间证书。这可以通过将服务器证书和中间体(按此顺序)放在同一个文件中并使用SSL_CTX_use_certificate_chain_file 而不是SSL_CTX_use_certificate_file 来完成。


    除此之外,不知道您的代码为何要求提供客户端证书。 Discord 很可能无法向您发送或无法发送您期望的,这可能会导致其他问题。可能是您只是从某个地方复制了代码并且不明白它在做什么,但它是这些行:

    SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); //Tested with a callback function that return 1, still not work
    SSL_CTX_set_verify_depth(ctx, 4);
    ...
    SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(CA_CERT_FILE));
    

    【讨论】:

      猜你喜欢
      • 2021-07-21
      • 2017-09-29
      • 2013-06-30
      • 2022-10-12
      • 2018-04-05
      • 1970-01-01
      • 2017-05-18
      • 2013-03-04
      • 1970-01-01
      相关资源
      最近更新 更多