1. 概述
本文将介绍如何设置一个 gdb 调试环境,以深入了解 TLS 连接并更好地理解 PostgreSQL 中使用的 OpenSSL API。
2. 使用调试符号构建 OpenSSL
首先,检出 OpenSSL 源代码并切换到您想要使用的版本。在本例中,我想使用 OpenSSL 3.0.2 版本来编译 PostgreSQL,因此我切换到 openssl-3.0.2 版本标签。
$ git clone https://github.com/openssl/openssl.git
$ cd openssl
$ git checkout openssl-3.0.2复制
接着,使用以下选项编译带有 gdb 调试支持的 OpenSSL:
$ ./config --prefix=/tmp/ssl --openssldir=/tmp/ssl -d shared -g3 -ggdb -fno-inline -O0 -fno-omit-frame-pointer
$ make -j
$ make install复制
编译带有调试符号的 OpenSSL 可能需要一段时间,最好将 prefix 设置为某个路径,这样可以确保该调试版本得以保存并重复使用。
3. 使用调试版 OpenSSL 库编译 PostgreSQL
同样,首先检出 PostgreSQL 源代码并切换到您感兴趣的分支。在本文中,我将使用 master 分支进行演示:
$ git clone https://github.com/postgres/postgres.git
复制
然后,使用启用调试选项的命令编译 PostgreSQL,并特别指定要链接的 OpenSSL 源代码和调试库:
$ ./configure --prefix=/tmp/pgapp --enable-tap-tests --enable-debug CC="gcc -std=gnu99" CFLAGS="-O0 -fno-omit-frame-pointer -I/tmp/openssl/include" LDFLAGS="-Wl,-rpath=/tmp/openssl" --with-openssl
$ make -j
$ make install复制
在这里,必须指定 LDFLAGS="-Wl,-rpath=/tmp/openssl"
,以确保 PostgreSQL 链接到您指定的 OpenSSL 库,否则它将链接到系统的库。为了进一步确认 PostgreSQL 链接的是您想要的 OpenSSL 库,通常可以运行以下命令:
$ which postgres
/tmp/pgapp/bin/postgres
$ ldd tmp/pgapp/bin/postgres
linux-vdso.so.1 (0x00007ffd8a3c1000)
libssl.so.3 => tmp/openssl/libssl.so.3 (0x00007f6878dc6000)
libcrypto.so.3 => tmp/openssl/libcrypto.so.3 (0x00007f6877c00000)
libz.so.1 => lib/x86_64-linux-gnu/libz.so.1 (0x00007f68781cf000)
libm.so.6 => lib/x86_64-linux-gnu/libm.so.6 (0x00007f68780e8000)
libicui18n.so.70 => lib/x86_64-linux-gnu/libicui18n.so.70 (0x00007f6877800000)
libicuuc.so.70 => lib/x86_64-linux-gnu/libicuuc.so.70 (0x00007f6877605000)
libc.so.6 => lib/x86_64-linux-gnu/libc.so.6 (0x00007f6877200000)
lib64/ld-linux-x86-64.so.2 (0x00007f6878e75000)
libstdc++.so.6 => lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f6876e00000)
libgcc_s.so.1 => lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f68780c8000)
libicudata.so.70 => lib/x86_64-linux-gnu/libicudata.so.70 (0x00007f6875000000)复制
在这里,检查 libssl.so.3
和 libcrypto.so.3
库,以确保 PostgreSQL 和 psql 链接的是您期望的 OpenSSL 库。在上面的示例中,我的 PostgreSQL 链接到了刚刚编译并安装的、带有调试符号的 OpenSSL 库。
4. 享受调试
要在 TLS 连接设置或初始化过程中调试 OpenSSL API,您需要一些证书。您可以按照 PostgreSQL 文档(https://www.postgresql.org/docs/current/ssl-tcp.html#SSL-CERTIFICATE-CREATION)设置您自己的证书,或者按照以下步骤使用 SSL 回归测试文件夹下预构建的证书。步骤如下:
$ initdb -D tmp/pgdata
$ cd postgres/src/test/ssl/ssl
$ cp -pr root_ca.crt server-cn-only+server_ca.crt server-cn-only.key tmp/pgdata/
$ chmod 600 tmp/pgdata/server-cn-only.key复制
然后,编辑 postgresql.conf
文件以启用 SSL 并指定证书相关的文件。例如:
$ vim pgdata/postgresql.conf
ssl = on
ssl_ca_file = 'root_ca.crt'
ssl_cert_file = 'server-cn-only+server_ca.crt'
ssl_key_file = 'server-cn-only.key'复制
在这里,启用了 SSL,根 CA 证书指向 root_ca.crt
,并使用实体证书 server-cn-only
和中间 CA server_ca
作为 PostgreSQL 服务器的证书,同时对应的私钥文件也已设置。
现在,我们已经准备好使用 gdb 调试 OpenSSL API。
$ gdb -args postgres -D pgdata
...
(gdb) b be_tls_init
Breakpoint 1 at 0x419bf2: file be-secure-openssl.c, line 95.
(gdb) b SSL_CTX_use_certificate_chain_file
Breakpoint 2 at 0xd9970
Breakpoint 1, be_tls_init (isServerStart=true) at be-secure-openssl.c:95
95 int ssl_ver_min = -1;
(gdb) c
Continuing.
Breakpoint 2, SSL_CTX_use_certificate_chain_file (ctx=0x5555561e9ba0, file=0x5555561ddc08 "server-cn-only+server_ca.crt") at ssl/ssl_rsa.c:534
534 return use_certificate_chain_file(ctx, NULL, file);
(gdb) s
use_certificate_chain_file (ctx=0x5555561e9ba0, ssl=0x0, file=0x5555561ddc08 "server-cn-only+server_ca.crt") at ssl/ssl_rsa.c:419
419 {
420 BIO *in;
421 int ret = 0;
422 X509 *x = NULL;
423 pem_password_cb *passwd_callback;
(gdb) l
414 * Read a file that contains our certificate in"PEM" format, possibly
415 * followed by a sequence of CA certificates that should be sent to the peer
416 * in the Certificate message.
417 */
418 static int use_certificate_chain_file(SSL_CTX *ctx, SSL *ssl, const char *file)
419 {
420 BIO *in;
421 int ret = 0;
422 X509 *x = NULL;
423 pem_password_cb *passwd_callback;
(gdb) p file
$2 = 0x5555561ddc08 "server-cn-only+server_ca.crt"
(gdb) pt ctx
type = struct ssl_ctx_st {
OSSL_LIB_CTX *libctx;
const SSL_METHOD *method;
struct stack_st_SSL_CIPHER *cipher_list;
struct stack_st_SSL_CIPHER *cipher_list_by_id;
struct stack_st_SSL_CIPHER *tls13_ciphersuites;
struct x509_store_st *cert_store;复制
在上面的示例中,我启用了两个断点:be_tls_init
和 SSL_CTX_use_certificate_chain_file
。be_tls_init
用来确保 PostgreSQL 已启用调试符号,而 SSL_CTX_use_certificate_chain_file
用来深入分析 OpenSSL。在这里,我们可以输出这个复杂的 ctx
对象作为示例。
通过这个调试环境设置,您应该能够调试 psql 客户端端,深入了解整个 TLS 过程。
5. 总结
在本文中,解释了如何设置一个简单的 gdb 调试环境,以深入了解 OpenSSL,希望它对您有所帮助。
关注公众号,了解更多社区动态
- 推荐阅读 -
深入理解 PostgreSQL Planner:简化扫描路径与查询计划
DeepSeek 加持!IvorySQL 文档智能助手正式上线!
如何利用 PostgreSQL 的 JSONB API 作为扩展的轻量级 JSON 解析器
IvorySQL v4 逻辑复制槽同步功能解析:高可用场景下的数据连续性保障
「2024 年度技术精华盘点」IvorySQL & PostgreSQL 技术干货全解析!
IvorySQL 4.0 之 Invisible Column 功能解析
IvorySQL 4.0 之兼容 Oracle 包功能设计思路解读
IvorySQL 升级指南:从 3.x 到 4.0 的平滑过渡
IvorySQL 4.0 发布:全面支持 PostgreSQL 17
