在PostgreSQL中启用SSL非常简单。只需三步,我们就可以通过SSL/TLS使用传输加密来确保与它的连接更加安全:
- 确保我们有可用的服务器证书和密钥文件
- 启用SSL配置(SSL = on)
- 确保pg_hba.conf文件规则相应更新
在本文中,我们将详细介绍这些步骤,还将了解如何检查和验证连接是否确实使用了更安全的SSL协议。
什么是SSL/TLS?
SSL(安全套接字层)是一种加密协议,旨在使两个节点之间的网络通信安全。如果没有某种形式的网络加密,任何可以检查网络数据包的第三方都可以访问客户端和服务器之间发送的数据(在这种情况下,是PostgreSQL数据,这意味着用户、密码,甚至SQL语句)。TLS(传输层安全)是它的更现代的定义,即使SSL已弃用,但仍通常用于命名目的。出于所有意图和目的,我们在这个博客中使用他们作为别名。
PostgreSQL文档页面在这方面为我们提供了更多的见解。如有需要,请咨询使用SSL保护TCP/IP连接和SSL支持条目以获取更多信息。
尝试在没有证书/密钥文件的情况下启用SSL
现在让我们看看当我们试图启用SSL而没有所需的证书和密钥文件时会发生什么:
|
1
2
3.
4
5
6
7
|
postgres=# alter system set ssl=on;
改变
系统
postgres=# select pg_reload_conf()
pg_reload_conf
----------------
t
(
1
行
)
|
我们没有看到任何错误,但是我们真的在使用SSL吗?如果我们检查错误日志,我们确实会看到错误:
|
1
2
3.
4
|
2022-06-23
20.
:
43
:
54.713
UTC
(
5284
]
日志
:
收到了
SIGHUP
,
重新加载
配置
文件
2022-06-23
20.
:
43
:
54.714
UTC
(
5284
]
日志
:
参数
“ssl”
改变了
来
“上”
2022-06-23
20.
:
43
:
54.715
UTC
(
5284
]
日志
:
可以
不
负载
服务器
证书
文件
“server.crt”
:
没有
这样的
文件
或
目录
2022-06-23
20.
:
43
:
54.715
UTC
(
5284
]
日志
:
SSL
配置
是
不
重新加载
|
创建证书
因此,我们首先需要创建前面提到的文件。如果您还没有有效的证书和密钥文件,可以使用下面的openssl命令(这里的重点不是深入研究这部分过程):
|
1
2
3.
4
5
6
7
|
(
根
@
node0
~
]
# CD /var/lib/pgsql/14/data
(
根
@
node0
数据
]
# openssl req -nodes -new -x509 -keyout服务器。密钥输出服务器。crt -subj '/C=US/L=NYC/O=雷竞技下载官网Percona/CN=postgres'
生成
一个
2048
位
RSA
私人
关键
。
。
。
。+++
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。
。+++
写作
新
私人
关键
来
“server.key”
-----
|
我们已经将当前的工作目录更改为PostgreSQL数据目录,因为我们是在基于rhel的系统中。如果你使用的是基于debian的系统,你应该将文件存储在/etc/ssl/certs/和/etc/ssl/private/或定义/检查ssl_cert_file和ssl_key_filePostgreSQL配置变量。同时,确保postgres用户拥有它们,并且它们只对postgres用户可读:
|
1
2
3.
4
5
|
(
根
@
node0
数据
]
# chmod 400 server.{crt,key}
(
根
@
node0
数据
]
# chown postgres:postgres server.{crt,key}
(
根
@
node0
数据
]
# ll server.{crt,key}
-r--------。
1
postgres
postgres
1212
小君
23
20.
:
49
服务器
.crt
-r--------。
1
postgres
postgres
1704
小君
23
20.
:
49
服务器
。key
|
启用SSL / TLS
现在我们可以启用SSL并重新加载配置;这次没有显示错误:
|
1
2
3.
4
5
6
7
|
postgres=# alter system set ssl=on;
改变
系统
postgres=# select pg_reload_conf()
pg_reload_conf
----------------
t
(
1
行
)
|
|
1
2
|
2022-06-23
20.
:
52
:
05.823
UTC
(
5284
]
日志
:
收到了
SIGHUP
,
重新加载
配置
文件
2022-06-23
20.
:
52
:
05.823
UTC
(
5284
]
日志
:
参数
“ssl”
改变了
来
“上”
|
到目前为止,我们已经启用了SSL,但是除非修改pg_hba.conf文件,否则这些设置不会应用于任何用户(至少不会以强制的方式应用)。这是第一步,可以给我们一个错误的安全感,所以让我们继续,看看如何解决它。
执行SSL / TLS
如前所述,pg_hba.conf文件是我们可以调整使用SSL需要哪些连接的地方。我们可以指示PostgreSQL使用hostssl"关键字代替平原"宿主”一个。请注意,此时您可以看到一些连接开始使用SSL,因为普通的“宿主关键字将允许希望使用SSL的连接使用它。然而,事实并非如此执行使用SSL(即:如果客户端不想使用SSL, PostgreSQL将不会拒绝连接)。
我们假设这是pg_hba.conf到目前为止我们一直在使用的文件:
|
1
2
3.
4
5
6
|
#类型数据库用户地址方法
当地的
所有
所有
同行
宿主
所有
所有
127.0.0.1/32
急停-沙-256
宿主
所有
所有
:
:
1/128
急停-沙-256
宿主
所有
所有
0.0.0.0/0
md5
宿主
复制
所有
10.124.33.113/24
md5
|
我们希望从所有远程用户(也包括远程复制连接)强制SSL连接:
|
1
2
3.
4
5
6
|
#类型数据库用户地址方法
当地的
所有
所有
同行
宿主
所有
所有
127.0.0.1/32
急停-沙-256
宿主
所有
所有
:
:
1/128
急停-沙-256
hostssl
所有
所有
0.0.0.0/0
md5
hostssl
复制
所有
10.124.33.113/24
md5
|
同样,如果我们坚持要真正强制连接使用SSL,这是不够的。我们必须再次调用pg_reload_conf(),以确保它们被加载到PostgreSQL本身:
|
1
2
3.
4
5
|
postgres=# select pg_reload_conf()
pg_reload_conf
----------------
t
(
1
行
)
|
此时,新的远程非ssl连接将被拒绝:
|
1
2
|
(
根
@
node1
~
]
# PSQL "host=10.124.33.132 sslmode=disable"
psql
:
错误
:
连接
来
服务器
在
“10.124.33.132”
,
港口
5432
失败的
:
致命的
:
没有
pg_hba
. conf
条目
为
宿主
“10.124.33.113”
,
用户
“postgres”
,
数据库
“postgres”
,
没有
加密
|
那么,我们现在终于可以说我们完全安全了吗?不,还没有!已经建立的连接在重新连接之前不会强制使用SSL。
检查使用SSL/TLS的连接
我们可以使用以下查询检查使用SSL的连接:
|
1
2
3.
4
5
6
7
8
9
10
11
|
postgres=# select pg_ssl. #pid, pg_ssl。ssl, pg_ssl。版本,
pg_sa
.backend_type
,
pg_sa
.usename
,
pg_sa
.client_addr
从
pg_stat_ssl
pg_ssl
加入
pg_stat_activity
pg_sa
在
pg_ssl
.pid
=
pg_sa
.pid
;
pid
|
ssl
|
版本
|
backend_type
|
usename
|
client_addr
------+-----+---------+----------------+----------+---------------
5547
|
f
|
|
walsender
|
postgres
|
10.124.33.113
5549
|
f
|
|
客户端
后端
|
postgres
|
10.124.33.132
5556
|
f
|
|
客户端
后端
|
postgres
|
10.124.33.113
(
3.
行
)
|
在这种情况下,复制连接(walsender)还没有使用SSL,另外两个客户端也没有连接,所以如果我们想让它们重新连接,我们需要强制重新启动。与往常一样,我们建议您首先在测试环境中尝试所有这些步骤,当需要在生产环境中执行这些步骤时,请在适当建立的维护窗口中执行这些步骤(无论这些步骤看起来多么微不足道)。
要强制复制连接使用SSL,可以重新启动副本中的服务或使用pg_terminate_backend(这将发送SIGTERM信号,并且在此上下文中使用是安全的)。在这种情况下,我们使用pg_terminate_backend但它也可以用于副本,前提是我们使用了正确的PID编号。
|
1
2
3.
4
5
|
postgres=# select pg_terminate_backend(5547);
pg_terminate_backend
----------------------
t
(
1
行
)
|
在这之后,我们应该会看到使用SSL/TLS协议的新复制连接正确:
|
1
2
3.
4
5
6
7
8
9
10
11
|
postgres=# select pg_ssl. #pid, pg_ssl。ssl, pg_ssl。版本,
pg_sa
.backend_type
,
pg_sa
.usename
,
pg_sa
.client_addr
从
pg_stat_ssl
pg_ssl
加入
pg_stat_activity
pg_sa
在
pg_ssl
.pid
=
pg_sa
.pid
;
pid
|
ssl
|
版本
|
backend_type
|
usename
|
client_addr
------+-----+---------+----------------+----------+---------------
5557
|
t
|
TLSv1
。
2
|
walsender
|
postgres
|
10.124.33.113
5549
|
f
|
|
客户端
后端
|
postgres
|
10.124.33.132
5556
|
f
|
|
客户端
后端
|
postgres
|
10.124.33.113
(
3.
行
)
|
PID 5549是我们自己的连接,所以这是一个简单的修复:
|
1
2
3.
4
5
|
postgres=# select pg_backend_pid;
pg_backend_pid
----------------
5549
(
1
行
)
|
来自5556的连接将是我们检查是否需要在所有连接上强制SSL的剩余连接。在客户端,我们可以使用\conninfo来检查当前连接的信息:
|
1
2
3.
|
postgres=# \ conninfo
你
是
连接
来
数据库
“postgres”
作为
用户
“postgres”
在
宿主
“10.124.33.132”
在
港口
“5432”
。
SSL
连接
(
协议
:
TLSv1
。
2
,
密码
:
ECDHE-RSA-AES256-GCM-SHA384
,
位
:
256
,
压缩
:
从
)
|
禁用SSL / TLS
如果您想禁用SSL,请确保在设置SSL =off并更改pg_hba.conf文件后不丢失客户端连接,否则如果您没有任何帐户,使用“主机”只访问方法可能会被锁定,唯一的出路是重新启动服务。为了安全起见,首先,编辑并重新加载pg_hba.conf文件,以包括带有“host”的条目,然后才完全禁用SSL (SSL =off)。
结论
启用SSL/TLS用于传输连接加密很容易,但在强制使用时需要注意一些陷阱。仅仅启用它的配置是不够的,即使在默认情况下,一些连接可能更喜欢使用SSL。如果您需要确保所有连接都使用SSL,请相应地编辑pg_hba.conf文件并确保已加载。请记住,“hostssl”项是强制执行此行为的项。
我们可以使用tcpdump和wireshark来检查连接是否确实被加密。但是,这是另一个博客的话题了……






