PG数据库中SSL那些事
在当今这个数据安全至关重要的时代,数据库的加密连接已成为保护数据传输安全的常规手段。PostgreSQL数据库作为一个功能强大的开源数据库系统,提供了SSL(Secure Sockets Layer)支持来确保数据在客户端和服务器之间的安全传输。本文将探讨PostgreSQL中SSL的使用和配置,以及如何通过SSL加强数据库的安全性。
配置PG以使用SSL
首先,要在PostgreSQL中启用SSL,需要在编译安装阶段通过特定的配置选项来指定。
./configure --with-openssl
从 PG 14 开始,引入新选项--with-ssl=LIBRARY来指定SSL类库,不过到目前为止仍然只支持 OpenSSL,所以习惯上依旧使用 --with-openssl 兼容选项。
如果编译阶段未指定SSL,后期在开启时会遇到报错。
[postgres@pg16 ~]$ psql
psql (16.4-ShawnYan)
Type "help" for help.
postgres=# alter system set ssl = on ;
ERROR: SSL is not supported by this build
生成SSL证书和密钥
在启用SSL之前,需要生成SSL证书和私钥。通过openssl命令行工具,我们可以创建自签名的根证书和服务器证书。可以通过如下命令生成服务器证书postgresql.crt和私钥postgresql.key,以及根证书root.crt和相应的私钥root.key。生成这些文件后,需要确保私钥文件的权限设置正确,以防止未授权访问。
openssl req -new -x509 -days 365 -nodes -text -out postgresql.crt \
-keyout postgresql.key -subj "/CN=pg16.shawnyan.cn"
chmod og-rwx postgresql.key
openssl req -new -nodes -text -out root.csr \
-keyout root.key -subj "/CN=pg16.shawnyan.com"
chmod og-rwx root.key
openssl x509 -req -in root.csr -text -days 3650 \
-signkey root.key -out root.crt
openssl req -new -nodes -text -out postgresql.csr \
-keyout postgresql.key -subj "/CN=pg16.shawnyan.com"
chmod og-rwx postgresql.key
openssl x509 -req -in postgresql.csr -text -days 365 \
-CA root.crt -CAkey root.key -CAcreateserial \
-out postgresql.crt
修改配置文件
生成SSL证书和密钥后,需要在PostgreSQL的配置文件中指定这些文件的位置。修改postgresql.conf文件,设置ssl_cert_file和ssl_key_file参数指向相应的证书和密钥文件。
[postgres@pg16 data]$ grep '^ssl' postgresql.conf
ssl = on
ssl_cert_file = 'postgresql.crt'
ssl_key_file = 'postgresql.key'
连接数据库时使用SSL
在客户端连接数据库时,可以通过指定连接字符串中的sslmode参数来要求SSL连接。
如下,使用psql命令行工具连接数据库时,通过sslmode=require参数确保了SSL加密连接的建立。
[postgres@pg16 ~]$ psql postgresql://127.1:5432/postgres?sslmode=require
psql (16.4-ShawnYan)
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
Type "help" for help.
postgres=# \conninfo
You are connected to database "postgres" as user "postgres" on host "127.1" (address "127.0.0.1") at port "5432".
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
postgres=#
也可,在命令行中重新建立带有SSL加密的连接。
[postgres@pg16 ~]$ psql
psql (16.4-ShawnYan)
Type "help" for help.
postgres=# \c "host=127.1 sslmode=require"
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
You are now connected to database "postgres" as user "postgres" on host "127.1" (address "127.0.0.1") at port "5432".
postgres=# \conninfo
You are connected to database "postgres" as user "postgres" on host "127.1" (address "127.0.0.1") at port "5432".
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
postgres=#
TLS 版本
在 CentOS 7 中,默认安装的 OpenSSL 版本为 1.0.2,该版本最高支持 TLSv1.2 版本。
对于新环境,推荐使用 Rocky Linux 9.4 系统,默认安装的是 OpenSSL 3.0 版本,支持 TLS v1.3 版本,可以获得更高的安全性和性能。
[postgres@pg16 ~]$ cat /etc/redhat-release
Rocky Linux release 9.4 (Blue Onyx)
[postgres@pg16 ~]$ openssl version
OpenSSL 3.0.7 1 Nov 2022 (Library: OpenSSL 3.0.7 1 Nov 2022)
在 PG 中可以通过参数 ssl_max_protocol_version / ssl_min_protocol_version 控制 TLS 协议版本。
例如,指定最大版本为 TLSv1.2。
postgres=# show ssl_max_protocol_version ;
ssl_max_protocol_version
--------------------------
(1 row)
postgres=# \c "host=127.1 sslmode=require"
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
You are now connected to database "postgres" as user "postgres" on host "127.1" (address "127.0.0.1") at port "5432".
postgres=# alter system set ssl_max_protocol_version = 'TLSv1.2';
ALTER SYSTEM
postgres=# \c "host=127.1 sslmode=require"
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, compression: off)
You are now connected to database "postgres" as user "postgres" on host "127.1" (address "127.0.0.1") at port "5432".
postgres=#
可以看到新建连接的协议版本为 TLSv1.2。
实践案例
在实际案例中,我们可以在PG数据库服务器端允许客户端自由选择 TLSv1.2 或者 TLSv1.3 版本。
比如,在 Java 代码实现中可以通过客户端属性进行控制。
TLSv1.2:
[postgres@pg16 ~]$ java -Djdk.tls.client.protocols=TLSv1.2 -cp .:postgresql-42.7.3.jar Main
Java Version: 1.8.0_422 (Red Hat, Inc.)
Driver: PostgreSQL JDBC Driver 42.7.3
Database: PostgreSQL 16.4-ShawnYan
Pid: 68698, UserName: postgres, DbName: postgres, State: active, Ssl: t, Version: TLSv1.2, Cipher: ECDHE-RSA-AES256-GCM-SHA384
TLSv1.3:
[postgres@pg16 ~]$ java -Djdk.tls.client.protocols=TLSv1.3 -cp .:postgresql-42.7.3.jar Main
Java Version: 1.8.0_422 (Red Hat, Inc.)
Driver: PostgreSQL JDBC Driver 42.7.3
Database: PostgreSQL 16.4-ShawnYan
Pid: 68716, UserName: postgres, DbName: postgres, State: active, Ssl: t, Version: TLSv1.3, Cipher: TLS_AES_256_GCM_SHA384
监控SSL连接
PostgreSQL提供了pg_stat_ssl系统视图,允许管理员监控当前的SSL连接状态。通过查询这个视图,可以获得关于SSL连接的详细信息,如协议版本、密码套件等。这有助于了解数据库的SSL使用情况,并收集当前加密连接的使用情况。
postgres=# table pg_stat_ssl;
pid | ssl | version | cipher | bits | client_dn | client_serial | issuer_dn
-------+-----+---------+------------------------+------+-----------+---------------+-----------
67602 | t | TLSv1.3 | TLS_AES_256_GCM_SHA384 | 256 | | |
(1 row)
小结
通过上述步骤,我们可以看到PostgreSQL中SSL的配置和使用是一个涉及多个步骤的过程。从编译安装阶段的配置选项,到生成SSL证书和密钥,再到配置数据库和监控SSL连接,每一步都至关重要。
更多PG新特性可参阅图书《快速掌握PostgreSQL版本新特性》
🌻 往期精彩 ▼
- [Oracle]
- [MySQL]
- [TiDB]
- [PG]
– / END / –
👉 这里可以找到我
如果这篇文章为你带来了灵感或启发,就请帮忙点『赞』or『在看』or『转发』吧,感谢!ღ( ´・ᴗ・` )~




