暂无图片
暂无图片
7
暂无图片
暂无图片
暂无图片

Postgresql开启ssl认证

叶同学专栏 2021-09-18
5290

PostgreSQL的SSL连接分两块

1、服务端的SSL验证:用SSL连接代替明文连接以防止网络包被窃听和防止他人伪装成服务器
2、客户端的SSL验证:用客户端SSL证书登录代替密码登录。

服务端证书类型

证书可以分为三类

  • 自签名证书:证书颁发者和主题是一样,自己给自己颁发,此类证书不需要根证书认证,所以是不安全的,是无法防止他人伪装成服务器,但如果服务器是按IP地址连接的,也许对这项要求不是很注重,所以自签名证书就够了

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

    CN=后面是 证书主题如域名或IP地址,此命令生成证书文件server.crt 和私钥文件 server.key ,请将它们部署在数据库服务器上,并设好ssl_cert_file、ssl_key_file参数。

  • 建立本地根CA,再由根CA签发服务器证书
    1、建立本地根CA

    openssl req -new -nodes -text -out root.csr -keyout root.key -subj "/CN=XX.XX.XX"
    openssl x509 -req -in root.csr -text -days 3650 -extfile openssl.cfg -extensions v3_ca -signkey root.key -out root.crt

    生成两个有用的文件 root.key (根CA的私钥,请离线保存), root.crt(根CA证书)

    2、由根CA颁发服务器证书:

    openssl req -new -nodes -text -out server.csr  -keyout server.key -subj "/CN=XX.XX.XX"
    openssl x509 -req -in server.csr -text -days 365 -CA root.crt -CAkey root.key -CAcreateserial -out server.crt

    生成两个有用的文件 server.key(服务器私钥),server.crt(服务器证书)

    请将server.key和server.crt部署在服务器,本地根证书root.crt部署在客户端,PostgreSQL客户端不依赖操作系统的证书,需要自行制定根证书的存放地方,所以即使是自行发行的根证书,也认为是合法的。在windows下根证书默认存放目录是appdata/postgresql目录下。

  • 公共CA签署的证书
    由知名CA签署的证书,大部分要收使用费,一般用在有域名的服务器上。申请后一般会得三个文件服务器私钥server.key、服务器证书server.crt、颁布者CA自己的证书。请将server.key和server.crt部署在服务器。客户端的公共root.crt可从 libcurl网站获取最新的pem文件,此文件含有目前世界已知所有CA的证书,将此文件改名为root.crt,并部署在客户端的$appdata/postgresql目录下,若在sslmode=verify-ca模式登陆失败,可能是颁布者CA的证书不含在root.crt里,可将颁布者CA的证书连接到root.crt(文本格式可编辑),也可连接到部署在服务器的服务器证书server.crt,建议后者。

数据库开启openssl

首先查看编译安装时有无开启openssl

[pg11@yejf ~]$ pg_config|grep CONFIGURE
CONFIGURE = '--prefix=/usr/local/pg11' '--with-perl' '--with-python'

没有开启的话,如果没有加上--with-openssl参数,在打开ssl配置,启动pg的时候会报错

SSL is not supported by this build

需要重新编译添加--with-openssl参数,让pg支持ssl认证方式

重新编译

[root@yejf]/opt/postgresql-11.9# export PATH=/usr/local/pg11/bin:$PATH
[root@yejf]/opt/postgresql-11.9# ./configure --prefix=/usr/local/pg11 --with-perl --with-python --with-openssl
[root@yejf]/opt/postgresql-11.9# make clean
[root@yejf]/opt/postgresql-11.9# make && make install

编译报错

configure: error: library 'crypto' is required for OpenSSL
解决
yum -y install openssl-devel 

再次查看已有--with-openssl支持

[pg11@yejf ~]$ pg_config|grep CONFIGURE
CONFIGURE = '--prefix=/usr/local/pg11' '--with-perl' '--with-python' '--with-openssl'

使用opsnessl生成密钥和自签名证书

生成一个有效期365天的简单自签名证书

[pg11@yejf ~]$ openssl req -new -x509 -days 365 -nodes -text -out server.crt -keyout server.key -subj "/CN=192.168.43.100"
Generating a 2048 bit RSA private key
.....................................................................+++
.................................................................................................+++
writing new private key to 'server.key'
-----

[pg11@yejf ~]$ ll
总用量 8
-rw-rw-r-- 1 pg11 pg11 4087 9月   2 11:32 server.crt
-rw-rw-r-- 1 pg11 pg11 1704 9月   2 11:32 server.key

openssl req 参数说明

-new        :创建一个证书请求文件,会交互式提醒输入一些信息,这些交互选项以及交互选项信息的长度值以及其他一些扩展属性在配置文件(默认为
         :openssl.cnf,还有些辅助配置文件)中指定了默认值。如果没有指定"-key"选项,则会自动生成一个RSA私钥,该私钥的生成位置
         :也在openssl.cnf中指定了。如果指定了-x509选项,则表示创建的是自签署证书文件,而非证书请求文件

-x509         :指定该选项时,将生成一个自签署证书,而不是创建证书请求。一般用于测试或者为根CA创建自签名证书

-days n       :指定自签名证书的有效期限,默认30天,需要和"-x509"一起使用。

-nodes      :默认情况下,openssl req自动创建私钥时都要求加密并提示输入加密密码,指定该选项后则禁止对私钥文件加密

-text         :以文本格式打印证书请求

-out filename :证书请求或自签署证书的输出文件,也可以是其他内容的输出文件,不指定时默认stdout

-keyout filename :指定自动创建私钥时私钥的存放位置,若未指定该选项,则使用配置文件中default_keyfile指定的值,默认该值为privkey.pem

-subj args    :替换或自定义证书请求时需要输入的信息,并输出修改后的请求信息。args的格式为"/type0=value0/type1=value1..."
           :如果value为空,则表示使用配置文件中指定的默认值,如果value值为".",则表示该项留空。其中可识别type(man req)有:
           :C是Country、ST是state、L是localcity、O是Organization、OU是Organization Unit、CN是common name等

修改权限

[pg11@yejf ~]$ chmod 600 server.key
[pg11@yejf ~]$ ll
总用量 8
-rw-rw-r-- 1 pg11 pg11 4087 9月   2 11:32 server.crt
-rw------- 1 pg11 pg11 1704 9月   2 11:32 server.key

复制认证文件到数据目录下

[pg11@yejf ~]$ cp server.crt $PGDATA
[pg11@yejf ~]$ cp server.key $PGDATA

配置postgres.conf和pg_hba.conf文件

--修改postgresql.conf
ssl=on
ssl_cert_file='server.crt'
ssl_key_file='server.key'
#ssl_ca_file 是用在客户端SSL认证上,服务端的SSL验证和此参数无关

--修改pg_hba.conf,新增ssl认证连接规则
hostssl all all 0.0.0.0/0 md5
hostnossl all all 0.0.0.0/0 reject

重启数据库,连接数据库可以看到ssl生效

[root@nna ~]#  psql -U pg11 "host=192.168.43.100 dbname=test port=1111 user=pg11"
Password for user pg11: 
psql (11.13, server 11.9)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.
test=

验证传输加密

没有开启ssl

在服务器使用tcpdump抓包

tcpdump -i ens33 host 192.168.43.128 -w ./nossl.cap

使用wireshark工具对抓取的包解析,传输的sql会被解析到

开启ssl

tcpdump抓包

[root@yejf]~# tcpdump -i ens33 host 192.168.43.128 -w ./ssl.cap

wireshark工具对抓取的包解析,看到传输的sql已经是加密过的

SSL双向认证和SSL单向认证的区别

双向认证 SSL 协议要求服务器和用户双方都有证书。单向认证 SSL 协议不需要客户拥有CA证书,服务器端不会验证客户证书,以及在协商对称密码方案,对称通话密钥时,服务器发送给客户的是没有加过密的(这并不影响 SSL 过程的安全性)密码方案。这样,双方具体的通讯内容,都是加过密的数据,如果有第三方攻击,获得的只是加密的数据,第三方要获得有用的信息,就需要对加密的数据进行解密,这时候的安全就依赖于密码方案的安全。而幸运的是,目前所用的密码方案,只要通讯密钥长度足够的长,就足够的安全。这也是我们强调要求使用128位加密通讯的原因。

一般Web应用都是采用SSL单向认证的,原因很简单,用户数目广泛,且无需在通讯层对用户身份进行验证,一般都在应用逻辑层来保证用户的合法登入。但如果是企业应用对接,情况就不一样,可能会要求对客户端(相对而言)做身份验证。这时就需要做SSL双向认证。

由于单向认证和双向认证的区别仅在于创建连接阶段,数据的传输均为加密的,因此客户端与PG服务端的连接采取SSL单向认证即可,即仅在PG Server端配置SSL证书

postgresql开启双向ssl认证

服务器端需生成三个文件: root.crt(根证书)
server.crt(服务器证书)
server.key(服务器私钥)

生成服务器私钥

--需要输入密码
[pg11@yejf yejf]$ openssl genrsa -des3 -out server.key 2048
Generating RSA private key2048 bit long modulus
.......................................+++
.......................................................+++
is 65537 (0x10001)
Enter pass phrase for server.key:
Verifying - Enter pass phrase for server.key:

--去掉密码,不然数据库启动会有问题
[pg11@yejf yejf]$ openssl rsa -in server.key -out server.key
Enter pass phrase for server.key:
139704832321424:error:28069065:lib(40):UI_set_result:result too small:ui_lib.c:831:You must type in 4 to 1023 characters
Enter pass phrase for server.key:
writing RSA key

创建私钥server.key,使用des3算法,有效期2048天

生成服务器证书

[pg11@yejf yejf]$ openssl req -new -key server.key -days 2650 -out server.crt -x509
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]:
State or Province Name (full name) []:
Locality Name (eg, city) [Default City]:
Organization Name (eg, company) [Default Company Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:
Email Address []:

生成根证书

由于没有公证机构提供,只能使用自签名证书,因此可以将服务器证书作为根证书

[pg11@yejf yejf]$ cp server.crt root.crt

复制认证文件到数据目录下及设置权限

cp server.key $PGDATA
cp server.crt $PGDATA
cp root.crt $PGDATA
chmod 600 $PGDATA/server.key

修改配置文件

[pg11@yejf pg11data]$ tail -5 postgresql.conf 
ssl=on
ssl_cert_file='server.crt'
ssl_key_file='server.key'
ssl_ca_file='root.crt'

[pg11@yejf pg11data]$ tail -5 pg_hba.conf 
hostssl all all 0.0.0.0/0 cert
hostnossl all all 0.0.0.0/0 reject

postgresql.conf增加ssl_ca_file

pg_hba.conf认证模式改成cert并且是hostssl连接

配置客户端证书

创建客户端私钥
--要求输入密码
[pg11@yejf yejf]$ openssl genrsa -des3 -out postgresql.key 2048
Generating RSA private key2048 bit long modulus
.......................................+++
....................................+++
is 65537 (0x10001)
Enter pass phrase for postgresql.key:
Verifying - Enter pass phrase for postgresql.key:


--去除密码
[pg11@yejf yejf]$ openssl rsa -in postgresql.key -out postgresql.key 
Enter pass phrase for postgresql.key:
writing RSA key

生成客户端证书签名请求
[pg11@yejf yejf]$ openssl req -new -key postgresql.key -out postgresql.csr -subj "/CN=pg11"

/CN=pg11,pg11是连接数据库的用户名,需要指定,不然会报错

使用ca根证书对客户端证书签名生成公钥
[pg11@yejf yejf]$ openssl x509 -req -days 3650 -in postgresql.csr -CA root.crt -CAkey server.key -out postgresql.crt -CAcreateserial
Signature ok
subject=/CN=pg11
Getting CA Private Key

把相关证书拷贝到客户端
scp postgresql.key root@192.168.43.128:/root/.postgresql    
scp postgresql.crt root@192.168.43.128:/root/.postgresql    
scp root.crt root@192.168.43.128:/root/.postgresql

重启数据库

客户端连接

没有证书情况下,提示需要ca证书来连接

[root@nna ~]#  psql -U pg11 "host=192.168.43.100 dbname=test port=1111 user=pg11"
psql: FATAL:  connection requires a valid client certificate
FATAL:  pg_hba.conf rejects connection for host "192.168.43.128", user "pg11", database "test", SSL off

[root@nna ~]#  psql -U pg11 "host=192.168.43.100 dbname=test port=1111 user=pg11 sslmode=verify-ca"
psql: root certificate file "/root/.postgresql/root.crt" does not exist
Either provide the file or change sslmode to disable server certificate verification.

修改文件权限
[root@nna .postgresql]# chmod 600 /root/.postgresql/postgresql.key

使用ssl连接
[root@nna .postgresql]# psql -U pg11 "host=192.168.43.100 dbname=test port=1111 user=pg11 sslmode=verify-ca"
psql (11.13, server 11.9)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

test=

使用证书外用户连接会失败

[root@nna .postgresql]# psql -U pg11 "host=192.168.43.100 dbname=test port=1111 user=test sslmode=verify-ca"
psql: FATAL:  certificate authentication failed for user "test"

参考链接

https://mp.weixin.qq.com/s/cToLxIEMLrJH3UXTiD5F3Q
https://blog
.csdn.net/Loiterer_Y/article/details/106683660?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.control


文章转载自叶同学专栏,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论