DEV Community

Michael
Michael

Posted on • Edited 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

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Engage with a sea of insights in this enlightening article, highly esteemed within the encouraging DEV Community. Programmers of every skill level are invited to participate and enrich our shared knowledge.

A simple "thank you" can uplift someone's spirits. Express your appreciation in the comments section!

On DEV, sharing knowledge smooths our journey and strengthens our community bonds. Found this useful? A brief thank you to the author can mean a lot.

Okay