PostgreSQL 用户及授权管理 06:启用 SSL 及验证

发布于:2024-06-29 ⋅ 阅读:(15) ⋅ 点赞:(0)

PostgreSQL 用户及授权管理 06:启用 SSL 及验证

安全在外企中是非常受重视的,一般外企都会要求所有可以使用加密的地方都使用加密。本小节我们启用 PostgreSQL 的 SSL 加密连接并进行抓包验证。

SSL 连接加密

安全套接字层 (SSL) 允许 PostgreSQL 接受加密的网络连接,这意味着每个数据包中的每一条数据都经过加密,因此我们要处理好密钥及合适的证书。

为了启用 SSL 扩展,我们首先需要配置服务器,然后接受传入的 SSL 连接,最后检测及验证客户端以 SSL 模式进行连接。

生成相关的证书

证书分为手工创建及自签名及从证书厂商那里购买证书。手工创建的证书适合在测试环境中使用,如果是在生产环境,那么建议购买付费的证书。证书是有有效期的,一般是免费的证书的有效期大概是 3 个月,付费的证书有效期一般是 1 年。接下来我们就介绍这两种类型的证书。

通过 openssl 的方式创建证书

接下来我们使用 openssl 来生成证书,或者在证书网站上面进行购买专业的证书。

[root@developing ~]# su - lavenliu

# 进入 PGDATA 目录,这里大家的目录可能与我的不一样
# 可以根据实际情况进行修改
[lavenliu@developing ~]$ cd $PGDATA

[lavenliu@developing data]$ mkdir ssl

[lavenliu@developing data]$ cd ssl

[lavenliu@developing ssl]$ openssl req -new -x509 -nodes -out mypg.lavenliu.cn.pem -keyout mypg.lavenliu.cn.key -days 365
.....+.+.........+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.+..+....+...+..+......+..........+..+.+......+......+........+.+...............+...+.....+......+.+...+..+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*..+.......+......+...........+....+..+...+....+...+.....+...+..........+......+.....+.........................+...+..+.+...+..+...+..........+..+..................+.+........+...+....+...+...+...+.....+.+......+.....+.......+..+........................+....+.....+.+...........+....+..+............+.......+.........+......+..............+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
...+.........+......+..+.......+...+......+.........+.....+.+..+....+.....+......+...+.+........+.+......+.....+.+..+.+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.....+.....+.+...+......+.........+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.......+...+....+...+..................+.....+.+.....+.+..+......+.+.....+......+...+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
# 下面会交互式的提示输入一些信息
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:Shanghai
Locality Name (eg, city) [Default City]:Shanghai
Organization Name (eg, company) [Default Company Ltd]:Chuanda Group
Organizational Unit Name (eg, section) []:DevOps Team
Common Name (eg, your name or your server's hostname) []:mypg.lavenliu.cn
Email Address []:lcc@lavenliu.cn
通过云厂商申请免费证书

现在很多云厂商都会提供一些免费的 SSL 证书可供使用,有效期有三个月及一年的,非常的方便。如果是在公有云厂商的控制台申请免费的,也是非常快的,通常几分钟就可以完成申请。如:

请添加图片描述

申请完成,可以下载证书到本地。我这里选择下载 Nginx 格式的。如:

请添加图片描述

为集群配置 SSL

为了启用 SSL 进行加密,服务器必须拥有私有和公共证书。一旦我们获得了证书,我们唯一需要做的就是将证书和密钥文件导入到我们的 PostgreSQL 服务器中。

假设我们的证书和密钥文件分别命名为 mypg.lavenliu.cn.pemmypg.lavenliu.cn.key,则必须在 postgresql.conf 配置文件中配置以下参数:

ssl = on
# 通过绝对路径配置
ssl_key_file = '/home/lavenliu/.pgenv/pgsql/data/ssl/mypg.lavenliu.cn.key'
ssl_cert_file = '/home/lavenliu/.pgenv/pgsql/data/ssl/mypg.lavenliu.cn.pem'

# 也可以通过相对路径配置,相对位置是 PGDATA 环境变量的值
ssl_key_file = 'ssl/mypg.lavenliu.cn.key'
ssl_cert_file = 'ssl/mypg.lavenliu.cn.pem'

第一行告诉 PostgreSQL 启用 SSL,而其他两行告诉服务器在哪里可以找到建立加密连接所需的文件。当然,这些文件必须能够被运行 PostgreSQL 集群的用户(通常是 postgres 操作系统用户)读取。

启用 SSL 后,我们需要调整 pg_hba.conf 文件以允许基于主机的访问机制处理基于 SSL 的连接。特别是,如果我们不想接受普通连接,则需要将每个主机条目替换为hostssl,例如:

hostssl all             lavenliu        myunixhost              scram-sha-256
hostssl all             forum           192.168.56.0/24         scram-sha-256

如果我们想同时接受明文连接和加密连接,可以将 host 方式保留即可。

通过 SSL 连接集群

当连接 PostgreSQL 时,如果基于主机的访问规则有匹配 hostssl 条目,客户端将自动切换到 SSL 连接;否则,它将默认为标准普通连接。

如果 pg_hba.conf 有一个 host 规则行,这意味着它可以接受 SSL 和普通连接。因此,我们需要在启动连接时强制使用 SSL。在 psql 中,这只能通过使用连接字符串并指定 sslmode=require 参数来启用它来实现。服务器如果接受连接,将打印正在使用的 SSL 协议:

[lavenliu@developing ~]$ psql "postgresql://forum@localhost:5432/forumdb?sslmode=require"
psql (16.2)
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
Type "help" for help.

forumdb=>

如果省略 sslmode 参数或使用标准 psql 连接参数,并且 pg_hba.conf 文件具有匹配的 hostssl 行,则连接将转换为 SSL。例如,以下三个连接产生相同的结果(加密连接):

$ psql -h localhost -U forum forumdb
psql (16.2)
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
Type "help" for help.

forumdb=> \q

$ psql "postgresql://forum@localhost:5432/forumdb"
psql (16.2)
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
Type "help" for help.

forumdb=> \q

$ psql "postgresql://forum@localhost:5432/forumdb?sslmode=require"
psql (16.2)
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
Type "help" for help.

forumdb=>

同样,我们可以通过设置 sslmode=disable 来指定禁用 SSL 连接。如果 pg_hba.conf 中有 hostssl 模式,则连接将被拒绝,而如果 pg_hba.conf 文件中有 host 行,则将作为非加密连接:

$ psql "postgresql://forum@localhost:5432/forumdb?sslmode=disable"
psql (16.2)
Type "help" for help.

forumdb=> 

最后,如果我们在连接字符串中使用了 SSL,但 PostgreSQL 服务器又未配置为使用 SSL,那么 PostgreSQL 会输出不支持 SSL 的错误信息:

$ psql "postgresql://forum@localhost:5432/forumdb?sslmode=disable"
psql: error: could not connect to server: server does not support SSL, but SSL was required

附录

PostgreSQL 不支持 SSL 问题解决

如何判断当前的 PostgreSQL 服务是否支持 SSL 呢?可以执行如下命令来验证:

[lavenliu@developing data]$ postgres -c ssl=on
2024-05-02 08:47:45.215 GMT [47322] FATAL:  SSL is not supported by this build

由上述输出可以看到,我们当前通过 pgenv 安装的 PostgreSQL 服务是不支持 SSL 的。或者执行如下命令:

[root@developing ~]# ldd `which postgres` |grep ssl

如果没有输出,则表明当前安装的 PostgreSQL 也不支持 SSL。如果支持 SSL,则上述命令会输出如下:

[lavenliu@developing ~]$ ldd /opt/pgsql-16.2/bin/postgres |grep ssl
	libssl.so.3 => /lib64/libssl.so.3 (0x00007f7469790000)

针对上述编译的版本不支持 SSL 怎么办?重新编译使其支持 SSL 即可,然后替换一下 postgres 的二进制程序,之前的数据还是可以使用的

[!tip]

通过 YUM 或 APT 安装的 PostgreSQL 则是支持 SSL 的。这里再次强调一下,不建议日常工作中使用编译的方式安装 PostgreSQL。

抓包验证连接是否加密

这里我们通过 tcpdump 来抓包验证一下,开启及没有开启 SSL 的区别。

没开启 SSL 的连接验证

分别打开两个终端,第一个终端里面使用 OS 的管理员账号进行抓包:

[root@developing ~]# tcpdump -nX -i lo port 5432

第二个终端进行数据库的连接及建表操作:

[postgres@developing ~]$ /opt/pgsql-16.2/bin/psql "postgresql://postgres@localhost:5432/forumdb?sslmode=disable"
psql (16.2)
Type "help" for help.

forumdb=# create table if not exists demo(name text);
NOTICE:  relation "demo" already exists, skipping
CREATE TABLE

forumdb=# insert into demo values ('Can you see me?');
INSERT 0 1

forumdb=# select * from demo;
      name       
-----------------
 Can you see me?
 Can you see me?
 Can you see me?
 Can you see me?
 Can you see me?
 Can you see me?
(6 rows)

此时,第一个终端里面将会显示如下内容(只截取了部分内容):

[root@developing ~]# tcpdump -nX -i lo port 5432
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on lo, link-type EN10MB (Ethernet), snapshot length 262144 bytes
11:55:09.651463 IP6 ::1.44496 > ::1.noadmin: Flags [S], seq 1958056583, win 33280, options [mss 65476,sackOK,TS val 3192031632 ecr 0,nop,wscale 7], length 0
...... 此处省略很多内容
	0x0000:  6006 fa3e 0020 0640 0000 0000 0000 0000  `..>...@........
	0x0010:  0000 0000 0000 0001 0000 0000 0000 0000  ................
	0x0020:  0000 0000 0000 0001 add0 0781 74b5 92db  ............t...
	0x0030:  d9e0 19ce 8010 0101 0028 0000 0101 080a  .........(......
	0x0040:  be42 8994 be42 8994                      .B...B..
11:55:16.843364 IP6 ::1.44496 > ::1.noadmin: Flags [P.], seq 84:133, ack 422, win 260, options [nop,nop,TS val 3192038824 ecr 3192031636], length 49
	0x0000:  6006 fa3e 0051 0640 0000 0000 0000 0000  `..>.Q.@........
	0x0010:  0000 0000 0000 0001 0000 0000 0000 0000  ................
	0x0020:  0000 0000 0000 0001 add0 0781 74b5 92db  ............t...
	0x0030:  d9e0 19ce 8018 0104 0059 0000 0101 080a  .........Y......
	0x0040:  be42 a5a8 be42 8994 5100 0000 3063 7265  .B...B..Q...0cre  # 这里是我们的建表语句
	0x0050:  6174 6520 7461 626c 6520 6966 206e 6f74  ate.table.if.not
	0x0060:  2065 7869 7374 7320 6465 6d6f 286e 616d  .exists.demo(nam
	0x0070:  6520 7465 7874 293b 00                   e.text);.
......
......
11:55:34.603291 IP6 ::1.44496 > ::1.noadmin: Flags [P.], seq 133:158, ack 560, win 260, options [nop,nop,TS val 3192056584 ecr 3192038824], length 25
	0x0040:  be42 eb08 be42 a5a8 5100 0000 1873 656c  .B...B..Q....sel # 此处是我们的查询语句
	0x0050:  6563 7420 2a20 6672 6f6d 2064 656d 6f3b  ect.*.from.demo;
	0x0060:  00                                       .
11:55:34.612985 IP6 ::1.noadmin > ::1.44496: Flags [P.], seq 560:766, ack 158, win 260, options [nop,nop,TS val 3192056593 ecr 3192056584], length 206
	0x0070:  0f43 616e 2079 6f75 2073 6565 206d 653f  .Can.you.see.me? # 这是查询出的数据
	0x0080:  4400 0000 1900 0100 0000 0f43 616e 2079  D..........Can.y
	0x0090:  6f75 2073 6565 206d 653f 4400 0000 1900  ou.see.me?D.....
	0x00a0:  0100 0000 0f43 616e 2079 6f75 2073 6565  .....Can.you.see
	0x00b0:  206d 653f 4400 0000 1900 0100 0000 0f43  .me?D..........C
	0x00c0:  616e 2079 6f75 2073 6565 206d 653f 4400  an.you.see.me?D.
	0x00d0:  0000 1900 0100 0000 0f43 616e 2079 6f75  .........Can.you
	0x00e0:  2073 6565 206d 653f 4400 0000 1900 0100  .see.me?D.......
	0x00f0:  0000 0f43 616e 2079 6f75 2073 6565 206d  ...Can.you.see.m
	0x0100:  653f 4300 0000 0d53 454c 4543 5420 3600  e?C....SELECT.6.
	0x0110:  5a00 0000 0549                           Z....I

从上面的抓包可以看到都是明文信息,这对安全要求严格的企业里面是不允许这样明文通讯的。

已开启 SSL 的连接验证

分别打开两个终端,第一个终端里面使用 OS 的管理员账号进行抓包:

[root@developing ~]# tcpdump -nX -i lo port 5432

第二个终端进行数据库的连接及建表操作:

[postgres@developing ~]$ psql "postgresql://forum@localhost:5432/forumdb?sslmode=require"
Password for user forum: 
psql (16.2)
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
Type "help" for help.

forumdb=> create table if not exists demo(name text);

forumdb=> insert into demo values ('Can you see me?');
INSERT 0 1

forumdb=> select * from demo;
      name       
-----------------
 Can you see me?
(1 rows)

此时,第一个终端里面将会显示如下内容(只截取了部分内容):

11:15:39.716066 IP 192.168.26.164.58914 > 192.168.26.164.noadmin: Flags [P.], seq 428722790:428722817, ack 442865350, win 512, options [nop,nop,TS val 2232602189 ecr 2232530665], length 27
	0x0000:  4500 004f 2e23 4000 4006 55ed c0a8 1aa4  E..O.#@.@.U.....
	0x0010:  c0a8 1aa4 e622 0781 198d ca66 1a65 96c6  .....".....f.e..
	0x0020:  8018 0200 b6da 0000 0101 080a 8512 ce4d  ...............M
	0x0030:  8511 b6e9 1703 0300 1689 269b d9de 66b3  ..........&...f.
	0x0040:  1e25 ac6a dc3d 2f21 48d0 a346 3430 97    .%.j.=/!H..F40.
11:15:39.716099 IP 192.168.26.164.58914 > 192.168.26.164.noadmin: Flags [P.], seq 27:51, ack 1, win 512, options [nop,nop,TS val 2232602189 ecr 2232530665], length 24
	0x0000:  4500 004c 2e24 4000 4006 55ef c0a8 1aa4  E..L.$@.@.U.....
	0x0010:  c0a8 1aa4 e622 0781 198d ca81 1a65 96c6  .....".......e..
	0x0020:  8018 0200 b6d7 0000 0101 080a 8512 ce4d  ...............M
	0x0030:  8511 b6e9 1703 0300 13d0 5baf ec18 278d  ..........[...'.
	0x0040:  2c4f 45c6 11a2 b909 e125 c543            ,OE......%.C
11:15:39.716193 IP 192.168.26.164.58914 > 192.168.26.164.noadmin: Flags [F.], seq 51, ack 1, win 512, options [nop,nop,TS val 2232602189 ecr 2232530665], length 0
	0x0000:  4500 0034 2e25 4000 4006 5606 c0a8 1aa4  E..4.%@.@.V.....
	0x0010:  c0a8 1aa4 e622 0781 198d ca99 1a65 96c6  .....".......e..
	0x0020:  8011 0200 b6bf 0000 0101 080a 8512 ce4d  ...............M
	0x0030:  8511 b6e9                                ....
。。。。。。省略很多输出
11:15:41.422926 IP 192.168.26.164.noadmin > 192.168.26.164.56030: Flags [P.], seq 2:101, ack 311, win 512, options [nop,nop,TS val 2232603896 ecr 2232603896], length 99
	0x0000:  4500 0097 25c1 4000 4006 5e07 c0a8 1aa4  E...%.@.@.^.....
	0x0010:  c0a8 1aa4 0781 dade 94d8 74b2 b503 ba93  ..........t.....
	0x0020:  8018 0200 b722 0000 0101 080a 8512 d4f8  ....."..........
	0x0030:  8512 d4f8 1603 0300 5802 0000 5403 03cf  ........X...T...
	0x0040:  21ad 74e5 9a61 11be 1d8c 021e 65b8 91c2  !.t..a......e...
	0x0050:  a211 167a bb8c 5e07 9e09 e2c8 a833 9c20  ...z..^......3..
	0x0060:  08e2 4768 d975 7b24 7855 635e 9790 458f  ..Gh.u{$xUc^..E.
	0x0070:  b388 db86 9f44 f04d 81c1 ed87 bf26 d68c  .....D.M.....&..
	0x0080:  1302 0000 0c00 2b00 0203 0400 3300 0200  ......+.....3...
	0x0090:  1714 0303 0001 01                        .......
11:15:41.423139 IP 192.168.26.164.56030 > 192.168.26.164.noadmin: Flags [P.], seq 311:652, ack 101, win 512, options [nop,nop,TS val 2232603896 ecr 2232603896], length 341
	0x0000:  4500 0189 27cd 4000 4006 5b09 c0a8 1aa4  E...'.@.@.[.....
	0x0010:  c0a8 1aa4 dade 0781 b503 ba93 94d8 7515  ..............u.

由上面的输出可以看到,打印的内容已经加密了。

总结

最后,如果配置得当,服务器可以通过 SSL 处理网络连接,从而加密所有网络流量和数据。如果在外企工作的话,那么他们对安全要求是非常严格的,在他们那里:安全第一,业务第二。在国内的企业可能要求的就没那么高了。这一节里面介绍的内容在国内企业用的虽然不多,但是这节的内容非常重要,推荐大家掌握。虽然国内企业不那么重视安全,但我们却不能不重视。


网站公告

今日签到

点亮在社区的每一天
去签到