PostgreSQL加密连接SSL配置

环境说明

操作系统 主机名 IP 类型 说明
CentOS Linux release 7.6.1810 (Core) centos7.6 192.168.1.150 PostgreSQL Server PostgreSQL 12.17
CentOS Linux release 7.6.1810 (Core) testLinux 192.168.1.200 client psql 13.11
Winserver 2012 192.168.1.99 client navicat

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这个文件夹后,不用输入密码就能连接

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

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

需要使用SSL连接:

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保护 声明
disable No No 我不关心安全性,并且我不想为加密增加负荷。
allow 可能 No 我不关心安全性,但如果服务器坚持,我将承担加密带来的负荷。
prefer 可能 No 我不关心安全性,但如果服务器支持,我希望承担加密带来的负荷。
require Yes No 我想要对数据加密,并且我接受因此带来的负荷。我信任该网络会保证我总是连接到想要连接的服务器。
verify-ca Yes Depends on CA policy 我想要对数据加密,并且我接受因此带来的负荷。我想要确保我连接到的是我信任的服务器。
verify-full Yes Yes 我想要对数据加密,并且我接受因此带来的负荷。我想要确保我连接到的是我信任的服务器,并且就是我指定的那一个。

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

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

参考资料

https://cloud.tencent.com/developer/information/openssl -subj参数有哪些可用选项-album

PostgreSQL加密连接SSL配置的更多相关文章

  1. MsSQL使用加密连接SSL/TLS

    说明 应用程序通过未加密的通道与数据库服务器通信, 这可能会造成重大的安全风险.在这种情况下, 攻击者可以修改用户输入的数据, 甚至对数据库服务器执行任意 SQL 命令. 例如,当您使用以下连接字符串 ...

  2. SQL Server使用加密连接SSL/TLS (转载)

    说明 应用程序通过未加密的通道与数据库服务器通信, 这可能会造成重大的安全风险.在这种情况下, 攻击者可以修改用户输入的数据, 甚至对数据库服务器执行任意 SQL 命令.例如,当您使用以下连接字符串时 ...

  3. MySQL的SSL加密连接与性能开销

    本文转载自:http://www.innomysql.net/article/23959.html(只作转载, 不代表本站和博主同意文中观点或证实文中信息) Contents [hide] 1 前言 ...

  4. Tomcat配置https加密连接

    配置https安全连接(ssl加密连接) https连接需要用到数字证书与数字签名(MD5算法),网站https连接首先需要申请数字证书,配置加密连接器,浏览器安装证书. 证书运用到RSA技术,RSA ...

  5. PostgreSQL远程连接,发生致命错误:没有用于主机“…”,用户“…”,数据库“…”,SSL关闭的pg_hba.conf记录

    PostgreSQL远程连接方法 有时候在远程连接时,会报Error connecting to the server:致命错误:没有用于主机“…”,用户“…”,数据库“…”,SSL关闭的pg_hba ...

  6. mysql建立ssl安全连接的配置

    mysql建立ssl安全连接的配置 1.环境.IP.安装包: centOS 5.4 虚拟机了两台服务器 mysql-5.1.48.tar.gz openssl-0.9.8b.tar.gz server ...

  7. MSSQL - 最佳实践 - 使用SSL加密连接

    MSSQL - 最佳实践 - 使用SSL加密连接 author: 风移 摘要 在SQL Server安全系列专题月报分享中,往期我们已经陆续分享了:如何使用对称密钥实现SQL Server列加密技术. ...

  8. SSL 通信原理及Tomcat SSL 配置

    SSL 通信原理及Tomcat SSL 双向配置 目录1 参考资料 .................................................................. ...

  9. mysql 建立加密连接

    加密连接可提高数据的安全性,但会降低性能.要进行加密连接,必须满足以下要求: user权限表里要有相关的SSL数据列.如果安装的MySQL服务器是4.0.0版的,user权限表已包含相关的SSL数据列 ...

  10. Mysql 5.7.18 加密连接mysql_ssl_rsa_setup

    MySQL 5.7.18 下载地址: https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.18-linux-glibc2.5-x86_64. ...

随机推荐

  1. 最详细STL(三)list

    list就是链表啦,他的一个结点由两个指针域,一个数据域组成.list可以在任何位置以O(n)的复杂度插入元素,头部和尾部的插入的复杂度为O(1).然而list也有一个致命的缺点,因为链表的空间申请是 ...

  2. Redmi AX6000 刷 OpenWrt

    一直想尝试玩玩软路由,但是家里实在没有软路由的需求,外加不知道该入手什么机器来刷软路由,所以迟迟没有入手.最近研究生要开学了,但是学校的有线网要下载专用软件认证才能上网,终于找到合适的理由入手一款软路 ...

  3. 搜索引擎用法 cheatsheet

    逻辑 写法 与 keyword1 keyword2 或 keyword1 OR keyword2 限定关键词的排列 "keyword" 限定搜索的网站 site:cnblogs.c ...

  4. Visual Studio Code 重置“不再询问”选项

    有一次使用 VS Code 重命名一个 Python 文件时,VS Code 询问"扩展'Python'希望通过移动此文件来进行重构更改".当时没有多想,选中"不再提问& ...

  5. in notin exists not exists 性能优化算法总结

    in notin exists not exists 性能优化算法总结 1.1. in 和 exists 区别 1.2. not in 能不能走索引 1.3. not in 和 join 的关系 1. ...

  6. 声明式 Shadow DOM:简化 Web 组件开发的新工具

    在现代 Web 开发中,Web 组件已经成为创建模块化.可复用 UI 组件的标准工具.而 Shadow DOM 是 Web 组件技术的核心部分,它允许开发人员封装组件的内部结构和样式,避免组件的样式和 ...

  7. TypeScript 学习笔记 – Handbook 1

    前言 一转眼, 一年多没有写 TypeScript 了. 最近又要开始写了, 乘此机会打算系统学习一下, 顺便写一个学习笔记. 我接触 TypeScript 比较早, 那是 Angular 2 bet ...

  8. 处理英文中的单数复数 (pluralize, singular plural)

    因为英语很烂, 有时候很烦这个. 如果是 hard code 的情况, 如果我不清楚的话就会去这里找 https://www.wordhippo.com/what-is/the-plural-of/l ...

  9. Figma 学习笔记 – Frame

    Frame = <div> Frame 就类似 HTML 中的 div, 它和形状 rectangle 特性上蛮相识的, 但是使用场景其实差很多, 所以不要搞错哦. (除了图片很少会用到 ...

  10. 大模型应用开发初探 : 通用函数调用Planner

    大家好,我是Edison. 上一篇,我们了解了什么是AI Agent以及如何用Semantic Kernel手搓一个AI Agent.有朋友留言说,自动函数调用对大模型有较高的要求,比如Azure O ...