DEV Community

Michael
Michael

Posted on • Updated on

HTTP3之QUICTLS报错: "unable to get local issuer certificate"

2024-06-06更新

https://github.com/openssl/openssl/issues/9436 有人在OpenSSL仓库提出了这个问题,但是官方也没有时间整这个。

看了评论后,我感觉这个问题确实不是官方的问题,当然是我的观点哈。为什么呢?因为人家仓库默认出来空的,正常,况且那么多平台,每个平台的证书库都不一样,如果随着操作系统迭代,那这个库就有点太不正经了。。。,所以最好是让各个平台自己编译成平台包的时候添加就好,比如我们使用Ubuntu等系统的时候,默认(目录位于/usr/lib/ssl)会跟系统的证书库(/etc/ssl)链接在一起了,这些都是在系统包维护者编译包的时候干的。

https://salsa.debian.org/debian/openssl/-/blob/debian/unstable/debian/rules#L122 这个地址是debian编译OpenSSL使用的rules文件,其中122行明确的新建了软链接到debian平台的官方证书库(/etc/ssl)。

所以如果自己编译certs文件夹是空的,正常,别慌,但是通过问题找到这个问题就已经成功了。。。 :)

背景

最近使用QUICTLS整HTTP3时候,将自签证书加入到系统默认cert store,然后加载默认证书路径时总是报错:

"unable to get local issuer certificate"
Enter fullscreen mode Exit fullscreen mode

QUICTLS在以前文章中介绍过。总的来说,就是为了让OpenSSL支持QUIC协议,基于OpenSSL仓库修改的仓库。系统原本安装了OpenSSL,通过编译QUICTLS后也安装了OpenSSL。注意依赖库时要分清楚使用哪个动态库

本文是在使用QUICTLS动态库时导致的问题,QUICTLS依赖库默认位于/usr/local/lib64,下面代码打印出证书相关默认目录。

// test.c
#include <stdio.h>
#include <openssl/x509.h>

int main()
{
     const char *file_path = X509_get_default_cert_file();
     const char *dir_path = X509_get_default_cert_dir();
     const char *file_env = X509_get_default_cert_file_env();
     const char *file_env = X509_get_default_cert_dir_env();
     printf(format: "file: %s, dir: %s, file_env: %s, dir_env: %s\n", 
          file_path, dir_path, file_env, dir_env);

     return 0;
}
// 打印原生OpenSSL相关证书地址
// gcc -o test test.c -lcrypto && ./test
// file: /usr/lib/ssl/cert.pem, dir: /usr/lib/ssl/certs, file_env: SSL_CERT_FILE, dir_env: SSL_CERT_DIR

// 打印QUICTLS相关证书地址
// gcc -o test test.c -L/usr/local/lib64 -lcrypto && ./test
// file: /usr/local/ssl/cert.pem, dir: /usr/local/ssl/certs, file_env: SSL_CERT_FILE, dir_env: SSL_CERT_DIR
Enter fullscreen mode Exit fullscreen mode

根本原因

根本原因是因为使用quictls后, OpenSSL使用了新的配置目录/usr/local/ssl, 里面只有certs文件夹, 而且里面是空的。

是的,怎么也没有想到是这么回事,就这个问题整了好长时间!!!

在进行证书验证时候, 找不到最终的根证书(找得到才怪), 就会报错: "unable to get local issuer certificate"

解决办法

解决办法是跟原生的OpenSSL目录(/usr/lib/ssl)里面设置的一样就好。

QUICTLS_DIR=/usr/local/ssl
sudo rmdir "$QUICTLS_DIR/certs"
sudo ln -s /etc/ssl/certs "$QUICTLS_DIR/certs"

sudo rmdir "$QUICTLS_DIR/private"
sudo ln -s /etc/ssl/private "$QUICTLS_DIR/private"

sudo rm "$QUICTLS_DIR/openssl.cnf"
sudo ln -s /etc/ssl/openssl.cnf "$QUICTLS_DIR/openssl.cnf"

/usr/local/bin/openssl version -a # QUICTLS的各种配置
openssl version -a # 原生OpenSSL的各种地址, 特别是OPENSSLDIR
Enter fullscreen mode Exit fullscreen mode

另外,openssl命令始终使用原生的, 因为原生是/usr/bin/openssl, QUICTLSopenssl命令位于/usr/local/bin/openssl

Top comments (0)