PostgreSQL本机支持使用SSL连接加密客户机/服务器通信以提高安全性。这要求在客户端和服务器系统上都安装OpenSSL,并且在构建时启用PostgreSQL中的支持。
要以SSL模式启动,必须存在包含服务器证书和私钥的文件。默认情况下,这些文件应该分别在服务器的数据目录中命名为server.crt和server.key,但是可以使用配置参数ssl-cert-file和ssl-key-file指定其他名称和位置。
在Unix系统上,server.key上的权限必须禁止任何访问World或Group;通过命令chmod 0600 server.key实现这一点。或者,该文件可以由根目录拥有,并具有组读取权限(即0640权限)。该安装程序用于由操作系统管理证书和密钥文件的安装。然后,运行PostgreSQL服务器的用户应成为可以访问这些证书和密钥文件的组的成员。
如果数据目录允许组读取访问,则证书文件可能需要位于数据目录之外,以便符合上述安全要求。通常,启用组访问以允许非特权用户备份数据库,在这种情况下,备份软件将无法读取证书文件,并可能出错。
如果私钥受密码短语保护,服务器将提示输入密码短语,并且在输入密码短语之前不会启动。使用密码短语还会禁用在不重新启动服务器的情况下更改服务器的SSL配置的功能。此外,受密码保护的私钥不能在Windows上使用。
server.crt中的第一个证书必须是服务器的证书,因为它必须与服务器的私钥匹配。“中间”证书颁发机构的证书也可以附加到文件中。这样做可以避免在客户机上存储中间证书的必要性,假设根证书和中间证书是使用v3_ca扩展创建的。这使得中间证书更容易过期。
不需要将根证书添加到server.crt。相反,客户机必须拥有服务器证书链的根证书。
OpenSSL配置
PostgreSQL读取系统范围的OpenSSL配置文件。默认情况下,此文件名为openssl.cnf,位于openssl version-d报告的目录中。通过将环境变量openssl_conf设置为所需配置文件的名称,可以覆盖此默认值。
OpenSSL支持各种不同强度的密码和身份验证算法。虽然可以在openssl配置文件中指定密码列表,但是可以通过修改postgresql.conf中的ssl密码来指定数据库服务器专用的密码。
使用client认证
要要求客户端提供可信证书,请将您信任的根证书颁发机构(CA)的证书放在数据目录中的文件中,将postgresql.conf中的参数ssl_ca_file设置为新文件名,并将身份验证选项clientcert=1添加到pg_hba.conf中相应的hotssl行中。证书将在SSL连接启动期间从客户端请求。服务器将验证客户端的证书是否由受信任的证书颁发机构之一签名。
如果您希望避免将现有根证书存储在客户机上(假设根证书和中间证书是使用v3_ca扩展名创建的),那么链接到现有根证书的中间证书也可以出现在ssl_ca_file 中。如果设置了参数 ssl_crl_file ,则还会检查证书吊销列表(crl)条目。
clientcert身份验证选项可用于所有身份验证方法,但仅在指定为hotssl的pg_hba.conf行中可用。如果未指定clientcert或将其设置为0,则服务器仍将根据其CA文件(如果配置了CA文件)验证任何提供的客户端证书,但不会坚持提供客户端证书。
如果您正在设置客户端证书,您可能希望使用cert身份验证方法,以便证书控制用户身份验证并提供连接安全性。
SSL server File
File |
Contents |
Effect |
ssl_cert_file |
server certificate |
sent to client to indicate server's identity |
ssl_key_file |
server private key |
proves server certificate was sent by the owner; does not indicate certificate owner is trustworthy |
ssl_ca_file |
trusted certificate authorities |
checks that client certificate is signed by a trusted certificate authority |
ssl_crl_file |
certificates revoked by certificate authorities |
client certificate must not be on this list |
server.crt和server.key应该存储在服务器上,root.crt应该存储在客户机上,这样客户机就可以验证服务器的叶证书是否由其受信任的根证书签名。root.key应脱机存储,以用于创建将来的证书。
1. 参数配置
1.1 postgresql.conf
ssl = on
# Produced by running: openssl ciphers | tr ':' '\n' | grep AES256 | grep SHA384
ssl_ciphers = 'ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:DHE-DSS-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDH-RSA-AES256-GCM-SHA384:ECDH-ECDSA-AES256-GCM-SHA384:ECDH-RSA-AES256-SHA384:ECDH-ECDSA-AES256-SHA384:AES256-GCM-SHA384'
# Server's certificate
ssl_cert_file = '/home/site/cert_test/server.crt'
ssl_key_file = '/home/site/cert_test/server.key'
#Used for verifying clients
ssl_ca_file = '/home/site/cert_test/ca-bundle.crt'
1.2 pg_hba.conf
hostssl clientcert=0 / 不设置
hostssl clientcert=1
hostssl all all 192.168.4.13/32 trust
2. 生成认证证书
2.1 create a simple self-signed certificate for the server
# openssl req -new -x509 -days 365 -nodes -text -out server.crt -keyout server.key -subj "/CN=daodao.com"
Generating a 2048 bit RSA private key
................................................+++
....................+++
writing new private key to 'server.key'
-----
# ls
server.crt server.key
# chmod og-rwx server.key
2.2 create a server certificate whose identity can be validated by clients
# openssl req -new -nodes -text -out root.csr \
> -keyout root.key -subj "/CN=root.daodao.com"
Generating a 2048 bit RSA private key
....+++
...............+++
writing new private key to 'root.key'
-----
# chmod og-rwx root.key
# ll
total 16
-rw-r--r--. 1 root root 3330 May 21 11:00 root.csr
-rw-------. 1 root root 1708 May 21 11:00 root.key
-rw-r--r--. 1 root root 4071 May 21 10:58 server.crt
-rw-------. 1 root root 1704 May 21 10:58 server.key
vim cert_test.csf_config
[ ca ]
default_md = sha384
default_ca = CA_default
[ CA_default ]
default_days = 365
preserve = no
policy = policy_strict
default_md = sha384
[ policy_strict ]
# The root CA should only sign intermediate certificates that match.
# See the POLICY FORMAT section of `man ca`.
commonName = supplied
[ req ]
# Options for the `req` tool (`man req`).
default_bits = 2048
distinguished_name = req_distinguished_name
string_mask = utf8only
default_md = sha384
[ req_distinguished_name ]
commonName = dbwtest03bc.test.com
[ namespace_extensions ]
# Extensions for server certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth,clientAuth
subjectAltName = @alt_names
[alt_names]
DNS.0 = dbwtest03bc.test.com
##########
# openssl x509 -req -in root.csr -text -days 3650 -extfile cert_test.csf_config -extensions v3_ca -signkey root.key -out root.crt
Error Loading extension section v3_ca
[root@dbwtest03bc cert_test]# openssl x509 -req -in root.csr -text -days 3650 -extfile cert_test.csf_config -signkey root.key -out root.crt
Signature ok
subject=/CN=root.daodao.com
Certificate:
Data:
Version: 1 (0x0)
Serial Number:
ef:df:21:70:3f:ee:5c:e1
Signature Algorithm: NULL
Issuer: CN=root.daodao.com
Validity
Not Before: May 21 15:10:43 2019 GMT
Not After : May 18 15:10:43 2029 GMT
Subject: CN=root.daodao.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:c2:e1:bb:53:1a:7c:88:56:83:e3:77:78:83:e3:
ea:30:24:53:af:ba:1e:b9:d6:9f:29:4b:15:ff:ee:
12:6a:7d:a1:e1:6f:74:f2:d3:2f:b0:07:a8:e3:4e:
23:1d:78:d1:ee:ab:b3:87:04:d5:65:c2:8b:24:9a:
db:2d:cd:1a:14:5b:56:d5:e5:15:eb:3f:37:fd:07:
da:02:4f:14:49:71:e0:ae:15:c9:42:1a:f5:67:ad:
d1:c6:b8:c8:64:51:f0:c5:cd:62:cf:50:03:f8:c3:
cf:02:a6:d6:a2:b5:4e:19:28:5e:e5:32:19:5a:f2:
3d:3e:fe:d2:49:75:d6:02:5c:68:f4:da:2d:c5:c2:
c9:b4:7f:08:7c:aa:79:3c:fb:cc:a0:14:29:77:bc:
44:25:18:79:4f:66:34:cb:27:3b:44:49:9b:08:0b:
0f:62:14:cd:5b:b4:08:db:fe:61:ac:f6:82:fb:d4:
f2:7b:b5:87:f6:ec:06:bc:b2:d0:f0:5f:fe:57:aa:
7f:f2:3d:67:9b:80:ba:81:43:bf:74:2e:02:0a:32:
7c:09:53:ff:15:e8:4c:24:1f:6b:b3:ea:af:2c:4b:
53:e8:fe:b3:01:ea:74:a6:f9:41:ea:71:8b:a0:99:
8b:1e:9f:69:be:9e:88:03:c5:20:c6:37:a7:61:71:
6a:b5
Exponent: 65537 (0x10001)
Signature Algorithm: NULL
Getting Private key
# openssl req -new -nodes -text -out server.csr \
> -keyout server.key -subj "/CN=daodao.com"
Generating a 2048 bit RSA private key
..................................................................................+++
........................................+++
writing new private key to 'server.key'
-----
[root@dbwtest03bc cert_test]# chmod og-rwx server.key
[root@dbwtest03bc cert_test]# openssl x509 -req -in server.csr -text -days 365 \
> -CA root.crt -CAkey root.key -CAcreateserial \
> -out server.crt
Signature ok
subject=/CN=daodao.com
Certificate:
Data:
Version: 1 (0x0)
Serial Number:
ee:10:d4:79:9d:5b:a4:c2
Signature Algorithm: NULL
Issuer: CN=daodao.com
Validity
Not Before: May 21 15:12:42 2019 GMT
Not After : May 20 15:12:42 2020 GMT
Subject: CN=daodao.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:b3:4b:82:bd:1e:4b:69:a5:38:1e:6c:ef:97:0e:
db:f8:ee:60:83:80:5b:4b:9f:26:6b:d3:db:21:0f:
6e:02:37:82:6d:11:f9:33:94:5c:f2:8e:b2:83:39:
01:5b:b7:4d:7f:cc:a9:f2:5b:59:fe:90:b9:3a:8e:
10:fc:38:bf:10:38:ec:4d:68:a5:9f:48:68:7f:1a:
81:3d:77:3c:a3:18:e2:8e:1f:61:95:54:c7:b7:2f:
ef:33:23:64:3b:a6:ff:59:0e:a5:f5:d4:87:ee:46:
5d:46:fa:47:98:d9:9c:b7:6a:aa:19:a2:cd:21:03:
cf:ba:33:13:60:fd:c9:36:cc:74:79:70:90:74:cb:
a1:3d:42:98:3a:3f:8c:fe:8c:eb:12:88:f6:91:aa:
71:71:fc:ba:5f:6d:1e:be:e5:3f:28:71:1c:87:03:
7b:44:7d:48:cc:89:46:be:f1:5f:c8:23:ee:c2:47:
18:8b:2c:79:2f:3c:2b:eb:24:43:c8:e0:6f:3d:d3:
d6:ce:72:f2:c0:60:05:dc:59:fc:80:b9:5e:0d:3d:
45:a0:d5:69:9d:9d:10:0f:b0:e1:fe:53:5f:ff:dd:
77:91:fe:b2:1c:34:13:61:d7:13:d5:39:b9:ce:00:
f5:a8:49:40:e4:3d:d7:0b:54:65:c6:a1:b8:a4:b4:
d1:97
Exponent: 65537 (0x10001)
Signature Algorithm: NULL
Getting CA Private Key
测试:
# psql -U dbadmin -d postgres -h dbwtest03bc
psql (10.6, server 11.1)
WARNING: psql major version 10, server major version 11.
Some psql features might not work.
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.
登陆信息中,显示了SSL Connection,说明已经启用ssl。