当前位置: 首页 > article >正文

PostgreSQL加密连接SSL配置

PostgreSQL加密连接SSL配置

环境说明

操作系统主机名IP类型说明
CentOS Linux release 7.6.1810 (Core)centos7.6192.168.1.150PostgreSQL ServerPostgreSQL 12.17
CentOS Linux release 7.6.1810 (Core)testLinux192.168.1.200clientpsql 13.11
Winserver 2012192.168.1.99clientnavicat

SSL说明

什么是SSL?

SSL的全名叫做secure socket layer(安全套接字层),最开始是由一家叫网景的互联网公司开发出来,主要是防止信息在互联网上传输的时候不被窃听或者篡改,后来网景公司提交SSL给ISOC组织做标准化,改名为TLS。

什么是openssl?

openssl 是目前最流行的 SSL 密码库工具,其提供了一个通用、健壮、功能完备的工具套件,用以支持SSL/TLS 协议的实现。

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

双向认证 SSL 协议要求服务器和用户双方都有证书。

单向认证 SSL 协议不需要客户拥有CA证书,服务器端不会验证客户证书,以及在协商对称密码方案,对称通话密钥时,服务器发送给客户的是没有加过密的(这并不影响 SSL 过程的安全性)密码方案。

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

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

前提条件:必须使用openssl来编译安装pg,否则后期不能启用ssl加密连接

查看postgresql是否使用openssl选项编译安装,没有则需重新编译:

[postgres@centos7 ~]$ pg_config|grep CONFIGURE|grep ssl
CONFIGURE = '--prefix=/postgresql/pg12' '--with-openssl'
[postgres@centos7 ~]$

在启用了–with-openssl这个编译选项的情况下,ssl_library的参数值是OpenSSL,否则为空。

[postgres@centos7 ~]$ psql -c "select name,setting,unit,context from pg_settings where name ~* 'ssl_library';"
    name     | setting | unit | context  
-------------+---------+------+----------
 ssl_library | OpenSSL |      | internal
(1 row)

配置单向SSL认证连接

1、为服务器创建一个有效期为365天的简单自签名证书,创建服务端证书和私钥文件:

su - postgres
mkdir ~/openssl
openssl req -new -x509 -days 365 -nodes -text -subj '/CN=postgres' -out ~/openssl/server.crt -keyout ~/openssl/server.key
chmod 600 ~/openssl/server.key

创建过程

[postgres@centos7 ~]$ mkdir ~/openssl
[postgres@centos7 ~]$ openssl req -new -x509 -days 365 -nodes -text -subj '/CN=postgres' -out ~/openssl/server.crt -keyout ~/openssl/server.key
Generating a 2048 bit RSA private key
.............+++
.+++
writing new private key to '/home/postgres/openssl/server.key'
-----
[postgres@centos7 ~]$ chmod 600 ~/openssl/server.key
[postgres@centos7 ~]$ ll openssl/
total 8
-rw-rw-r-- 1 postgres postgres 4058 Nov 11 08:16 server.crt
-rw------- 1 postgres postgres 1704 Nov 11 08:16 server.key
[postgres@centos7 ~]$

2、修改postgreql.conf配置文件

cat >> /postgresql/pgdata/postgresql.conf << "EOF"
ssl = on
ssl_cert_file = '/home/postgres/openssl/server.crt'
ssl_key_file = '/home/postgres/openssl/server.key'
EOF

参数说明

参数说明
ssl支持SSL连接。默认是关闭的。这个参数只能在服务器启动时设置。SSL通信只能通过TCP/IP连接进行。
ssl_cert_file指定包含SSL服务器证书的文件的名称。默认是server.crt,相对路径相对于数据目录$PGDATA。此参数只能在服务器启动时设置。
ssl_key_file指定包含SSL服务器私钥的文件的名称。默认是server.key,相对路径相对于数据目录。此参数只能在服务器启动时设置。

要在SSL模式下启动,必须存在包含服务器证书和私钥的文件。默认情况下,这些文件将被命名为server.crt和server.key。但是可以使用配置参数ssl_cert_file和ssl_key_file指定其他名称和位置。

在linux系统中,server.key必须禁止其他用户的访问权限。我们需要通过chown命令将server.key的访问权限设置成600。

SSL打开后,此时服务器将侦听同一TCP端口上的正常连接和SSL连接,并与任何连接客户机协商是否使用SSL。

3、重启数据库,创建sslinfo扩展,验证ssl连接

pg_ctl start
psql -c "create extension sslinfo;"


[postgres@centos7 ~]$ psql -c "\dx"
                    List of installed extensions
  Name   | Version |   Schema   |            Description             
---------+---------+------------+------------------------------------
 plpgsql | 1.0     | pg_catalog | PL/pgSQL procedural language
 sslinfo | 1.2     | public     | information about SSL certificates
(2 rows)

连接的时候需要加上-h参数,否则不是以ssl连接的

[postgres@centos7 ~]$ psql -U postgres
psql (12.17)
Type "help" for help.

postgres=# select ssl_is_used();
 ssl_is_used 
-------------
 f
(1 row)
postgres=# exit
[postgres@centos7 ~]$
[postgres@centos7 ~]$ psql -h localhost
psql (12.17)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

postgres=# select ssl_is_used();
 ssl_is_used 
-------------
 t
(1 row)

postgres=# exit
[postgres@centos7 ~]$
[postgres@centos7 ~]$ psql 'host=localhost user=postgres dbname=postgres password=postgres sslmode=require'
psql (12.17)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

postgres=# select ssl_is_used();
 ssl_is_used 
-------------
 t
(1 row)

postgres=# exit
[postgres@centos7 ~]$ 

配置双向SSL认证连接

双向SSL认证配置我们需要根服务器来为客户端、数据库颁发证书。

服务器端证书配置

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

1、生成服务器私钥server.key

服务器私钥生成后,需移除密码,否则数据库重启时会出现异常。

cd $PGDATA
openssl genrsa -des3 -out server.key 2048
openssl rsa -in server.key -out server.key  #去掉证书的密码保护
chmod 400 server.key

目录根据实际情况,openssl 就是 openssl.org,genrsa 是 generate an RSA private key,des3 是加密算法。意思是生成一个 RSA 密钥,再将密钥用 des3 算法加密。

2、生成服务器证书server.crt

openssl req -new -key server.key -days 3650 -out server.crt -x509 -subj '/C=CN/ST=Shaanxi/L=Xian/O=163.com/CN=test/emailAddress=test@163.com'

subj参数说明:用于指定证书请求或自签名证书的主题信息。主题信息包括一系列的字段,如国家、组织、单位、通用名称等。下面是openssl -subj参数的可用选项:

全称缩写说明
Country Name (2 letter code) [AU]/C指定证书的国家代码,例如/C=CN表示中国
State or Province Name (full name) [Some-State]/ST指定证书的省/州
Locality Name (eg, city) []/L指定证书的城市/地区
Organization Name (eg, company) [Internet Widgits Pty Ltd]/O指定证书的组织名称
Organizational Unit Name (eg, section) []/OU指定证书的组织单位
Common Name (e.g. server FQDN or YOUR name) []/CN指定证书的通用名称,即证书的域名
Email Address []/emailAddress指定证书的电子邮件地址
/serialNumber=指定证书的序列号
/DN指定证书的颁发者名称
/DC指定证书的颁发者组织单位
/DNQ指定证书的颁发者通用名称
/DNQUALIFIER指定证书的颁发者限定符
/DNEMAIL指定证书的颁发者电子邮件地址

3、根证书root.crt

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

cp server.crt root.crt

服务器端数据库配置

1、postgresql.conf

cat >> /postgresql/pgdata/postgresql.conf << "EOF"
ssl=on
ssl_ca_file='root.crt'
ssl_key_file='server.key'
ssl_cert_file='server.crt'
EOF

2、pg_hba.conf

更改服务器的pg_hba.conf文件禁止用户以非SSL连接数据库。

PostgreSQL的客户机身份验证由一个配置文件控制,该配置文件通常名为pg_hba.conf,存储在数据库的数据目录中。(HBA代表基于主机的身份验证。),当initdb初始化数据目录时,将安装一个默认的pg_hba.conf文件。

pg_hba.conf文件的一般格式是一组记录,每行一个。其中每个记录指定连接类型、客户机IP地址范围(连接类型相关)、数据库名、用户名和用于匹配这些参数的连接的身份验证方法。具有匹配的连接类型、客户端地址、请求的数据库和用户名的第一条记录用于执行身份验证。不存在“穿透”或“备份”, 如果选择了一条记录,身份验证失败,则不考虑后续记录。如果没有记录匹配,则拒绝访问。

pg_hba.conf与ssl相关的配置有两个。

  • hostssl: 此记录匹配使用TCP/IP进行的连接尝试,但仅在使用SSL加密进行连接时才匹配。要使用此选项,必须使用SSL支持构建服务器。此外,必须通过设置SSL配置参数在服务器启动时启用SSL。
  • hostnossl:此记录类型具有与hostssl相反的行为;它只匹配不使用SSL的TCP/IP上的连接尝试。

使用使用host的话优先使用ssl认证,hostssl表示强制使用ssl, hostnossl 强制不使用ssl。

cat >> /postgresql/pgdata/pg_hba.conf <<"EOF"
hostssl all all 0.0.0.0/0 cert
EOF


[postgres@centos7 ~]$ egrep -v "^$|^#" /postgresql/pgdata/pg_hba.conf
local   all             all                                     trust
host    all             all             127.0.0.1/32            trust
host    all             all             ::1/128                 trust
host    replication     all             127.0.0.1/32            trust
host    replication     all             ::1/128                 trust
hostssl all all 0.0.0.0/0 cert

重启数据库

pg_ctl restart

普通连接会报错

[postgres@testLinux ~]$ psql -U postgres -h 192.168.1.150
psql: error: FATAL:  connection requires a valid client certificate
FATAL:  no pg_hba.conf entry for host "192.168.1.200", user "postgres", database "postgres", SSL off
[postgres@testLinux ~]$

客户端配置SSL证书

开启客户端SSL连接也需要三个文件

  • root.crt (trusted root certificate) :root.crt(根证书)
  • postgresql.crt (client certificate) :postgresql.crt(客户端证书)
  • postgresql.key (private key) :postgresql.key(客户端私钥)

生成postgresql.key

cd $PGDATA
openssl genrsa -des3 -out postgresql.key 2048
openssl rsa -in postgresql.key -out postgresql.key  #去掉证书的密码保护

生成postgresql.crt

openssl req -new -key postgresql.key -out postgresql.csr -subj '/C=CN/ST=Shaanxi/L=Xian/O=163.com/CN=postgres/emailAddress=test@163.com'

openssl x509 -req -in postgresql.csr -CA root.crt -CAkey server.key -out postgresql.crt -CAcreateserial

说明:Common Name (e.g. server FQDN or YOUR name) []:postgres该项必须设置为要连接postgresql数据库的用户名,否则会默认使用当前计算机的用户名,导致证书使用时,认证失败。

测试连接

Linux

psql客户端使用ssl连接。

可以配置环境变量PGSSLCERT和PGSSLKEY来指定密钥和证书的位置。

在Linux环境中,需要将证书放在当前用户的.postgresql目录下

#将证书拷贝到客户端
su - postgres
mkdir .postgresql
scp 192.168.1.150:/postgresql/pgdata/root.crt /home/postgres/.postgresql/
scp 192.168.1.150:/postgresql/pgdata/postgresql.key /home/postgres/.postgresql/
scp 192.168.1.150:/postgresql/pgdata/postgresql.crt /home/postgres/.postgresql/
chmod 600 root.crt postgresql.key postgresql.crt

#使用以下命令测试连接(正常连接)
psql 'host=192.168.1.150 user=postgres dbname=postgres password=postgres sslmode=require'
psql "postgresql://postgres@192.168.1.150:5432/postgres?sslmode=require"
psql "postgresql://postgres@192.168.1.150:5432/postgres?ssl=true"
psql postgresql://postgres@192.168.1.150:5432/postgres?ssl=true

执行过程

[postgres@testLinux ~]$ pwd
/home/postgres
[postgres@testLinux ~]$ ll /home/postgres/.postgresql
total 12
-rw-------. 1 postgres postgres 1220 Nov 12 08:08 postgresql.crt
-rw-------. 1 postgres postgres 1675 Nov 12 08:07 postgresql.key
-rw-------. 1 postgres postgres 1334 Nov 12 08:06 root.crt
[postgres@testLinux ~]$
[postgres@testLinux ~]$ psql 'host=192.168.1.150 user=postgres dbname=postgres password=postgres sslmode=require'
psql (13.11, server 12.17)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

postgres=# exit
[postgres@testLinux ~]$ psql "postgresql://postgres@192.168.1.150:5432/postgres?sslmode=require"
psql (13.11, server 12.17)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

postgres=# exit
[postgres@testLinux ~]$ psql "postgresql://postgres@192.168.1.150:5432/postgres?ssl=true"
psql (13.11, server 12.17)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

postgres=# exit
[postgres@testLinux ~]$ psql postgresql://postgres@192.168.1.150:5432/postgres?ssl=true
psql (13.11, server 12.17)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

postgres=# exit
[postgres@testLinux ~]$

证书不在当前用户的.postgresql目录下,例如在/tmp目录下

cd /home/postgres/.postgresql
cp postgresql.crt postgresql.key root.crt /tmp/
rm -rf /home/postgres/.postgresql

psql postgresql://postgres@192.168.1.150:5432/postgres?ssl=true\&sslrootcert=/tmp/root.crt\&sslkey=/tmp/postgresql.key\&sslcert=/tmp/postgresql.crt

执行过程

[postgres@testLinux ~]$ ll /tmp/
total 12
-rw-------. 1 postgres postgres 1220 Nov 12 08:13 postgresql.crt
-rw-------. 1 postgres postgres 1675 Nov 12 08:13 postgresql.key
-rw-------. 1 postgres postgres 1334 Nov 12 08:13 root.crt
[postgres@testLinux ~]$ 
[postgres@testLinux ~]$ rm -rf /home/postgres/.postgresql
#.postgresql目录已经删除,所以以下连接会报错
[postgres@testLinux ~]$ psql 'host=192.168.1.150 user=postgres dbname=postgres password=postgres sslmode=require'
psql: error: FATAL:  connection requires a valid client certificate
[postgres@testLinux ~]$ 
#指定证书位置连接
[postgres@testLinux ~]$ psql postgresql://postgres@192.168.1.150:5432/postgres?ssl=true\&sslrootcert=/tmp/root.crt\&sslkey=/tmp/postgresql.key\&sslcert=/tmp/postgresql.crt
psql (13.11, server 12.17)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

postgres=# exit
[postgres@testLinux ~]$
Windows

在Windows环境中,可以将证书和密钥文件放在%appdata%\postgresql这个文件夹下

C:\Users\Administrator>echo %appdata%
C:\Users\Administrator\AppData\Roaming

C:\Users\Administrator>cd C:\Users\Administrator\AppData\Roaming

C:\Users\Administrator\AppData\Roaming>mkdir postgresql

C:\Users\Administrator\AppData\Roaming>cd postgresql

C:\Users\Administrator\AppData\Roaming\postgresql>dir/b
postgresql.crt
postgresql.key
root.crt

navicat连接测试:

root.crtpostgresql.crtpostgresql.key拷贝到%appdata%\postgresql这个文件夹后,不用输入密码就能连接

image-20241112195810883

删除%appdata%\postgresql这个文件夹后,指定证书位置:

使用普通连接方式将无法连接:

image-20241112194356222

需要使用SSL连接:

image-20241112194504242

image-20241112194730407

SSL加密等级说明

加密等级说明
disable只尝试非SSL连接
allow首先尝试非SSL连接,若失败再尝试SSL连接
prefer (default)首先尝试SSL连接,若失败再尝试非SSL连接
require只尝试SSL连接,若有根证书存在,等同于verify-ca
verify-ca只尝试SSL连接,并用根证书验证服务器证书是不是根CA签发的
verify-full只尝试SSL连接,并用根证书验证服务器证书是不是根CA签发的,且主题必须匹配连接域名或IP地址

SSL 模式描述

sslmode窃听保护MITM保护声明
disableNoNo我不关心安全性,并且我不想为加密增加负荷。
allow可能No我不关心安全性,但如果服务器坚持,我将承担加密带来的负荷。
prefer可能No我不关心安全性,但如果服务器支持,我希望承担加密带来的负荷。
requireYesNo我想要对数据加密,并且我接受因此带来的负荷。我信任该网络会保证我总是连接到想要连接的服务器。
verify-caYesDepends on CA policy我想要对数据加密,并且我接受因此带来的负荷。我想要确保我连接到的是我信任的服务器。
verify-fullYesYes我想要对数据加密,并且我接受因此带来的负荷。我想要确保我连接到的是我信任的服务器,并且就是我指定的那一个。

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

sslmode的默认值是prefer。如表中所示,这在安全性的角度来说没有意义,并且它只承诺可能的性能负荷。提供它作为默认值只是为了向后兼容,并且我们不推荐在安全部署中使用它。

参考资料

https://cloud.tencent.com/developer/information/openssl%20-subj%E5%8F%82%E6%95%B0%E6%9C%89%E5%93%AA%E4%BA%9B%E5%8F%AF%E7%94%A8%E9%80%89%E9%A1%B9-album


http://www.kler.cn/a/393949.html

相关文章:

  • SQL,力扣题目1127, 用户购买平台
  • 【数据结构】交换排序——冒泡排序 和 快速排序
  • docker镜像源,亲测可用,时间2024-11-14
  • 【数据结构与算法】第11课—数据结构之选择排序和交换排序
  • 封装el-menu
  • 车载空气净化器语音芯片方案
  • linux安装ansible
  • 微信小程序家政项目小程序
  • sqoop Oracle 导入到hive 日期时间消失
  • unity 玩家和炸弹切线计算方式
  • python 爱心邮件代码
  • 二叉树的遍历(手动)
  • 2025年法定节假日日历
  • 【Docker】Docker Compose部署单节点多容器应用
  • 从零开始的 Hugging Face 项目:我的首个在线 SQL 查询工具之旅20241111
  • 将python下载的依赖包传到没网的服务器
  • Docker基础概念
  • sentinel服务保护
  • SQL面试题——蚂蚁SQL面试题 会话分组问题
  • 【C语言】指针数组和数组指针的区别
  • 【MinIO】Python 运用 MinIO 实现简易文件系统
  • 【MySQL基础刷题】总结题型(三)
  • 前端入门一之ES6--递归、浅拷贝与深拷贝、正则表达式、es6、解构赋值、箭头函数、剩余参数、String、Set
  • 乐维网管平台(六):如何正确管理设备端口
  • 矩阵中的路径(dfs)-acwing
  • spring boot项目打成war包部署