SSL单向认证和双向认证:
SSL单向认证:只有一端校验对端的证书合法性,通常都是客户端来校验服务器的合法性。即在一般的单向认证中,只要求服务器端部署了ssl证书就行,客户端可以无证书,任何用户都可以去访问服务端,服务端只是提供了身份认证。
client: 无证书
server: server.crt, server.key

SSL双向认证:客户端和服务端相互校验,服务器需要校验每个客户端,每个客户端也需要校验服务器,只有服务器和用户双方都有证书才能正常通信,因此只能是服务端允许的客户才能访问服务器。
client: root.crt, postgresql.crt, postgresql.key
server: root.crt, server.crt, server.key

下面分别从服务端和客户端说明如何配置SSL单/双向认证**********************************************

一、服务端

下载pg安装包:
 wget  https://ftp.postgresql.org/pub/source/v11.4/postgresql-11.4.tar.gz
安装前准备:
yum install net-tools -y
yum install sysstat -y
yum install iotop libXp redhat-lsb gcc gdb –y
yum install xorg-x11-xauth -y
yum install -y vim lrzsz tree wget gcc gcc-c++ readline-devel hwloc smartmontools
yum install -y readline readline-devel openssl openssl-devel zlib zlib-devel numactl
解压 :
 tar zxvf postgresql-11.4.tar.gz
编译:
./configure --prefix=/usr/local/postgresql    --with-openssl  #加 --with-openssl编译选项
安装:
make && make install
创建目录:
mkdir /usr/local/postgresql/data
mkdir /usr/local/postgresql/log
加入系统环境变量:

vim /etc/profile

export PGHOME=/usr/local/postgresql
export PGDATA=/usr/local/postgresql/data
export PATH=$PATH:$HOME/.local/bin:$HOME/bin:$PGHOME/bin
使配置文件生效:
source /etc/profile
增加用户 postgres 并赋权:
adduser postgres
passwd postgres
chown -R postgres:root /usr/local/postgresql/
切换到用户 postgres:
su postgres
cd /usr/local/postgresql/data/
创建证书:

虽然可以使用自签名证书进行测试,但在实际生产中应该使用由证书颁发机构(CA)(通常是企业范围的根CA)签署的证书。

要创建可以由客户端验证身份的服务器证书,首先创建证书签名请求(certificate signing request (CSR))和公钥/私钥文件:

[root@xxx data]# openssl req -new -nodes -text -out root.csr -keyout root.key -subj "/CN=root.yourdomain.com"  aisainfo 
Generating a 2048 bit RSA private key
............................................................................................................................+++
....+++
writing new private key to 'root.key'
-----

[root@xxx data]# ll
-rw-r--r--. 1 root     root      3315 May  6 07:30 root.csr
-rw-r--r--. 1 root     root      1704 May  6 07:30 root.key

然后,使用密钥对请求进行签名,以创建根证书颁发机构(在Linux上使用默认的OpenSSL配置文件位置):

[root@xxx data]# openssl x509 -req -in root.csr -text -days 3650 -extfile /etc/pki/tls/openssl.cnf  -extensions v3_ca -signkey root.key -out root.crt
Signature ok
subject=/CN=postgres
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number:
            9c:dc:90:eb:19:e4:e4:6d
    Signature Algorithm: NULL
        Issuer: CN=postgres
        Validity
            Not Before: May  6 03:28:00 2023 GMT
            Not After : May  3 03:28:00 2033 GMT
        Subject: CN=postgres
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:c4:35:2b:73:a1:d2:b5:17:3b:10:9c:2e:b6:53:
                    a6:90:fb:22:a4:97:5b:73:58:19:cc:9a:1f:08:0d:
                    2f:07:2d:df:ee:4e:18:f4:c5:12:5c:95:3b:90:d2:
                    ca:28:31:4d:b2:fa:e9:5f:6d:57:c0:30:ec:bf:55:
                    ff:9b:18:c6:68:f3:7c:2a:bc:94:1d:52:0a:d2:00:
                    ae:f4:79:9c:53:b1:43:b0:12:65:1f:ef:d0:14:b2:
                    64:7c:32:ec:97:93:a0:e1:41:b1:54:53:85:99:d8:
                    ac:3f:a3:f0:d0:d4:95:0d:b2:15:86:aa:6b:df:5d:
                    c6:70:bf:ea:d4:c0:01:51:24:ef:7b:f0:6e:8a:42:
                    7a:e2:ed:7d:29:a4:c5:7f:5e:2d:dc:fd:bb:3c:35:
                    4b:af:13:3b:22:c7:47:a5:49:92:36:f7:f2:57:78:
                    ef:c8:e1:cb:47:ff:6d:31:cd:97:f5:2f:02:76:07:
                    05:27:9a:39:da:e0:92:a7:fc:51:cb:b9:59:ea:c9:
                    b2:65:23:29:7e:88:62:59:c6:5a:a3:3c:91:ab:ea:
                    4d:1b:32:04:e1:45:6e:98:5b:a5:42:51:47:51:1c:
                    b3:74:58:08:5d:51:d9:1d:62:3f:37:4e:4a:ed:1e:
                    72:ae:d0:58:17:bb:26:57:20:95:72:ef:04:02:00:
                    bd:27
                Exponent: 65537 (0x10001)
    Signature Algorithm: NULL
Getting Private key

[root@xxx data]# ll
-rw-r--r--. 1 root     root      1090 May  6 07:31 root.crt
-rw-r--r--. 1 root     root      3315 May  6 07:30 root.csr
-rw-r--r--. 1 root     root      1704 May  6 07:30 root.key

最后,创建一个由新的根证书颁发机构签名的服务器证书:

[root@xxx data]# openssl req -new -nodes -text -out server.csr -keyout server.key -subj "/CN=dbhost.yourdomain.com"       udmuser
Generating a 2048 bit RSA private key
...............................................+++
.....+++
writing new private key to 'server.key'
-----

[root@xxx data]# ll
-rw-r--r--. 1 root     root      3315 May  6 07:37 server.csr
-rw-r--r--. 1 root     root      1704 May  6 07:37 server.key


[root@xxx data]# chmod og-rwx server.key



[root@xxx data]# openssl x509 -req -in server.csr -text -days 365 -CA root.crt -CAkey root.key -CAcreateserial -out server.crt
Signature ok
subject=/CN=postgres
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number:
            bb:ca:fa:52:ef:54:e9:c7
    Signature Algorithm: NULL
        Issuer: CN=postgres
        Validity
            Not Before: May  6 07:39:04 2023 GMT
            Not After : May  5 07:39:04 2024 GMT
        Subject: CN=postgres
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:e5:41:69:05:65:23:dc:5e:ef:b0:af:29:01:b6:
                    00:91:4b:a6:20:09:72:9b:d4:eb:75:3a:1d:75:ae:
                    76:9d:7c:6f:f8:cc:2b:03:39:d1:37:23:4e:cf:99:
                    69:8e:93:45:61:b7:af:e5:a2:63:61:31:05:07:ca:
                    d6:5a:cf:f5:53:02:60:1c:15:ed:32:7f:18:27:c8:
                    d0:c1:b4:f7:2d:87:19:51:34:ed:ef:04:2f:65:18:
                    74:0d:b9:5c:c0:e2:ff:21:16:4a:cd:b3:13:a8:2c:
                    bb:4f:e5:20:83:26:16:0c:48:ce:c1:d9:36:c1:fb:
                    db:8e:dd:9e:1b:fc:11:d6:73:a6:74:b0:27:bb:0d:
                    d9:80:2f:b9:ee:b3:bf:a2:3e:8c:15:12:be:35:85:
                    2c:5c:5a:2c:c1:c6:a4:63:ae:cd:37:49:38:aa:55:
                    67:32:b3:11:7e:ce:e8:e2:46:1e:57:52:a6:2a:6b:
                    2e:90:f8:e0:25:aa:0c:fa:8a:74:d1:4f:39:c9:0e:
                    68:09:89:8c:54:e6:0a:68:27:76:82:e4:eb:f0:64:
                    9d:e1:34:f5:19:e5:cf:dc:81:03:cb:40:d9:a2:64:
                    64:a1:92:b3:c4:14:3a:c3:0d:7b:b8:86:6a:c3:a2:
                    f5:1a:af:20:9e:e3:da:fc:58:38:6f:4d:8c:b6:1f:
                    ad:cb
                Exponent: 65537 (0x10001)
    Signature Algorithm: NULL
Getting CA Private Key

[root@xxx data]# ll
-rw-r--r--. 1 root     root       973 May  6 07:39 server.crt
-rw-r--r--. 1 root     root      3315 May  6 07:37 server.csr
-rw-------. 1 root     root      1679 May  6 07:38 server.key



执行初始化数据库命令:
/usr/local/postgresql/bin/initdb -D /usr/local/postgresql/data/

注意:
1)不能在 root 用户下初始数据库,否则会报错;
2)初始化之后配置pg_hba.conf和postgres.conf,接着启动数据库可直接按配置启动数据库;下面描述的方法是启动数据库后,再修改配置并使配置生效的方法,配置参数都是一样的。

切到root下,为 pg_ctl 创建软链接:
su
ln -s /usr/local/postgresql/bin/pg_ctl /usr/bin/pg_ctl
ln -s /usr/local/postgresql/bin/psql /usr/bin/psql
为用户 postgres 赋权:
chown -R postgres:postgres /usr/local/postgresql/data
chmod -R 0700 /usr/local/postgresql/data
切换到用户 postgres启动服务:
su postgres
pg_ctl start -l /usr/local/postgresql/log/pg_server.log
到指定路径查看日志

日志路径: /usr/local/postgresql/log/pg_server.log ----> /usr/local/postgresql/data/pg_log

在这里插入图片描述

修改postgres.conf,配置SSL参数:

vim postgres.conf

ssl = on                                 #支持SSL,默认off(关闭)。该参数只能在Server启动时设置。SSL通信只能通过TCP/IP连接进行。
ssl_cert_file = 'server.crt'             #指定包含SSL服务器证书的文件的名称。
ssl_key_file = 'server.key'              #指定包含SSL服务器私钥的文件的名称。

注意:
单项认证采用以上配置即可,双向认证使用以下配置【双向认证必须配置ssl_ca_file项】:

ssl = on                                 #支持SSL,默认off(关闭)。该参数只能在Server启动时设置。SSL通信只能通过TCP/IP连接进行。
ssl_ca_file = 'root.crt'                 #指定根证书,SSL单项认证时也可以不配置、SSL双向认证必须配置
ssl_cert_file = 'server.crt'             #指定包含SSL服务器证书的文件的名称。
ssl_key_file = 'server.key'              #指定包含SSL服务器私钥的文件的名称。
修改pg_hba.conf

如果强制SSL连接(仅允许SSL连接)、不允许普通连接,则修改pg_hba.conf,配置SSL连接认证规则:
vim pg_hba.conf

单向认证:

hostssl      all    all    0.0.0.0/0    md5

双向认证(以下两种配置方式都可以):

hostssl      all    all    0.0.0.0/0    md5  clientcert=1
hostssl      all    all    0.0.0.0/0    cert

注意:
不同版本的postgresql配置双向认证的参数略有不同,我当前安装的v11.4版本就可以用clientcert=1或者cert,具体可以根据自己安装的版本查看官方说明,v11.4版本的配置说明如下:

【参考资料】:PostgreSQL: Documentation: 11: 18.9. Secure TCP/IP Connections with SSL

18.9.3. Using Client Certificates
To require the client to supply a trusted certificate, place certificates of the root certificate authorities (CAs) you trust in a file in the data directory, set the parameter ssl_ca_file in postgresql.conf to the new file name, and add the authentication option clientcert=1 to the appropriate hostssl line(s) in pg_hba.conf. A certificate will then be requested from the client during SSL connection startup. (See Section 34.18 for a description of how to set up certificates on the client.) The server will verify that the client’s certificate is signed by one of the trusted certificate authorities.
The clientcert authentication option is available for all authentication methods, but only in pg_hba.conf lines specified as hostssl. When clientcert is not specified or is set to 0, the server will still verify any presented client certificates against its CA file, if one is configured — but it will not insist that a client certificate be presented.
If you are setting up client certificates, you may wish to use the cert authentication method, so that the certificates control user authentication as well as providing connection security. See Section 20.12 for details. (It is not necessary to specify clientcert=1 explicitly when using the cert authentication method.)

说明:
pg_hba.conf中的Client连接认证规则配置的几种类型:local、host、hostssl、hostnossl
local: 此记录匹配通过 Unix 域套接字进行的联接企图,没有这种类型的记录,就不允许 Unix 域套接字的联接。
host: 此记录匹配使用TCP/IP进行的连接尝试,他既匹配通过ssl方式的连接,也匹配通过非ssl方式的连接,会优先使用ssl认证。
hostssl: 此记录匹配使用TCP/IP进行的连接尝试,但仅在使用SSL加密进行连接时才匹配。hostssl表示强制使用ssl。
hostnossl:此记录类型具有与hostssl相反的行为:它仅匹配不使用SSL的TCP/IP上的连接尝试。hostnossl表示前置不使用ssl。

登陆PostgreSQL数据库,打开ssl开关:

psql -U postgres -d postgres

postgres=# alter system set ssl=on;
ALTER SYSTEM
调用pg_reload_conf()以确保配置文件被加载:
postgres=# select pg_reload_conf();

重新加载配置遇到的几个问题:
1、未删除server.key的密码,报错:“private key file ““server.key”” cannot be reloaded because it requires a passphrase”,"
解决方法:删除私钥中的密码

openssl rsa -in server.key -out server.key

2、server.key未修改访问权限,报错:“private key file “server.key” has group or world access”
解决方法:修改文件权限

chmod 600 xxxfile

3、未正确配置pg_hba.conf,远程连接时报错:
“xxxuser”,“xxxdb”,25257,“10.11.58.83:44764”,644a0fb6.62a9,1,“authentication”,2023-04-27 06:01:26 UTC,3/2216,0,FATAL,28000,“no pg_hba.conf entry for host ““10.11.58.83"”, user ““xxxuser””, database ““xxxdb””, SSL off”,”"
解决方法:检查pg_hba.conf文件配置

重启数据库,ssl生效
[postgres@localhost~]$ psql -Upostgres postgres -h localhost
Password forusersa: 
psql (11.1)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" forhelp.
查看ssl开关:
postgres=# show ssl;
 ssl
-----
 on
(1 row)
检查使用SSL/TLS的会话连接
postgres=#  select pg_ssl.pid, pg_ssl.ssl, pg_ssl.version,pg_sa.backend_type, pg_sa.usename, pg_sa.client_addr from pg_stat_ssl pg_ssl join pg_stat_activity pg_sa on pg_ssl.pid = pg_sa.pid;
  pid  | ssl | version |         backend_type         | usename  | client_addr
-------+-----+---------+------------------------------+----------+-------------
 16629 | f   |         | autovacuum launcher          |          |
 16748 | f   |         | logical replication launcher | postgres |
 25923 | t   | TLSv1.2 | client backend               | postgres | ::1
 16627 | f   |         | background writer            |          |
 16626 | f   |         | checkpointer                 |          |
 16628 | f   |         | walwriter                    |          |
(6 rows)

总结:
服务端按需求配置postgres.conf、pg_hba.conf两个配置文件,并放入相关证书文件(root.crt, server.crt, server.key)即可打开SSL单/双向认证连接;仅做单向认证的话到这里就完成了,无需对客户端进行配置;下面描述的是客户端双向认证配置流程。

二、客户端:

1)生成客户端SSL配置(在服务端进行):

服务端为客户端生成客户后端证书,提供给客户端连接时使用。
客户端开启SSL配置双向认证连接服务器,需要三个文件:
root.key(根证书)
postgresql.crt(客户端证书)
postgresql.key(客户端私钥)

在服务器端操作、生成客户端需要的文件,即客户后端私钥(postgresql.key)和客户端证书(postgresql.crt):

创建一个由根证书颁发机构签名的客户端证书:
[root@xxx data]# openssl req -new -nodes -text -out postgresql.csr -keyout postgresql.key  -subj "/CN=dbhost.yourdomain.com"   udmuser
Generating a 2048 bit RSA private key
...........+++
............................................................+++
writing new private key to 'postgresql.key'
-----
[root@xxx data]# ll
-rw-r--r--. 1 root     root      3315 May  6 08:26 postgresql.csr
-rw-r--r--. 1 root     root      1704 May  6 08:26 postgresql.key


[root@xxx data]# chmod og-rwx postgresql.key

[root@xxx data]# openssl x509 -req -in postgresql.csr -text -days 365 -CA root.crt -CAkey root.key -CAcreateserial -out postgresql.crt
Signature ok
subject=/CN=postgres
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number:
            c1:32:b7:ec:c8:a1:31:4f
    Signature Algorithm: NULL
        Issuer: CN=postgres
        Validity
            Not Before: May  6 08:28:15 2023 GMT
            Not After : May  5 08:28:15 2024 GMT
        Subject: CN=postgres
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:e0:8c:eb:29:3c:df:17:ca:8c:e4:ab:37:8f:f9:
                    02:ec:3e:c3:0f:0d:86:2c:fb:21:aa:81:39:31:fd:
                    45:4e:3e:a4:99:f8:f4:49:cc:69:d2:1a:31:87:f1:
                    e8:17:46:86:0b:d5:06:46:9a:85:1a:d5:7a:1a:d4:
                    27:b7:09:6d:28:0e:9b:ff:c4:96:90:5e:02:b2:b3:
                    be:49:d0:6b:f3:aa:25:5d:1f:22:b3:a1:e2:0d:29:
                    6b:e6:41:09:85:a6:66:ee:2f:6b:a7:25:8a:25:f3:
                    92:71:6b:fc:d9:34:68:eb:70:0c:f0:d8:b2:4f:82:
                    f3:02:fa:0f:02:c8:95:5e:32:09:d0:01:ae:39:8d:
                    13:c4:9a:e1:6b:ab:3b:01:96:c1:d8:95:0c:70:22:
                    2b:7d:a8:e9:0d:5f:18:5f:5c:6e:84:80:0a:51:77:
                    2e:87:3d:62:6e:0b:30:39:a2:76:19:ff:95:da:ad:
                    fb:61:44:e7:15:f3:c9:c6:fa:b2:26:db:b9:79:08:
                    ad:75:bf:26:15:54:62:63:ee:ed:0e:67:6d:05:df:
                    3c:03:4a:fc:d8:6c:f8:b3:b4:fb:ab:66:c0:f8:e6:
                    4d:3f:0b:77:9d:be:4f:a8:5c:c0:4f:1f:76:d4:cf:
                    4b:33:e8:40:09:96:8c:02:dc:9c:9e:d3:37:59:d4:
                    65:d3
                Exponent: 65537 (0x10001)
    Signature Algorithm: NULL
Getting CA Private Key

[root@xxx data]# ll
-rw-r--r--. 1 root     root       973 May  6 08:28 postgresql.crt
-rw-r--r--. 1 root     root      3315 May  6 08:26 postgresql.csr
-rw-------. 1 root     root      1679 May  6 08:27 postgresql.key
2) 拷贝客户端SSL配置文件到客户端机器
root.key          #根证书
postgresql.crt    #客户端证书
postgresql.key    #客户端私钥

将 1)中生成的客户端证书从服务端复制到客户端以下路径:
(a)~/.postgresql/目录下(没有找到的话在root下mkdir一个.postgresql文件夹再放进去证书),这是默认路径
(b) 将证书放到自定义路径下,并通过设置环境变量指定证书路径:

export PGSSLROOTCERT=/home/pgcert/root.crt
export PGSSLCERT=/home/pgcert/postgresql.crt
export PGSSLKEY=/home/pgcert/postgresql.key
3)配置/etc/odbc.ini文件:

PostgreSQL 的几种SSL连接模式:
disable: 只尝试非SSL连接。
allow: 首先尝试非SSL连接,若失败再尝试SSL连接。
prefer: 默认模式,首先尝试SSL连接,若失败再尝试非SSL连接。
require: 只尝试SSL连接,若有根证书存在,等同于verify-ca。
verify-ca: 只尝试SSL连接,并用根证书验证服务器证书是不是根CA签发的。
verify-full:只尝试SSL连接,并用根证书验证服务器证书是不是根CA签发的,且主题必须匹配连接域名或IP地址

进行SSL连接的话仅考虑配置后三种连接模式,其区别在于:
Require:只对数据链路加密,并不验证数据库的真实性。
Verify-CA:加密数据链路,同时验证数据库的真实性。
Verify-Full:加密数据链路,验证数据库的真实性,同时比对证书内的CN或DNS与连接时配置的数据库连接地址是否一致。

并且:
verify-ca和verify-full之间的区别取决于根CA的策略。如果使用了一个公共CA,verify-ca允许连接到那些可能已经被其他人注册到该CA的服务器。在这种情况下,总是应该使用verify-full。如果使用了一个本地CA或者甚至是一个自签名的证书,使用verify-ca常常就可以提供足够的保护。

由于我的项目使用的是自签名的证书,因此我配置Sslmode = require,无证书时可进行单向认证连接;放入相关证书(等同于verify-ca)即可满足双向认证连接的需求。

增加下面的配置:
vim /etc/odbc.ini

Sslmode = require

三、测试:

远程连接数据源并进行数据库操作:
[root@xxx /root]#isql xxxxx  -v
+---------------------------------------+
| Connected!                            |
|                                       |
| sql-statement                         |
| help [tablename]                      |
| quit                                  |
|                                       |
+---------------------------------------+
SQL> select * from xxxTable;

操作数据库和抓包:

1、远程连接
2、操作数据库
3、断开远程连接
单向认证抓包:
请添加图片描述
双向认证抓包:
请添加图片描述

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐