从数据加密到PostgreSQL SSL认证连接

为了保证数据库连接的安全性能,PostgreSQL允许使用SSL证书的方式去连接数据库,这无疑大大加强了数据访问的安全性能。
在讲解PostgreSQL中SSL的使用前,我们先来了解下什么是SSL证书。

1、数据加密

首先我们先来聊聊什么是数据加密。

1.1、对称加密

数据加密这也是和我们生活中息息相关的,可能你不清楚什么是加密算法,不过你可能有过这样的经历:在读书的时候,每当考试的时候总会有人想尽办法去作弊,当然我想总不会有人蠢到考试的时候在监考老师眼皮地下像平时说话一样,第一题选A,第二题选B这样交流。这种蠢办法就是我们常说的”明文“。

那经常见到的方式是什么呢?比方说A同学和B同学考试前先相互约定好”暗号”——“摸头表示选A,摸下巴表示选B等等”。那这个暗号就是“密钥”,通过这个密钥我们将想要传递的信息“ABCD”转化成了“摸头摸下巴”,有了这个密钥,那就可以光明正大的作弊了。

这种加密方式便是对称加密,即A通过密钥将数据加密,而B也是通过同样的密钥将数据解密。

1.2、非对称加密

通过刚刚的方法我们已经可以把数据进行加密进行传递了,但是有个问题,万一A同学和B同学在考试前偷偷约定“暗号”的时候,不小心被监控老师听到了,那么等到考试的时候他们”摸头摸下巴“进行数据传递时,监控老师一眼就能看出他们是在作弊了。

前面这种通过”公钥“进行加密的方式显然安全性很低,只要被第三者知道了密钥那么数据便相当于是”明文“传输了。

既然这种方式安全性不足,那么人们就想到了另一种通过”公钥“和”私钥“的方式进行数据加密。即每个人都会生成一个自己的”公钥“和”私钥“对,”私钥“由自己保管,”公钥“用来发送给别人。

例如:

A说:”我的公钥是sdsfj$&!sds,请用这个公钥进行加密”
B说:”好的,加密后的信息为hsdb!*&sds,请查收“
A说:”收到“

那么对于其它人来看显然是不明白A和B两个人说的是啥,虽然A将公钥发了出来,所有人都可以看见,但是用A的公钥加密的信息只能通过A自己的私钥才能解密,所以这样就保证了数据的安全。

这便是非对称加密,通过这种方式,只要保证自己的私钥安全,那么信息就不会被别人破解。必将常见的SSH、HTTPS等都是通过这种方式进行加密的。

1.3、电子证书

上面我们说的非对称加密看上去似乎信息不会被破解,但是仍然存在漏洞。如果A和B的对话被第三个人C看到了,那么C完全可以这么做:

C:“hi,B兄,我换了新的公钥hsdb$%wew,请用这个公钥将数据加密发给我”
B:“好的,兄弟,我要说的是sdh!**iop”
C:“收到”

可以看到,非对称加密存在的问题是:对于B用户来说他并不知道和他对话的人究竟是不是A,别人完全可以冒充A,然后将自己的公钥发给B,然后B利用这个公钥去加密再把信息发出去,自然信息就泄露了。

这个时候你可能想这个好办,A和B既然认识,那么他们不会想个“暗号”吗?于是有了下面的对话:

A:“hi,B兄,这是我的公钥ljbd%^&sqwe”
B:“好的,歪比歪比?”
A:“外比巴卜”
B:“好兄弟,你确实是A,我要传给你的信息是iubs!*Fsw”
A:“好的,收到”

通过上面的方式我们可以看到,A和B约定了一个暗号,B在发送信息前先通过暗号确认了A的身份。但是这种方式C看到了就想”当我是*吗?我也知道你们的暗号了”,接着C也可以通过这个暗号和B进行对话。

C:“hi,B兄,这是我的公钥mnbd%^&ooqwe”
B:“好的,歪比歪比?”
C:“外比巴卜”
B:“好兄弟,你确实是A,我要传给你的信息是iuops!*Fsw”
C:“好的,收到”

接着B又被骗了,于是B痛定思痛,想到了一个办法,当C再次和B对话时:

C:“hi,B兄,这是我的公钥mnbd%^&ooqwe”
B:“好的,把你的证书拿出来我看下”
C:“啊?啥证书?”
B:“你这个死骗子!”

原来B想到了一个办法,去找另一个人D,D和他说”我做一张证书发给A,这样你看到这个证书就知道是A了“。
但是B经过这么多次上当受骗之后显然也变机灵了,对D说“现在办假证的这么多,我咋知道证书是真是假呢?”
D告诉他”这个好办,我给你一样东西,你用这个就知道证书是真是假了“
B忙问”啥宝贝,验钞机吗???“
D说”我自己的公钥!“

原来D也有自己的公钥和私钥,D在证书上将A的信息用他的私钥制作成签名,然后把公钥给了B,这样B通过D给的公钥就知道证书上的信息是不是正确的了。

这里显然D的公钥是至关重要的一样东西,这便是我们常说的”根证书“!

大家可以想想,是不是我们在访问某些安全级别高的网站时,网页都会弹出一个对话框然你先去下载证书。这里的网页就是B,我们自己的客户端就是A,我们想要去B传输信息给我们,B首先会找我们要证书,所以我们只有下载了证书之后B才会允许和我们之间进行信息传输。

2、SSL证书使用

2.1、SSL证书简介

当我们使用SSL证书访问数据库也是如此,数据库会需要我们客户端提供证书才允许访问。
而SSL证书认证也分为单向和双向两种认证方式:双向认证 SSL 协议要求服务器和用户双方都有证书。单向认证 SSL 协议不需要客户拥有CA证书,服务器端不会验证客户证书,以及在协商对称密码方案,对称通话密钥时,服务器发送给客户的是没有加过密的(这并不影响 SSL 过程的安全性)密码方案。

2.2、PostgreSQL配置单向SSL认证连接

想要我们的pg数据库支持SSL连接,首先需要确保服务器有安装openssl:

yum -y install openssl openssl-devel

接着在编译安装时指定开启ssl

./configure --prefix=/home/pg14/pgsql14.1 --with-openssl 

首先我们先演示下如何配置单向SSL认证,先要为服务器创建一个有效期为365天的简单自签名证书:

openssl req -new -x509 -days 365 -nodes -text -out server.crt \
  -keyout server.key -subj "/CN=cnndwpmesp1T"

然后执行:

chmod og-rwx server.key

接着修改postgreql.conf配置文件:

ssl=on
ssl_cert_file='/home/pg10/openssl/server.crt'
ssl_key_file='/home/pg10/openssl/server.key'

重启数据库,然后进行连接:

psql "host=localhost user=postgres dbname=postgres password=1qaz@WSX sslmode=require"
psql (12.4)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

postgres=# 

2.3、PostgreSQL配置双向SSL认证连接

双向SSL认证配置我们需要根服务器来为客户端、数据库颁发证书。
这里我们使用5台服务器演示:

server a, 根服务器1, 用于给客户端颁发证书    
server b, 根服务器2, 给授权机构3签名发证    
server c, 根服务器2的授权机构3, 用于给数据库颁发证书    
server d, 数据库服务器    
server e, 客户端    

server c是用来模拟授权机构,如果不清楚授权机构的含义,可以理解成权威机构server a要为全球的服务器办法证书,十分繁忙,因此需要将他的权限授给下面的一个个授权机构,有点类似代理商的概念。

–server a,根服务器1:
生产公钥ca1.crt,私钥ca1.key

mkdir keys certs    
chmod og-rwx keys certs
openssl req -new -x509 -days 3650 -nodes -out certs/ca1.crt -keyout keys/ca1.key -subj "/CN=172.23.11.142" 

–server b,根服务器2:

mkdir keys certs    
chmod og-rwx keys certs
openssl req -new -x509 -days 3650 -nodes -out certs/ca2.crt -keyout keys/ca2.key -subj "/CN=172.23.11.143"   

–server c,根服务器3:

openssl req -new -nodes -text -out intermediate.csr -keyout intermediate.key -subj "/CN=172.23.11.144"    
chmod og-rwx intermediate.key   

然后将intermediate.csr发送到server b上进行盖章。

server b上执行:
openssl x509 -req -in intermediate.csr -text -days 1825 -extensions v3_ca -CA certs/ca2.crt -CAkey keys/ca2.key -CAcreateserial -out intermediate.crt

Signature ok
subject=/CN=172.23.11.144
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number:
            87:05:b6:07:e6:3e:5b:b4
    Signature Algorithm: NULL
        Issuer: CN=172.23.11.144
        Validity
            Not Before: May 31 05:46:30 2021 GMT
            Not After : May 30 05:46:30 2026 GMT
        Subject: CN=172.23.11.144
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:c9:46:74:61:50:27:20:d6:73:44:7d:30:14:b0:
                    91:69:60:9c:2e:1c:b8:96:f1:34:c5:79:10:10:0e:
                    8f:b4:0a:20:d1:b8:2b:42:53:da:55:6b:91:f9:d4:
                    fb:83:ea:66:42:85:28:d8:f1:2e:15:e6:77:fc:09:
                    a9:bf:e0:d7:d7:45:e5:6d:4c:90:40:9b:b0:92:92:
                    5f:69:77:84:97:a8:33:fa:b1:75:40:af:23:e1:90:
                    27:e3:eb:93:82:d4:7d:41:0b:98:bc:46:a3:93:65:
                    7a:d1:15:13:53:60:04:32:74:cb:f2:a0:db:55:c9:
                    2b:ae:a3:34:d8:8e:65:a8:da:3d:7b:30:f8:ee:7f:
                    35:37:0d:fd:52:e9:94:ff:30:f6:43:e7:ff:2c:5c:
                    fd:68:31:0b:84:8a:09:ed:33:c3:47:a3:6d:53:7d:
                    99:a9:ad:b3:a6:e4:67:90:42:73:7f:35:6f:0c:85:
                    fd:bd:52:1b:57:e8:1d:5a:75:a5:7b:02:70:42:01:
                    49:f7:ee:e6:bf:58:2d:de:9b:7c:c9:c1:c7:f9:f5:
                    c2:d0:4c:c7:73:c6:f3:05:d5:de:7b:03:b5:ea:fe:
                    f8:27:52:98:43:ab:75:be:eb:83:42:f3:43:89:5a:
                    5f:47:76:4c:d6:fa:98:aa:af:e8:d5:3a:a1:8b:71:
                    63:fd
                Exponent: 65537 (0x10001)
    Signature Algorithm: NULL
Getting CA Private Key

接着将盖完章的文件再传回给server c

–server d,数据库服务器:
生成key、证书签名申请文件:

openssl req -new -nodes -text -out server.csr -keyout server.key -subj "/CN=172.23.10.37"    
chmod og-rwx server.key   

然后将server.csr发给server c进行盖章:
openssl x509 -req -in server.csr -text -days 365 -CA intermediate.crt -CAkey intermediate.key -CAcreateserial -out server.crt

Signature ok
subject=/CN=172.23.10.37
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number:
            e3:ae:d1:f8:35:55:1b:17
    Signature Algorithm: NULL
        Issuer: CN=172.23.10.37
        Validity
            Not Before: May 31 05:48:52 2021 GMT
            Not After : May 31 05:48:52 2022 GMT
        Subject: CN=172.23.10.37
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:c7:ce:bb:99:b8:b0:45:ea:2e:10:84:f2:79:68:
                    2b:6b:07:0a:52:e4:d4:cb:2b:74:fe:5e:48:f4:17:
                    7e:17:92:d4:1a:8f:0c:75:cd:ac:1c:7e:7a:a4:c7:
                    1d:94:7c:95:1f:b2:73:93:f0:00:b0:3a:0a:e4:7a:
                    a6:39:91:eb:0b:66:95:37:36:8f:bc:3a:93:99:ac:
                    42:ac:99:e6:a3:bc:26:0f:17:84:e7:00:07:77:cb:
                    bd:ea:53:c5:58:65:08:e3:e6:32:18:b4:e9:64:4f:
                    10:d6:cc:22:2d:e7:ca:fc:b8:d5:84:f7:1f:61:11:
                    a0:eb:14:8c:d7:42:b3:08:8e:9c:ab:61:35:9b:45:
                    c7:23:96:50:16:d1:e7:ab:9f:b4:31:bf:bd:18:02:
                    47:50:cb:1e:c7:0c:c0:48:2e:04:bc:e2:0b:0c:2d:
                    d0:81:3b:90:ad:24:37:56:8b:a1:0a:db:55:d6:88:
                    37:24:1a:86:5e:71:b7:6c:b5:27:40:63:2c:49:c2:
                    8a:40:14:9e:71:1f:02:e8:f8:d3:0e:fe:72:6b:2d:
                    bb:ef:f0:a1:eb:61:4e:ef:5c:71:1a:e3:fd:7c:1e:
                    ff:6b:a3:d2:de:4d:1b:e1:a8:2a:86:43:e0:ae:a6:
                    53:75:54:5e:d3:23:44:cb:a8:96:d7:89:67:3f:17:
                    ae:2f
                Exponent: 65537 (0x10001)
    Signature Algorithm: NULL
Getting CA Private Key

盖章后的证书server.crt发给server d,这里我们将server.crt, server.key 都放到 $PGDATA 目录中, 设置为600权限

–server e,客户端:
生成key、证书签名申请文件.

openssl req -new -nodes -text -out client.csr -keyout client.key -subj "/CN=172.23.10.37"    
chmod og-rwx client.key   

把server.csr发给根服务器1去盖章
openssl x509 -req -in client.csr -text -days 365 -CA certs/ca1.crt -CAkey keys/ca1.key -CAcreateserial -out client.crt

Signature ok
subject=/CN=172.23.10.37
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number:
            a3:6b:8b:8e:b1:c7:f3:39
    Signature Algorithm: NULL
        Issuer: CN=172.23.10.37
        Validity
            Not Before: May 31 05:50:50 2021 GMT
            Not After : May 31 05:50:50 2022 GMT
        Subject: CN=172.23.10.37
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:cd:98:6c:0b:60:91:82:b4:03:31:9d:12:b5:24:
                    7b:7f:7b:90:de:e0:f1:57:04:24:d9:c5:57:cc:e3:
                    f0:6a:b3:2e:c4:3d:98:c6:9e:d7:03:4f:85:1f:3c:
                    bd:9f:be:94:5c:f3:21:77:5a:00:59:e5:76:c8:b4:
                    83:91:a5:90:d1:68:c2:5f:41:d7:eb:a0:c3:4d:c8:
                    8e:21:73:ff:5a:e4:6b:0b:6e:1b:c3:ec:31:85:e7:
                    6b:6c:c2:6f:54:b4:51:f4:42:47:05:6e:35:32:78:
                    f8:96:49:32:dc:71:26:26:05:3d:fe:b5:9a:24:9c:
                    8a:23:07:48:93:14:ea:01:ce:64:c3:20:f5:19:b2:
                    9c:f1:19:65:e9:64:23:e9:d6:a8:ab:bb:12:e7:02:
                    73:33:64:85:fe:4e:68:64:49:b0:ae:24:cc:9c:80:
                    89:af:e5:e9:3a:b2:79:82:7d:ce:16:ac:c6:44:12:
                    77:ef:16:79:22:16:e1:82:55:a0:5a:8d:5c:1b:70:
                    fe:08:36:bc:37:53:1a:a5:cf:c2:43:44:4e:0b:3d:
                    f5:8d:b3:f6:e8:9c:48:d8:4b:d3:21:cc:97:96:94:
                    70:fb:8c:f7:fd:b9:a8:4d:56:fd:8a:c4:d4:c9:8a:
                    52:85:23:19:e4:48:dd:f1:df:bc:82:73:df:45:09:
                    3e:9d
                Exponent: 65537 (0x10001)
    Signature Algorithm: NULL
Getting CA Private Key

盖章后的证书client.crt再发送回server e,我们把client.crt和client.key 都放到客户端的$PGHOME目录中 , 设置为600权限

除此之外,我们还需要把办证机构的公钥分发下去, 让他们可以辨别证书真伪。

–server d,数据库服务器:
将server a中的ca1.crt 文件内容写入 server d的 $PGDATA/ca1.crt文件中。

然后配置数据库参数:

ssl = on    
ssl_ca_file = 'ca1.crt'    
ssl_cert_file = 'server.crt'    
ssl_crl_file = ''    
ssl_key_file = 'server.key'  

重启数据库生效。

–server e,客户端服务器:
需要校验数据库服务器证书真伪, 所以需要给数据库服务器颁发证书的机构的公钥。
我们要将server b上的ca2.crt文件和server c上intermediate.crt文件的内容复制到客户端服务器的~/.postgresql/ca2_int.crt文件中。

授权:

chmod 600 ~/.postgresql/ca2_int.crt     

连接测试:

pg14@cnndr4pptliot->  export PGSSLMODE="verify-ca"

pg14@cnndr4pptliot-> export PGSSLROOTCERT="/home/pg14/pgdata/ca2_int.crt"

pg14@cnndr4pptliot-> psql -h localhost -p 2021 -U bill postgres
psql (14beta1)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

postgres=# 

参考链接:
http://postgres.cn/docs/12/ssl-tcp.html
https://segmentfault.com/a/1190000004461428

上一篇:Linux 服务器常用命令(CRT)


下一篇:SVN提交前准备