一、PostgreSQL 安全防护概述
1.1、数据库的密码安全性
PostgreSQL 数据库的密码安全性是一个重要的话题。PostgreSQL 数据库的密码可以通过多种方式进行加密存储,例如使用 MD5 或 SCRAM-SHA-256 算法。然而,如果密码存储为明文,它们将非常容易被破解。
1.2、常用安全防护功能
PostgreSQL 的 auth_delay、passwordcheck 安全性方案是一种旨在防止暴力破解攻击的机制。该方案通过在认证失败后引入延迟时间,从而减慢攻击者尝试不同密码组合的速度。当用户输入的密码错误时,auth_delay 会使服务器暂时停止响应,延迟一段时间后才能继续验证。这不仅增加了暴力破解的难度,而且减少了服务器资源的消耗。passwordcheck 主要是使用强密码策略,加固第一道防线。
二、整改实施流程
2.1、配置 pg_hba.conf 文件
Pg_hba.conf 主要功能:
- 1、pg_hba.conf 文件是 PostgreSQL 数据库的访问控制配置文件,它决定了哪些用户可以从哪些主机连接到哪些数据库,以及使用何种认证方法。
- 2、pg_hba.conf 位置:默认存放于$PGDATA 目录下。
- 3、存储类型如下表:
| 访问类型 | 数据库名 | 用户名 | 主机地址 | 加密方式 |
|---|---|---|---|---|
| local | all | all | trust | |
| host | postgres | postgres | 127.0.0.1/32 | trust |
| host | postgres | postgres | 192.168.1.0/24 | scram-sha-256 |
说明:
- 1、local:表示本地访问;
- 2、host:表示通过 IP 地址访问;
- 3、192.168.1.0/24:表示在 192.168.1.*网段才可以访问;
- 4、数据库名:all:表示所有数据库都可以访问;
- 5、用户名:all:表示所有用户都可以访问;
- 6、加密方式:trust:表示无条件接受;md5:现在已被破解,不推荐使用 md5 加密;scram-sha-256:是目前最安全的加密方式。
- 7、注意:pg_hba.conf 有验证顺序,即第一个验证通过后,就不会再验证后面的规则了。
- 8、如果需要访问多个数据库、或多个用户,可以在用户名后加英文状态的逗号(,)分开。如: host postgres,dbtest sy , postgres 192.168.4.0/24 scram-sha-256
示例:
代码如下:
Vi $PGDATA/pg_hba.conf # TYPE DATABASE USER ADDRESS METHOD # "local" is for Unix domain socket connections only local all all trust # IPv4 local connections: #host all all 127.0.0.1/32 trust host postgres sy 192.168.1.0/24 scram-sha-256 # IPv6 local connections: host all all ::1/128 trust # Allow replication connections from localhost, by a user with the # replication privilege. local replication all trust host replication all 127.0.0.1/32 trust host replication all ::1/128 trust
2.2、auth_delay 安装
功能特点:
auth_delay 是 PostgreSQL 数据库的一个安全特性,它可以在用户认证失败后引入延迟时间,以此来减缓暴力破解攻击的速度。这个特性通过在 postgresql.conf 配置文件中设置 shared_preload_libraries 参数来启用,并通过 auth_delay.milliseconds 参数来指定每次认证失败后的延迟时间,单位为毫秒。例如,设置 auth_delay.milliseconds = '5000'表示每次认证失败后将延迟 5 秒。
说明:auth_delay 插件在源文件中的 contrib 目录中。
- 1、切换到源文件的 contrib 目录
代码如下:
[postgres@Server ~]$ cd /install/postgresql-17beta1/contrib/ [postgres@Server contrib]$ ls amcheck btree_gin dict_xsyn intagg ltree_plpython pgcrypto pg_trgm spi auth_delay btree_gist earthdistance intarray Makefile pg_freespacemap pg_visibility ssl auto_explain citext file_fdw isn meson.build pg_prewarm pg_walinspect sta basebackup_to_shell contrib-global.mk fuzzystrmatch jsonb_plperl oid2name pgrowlocks postgres_fdw tab basic_archive cube hstore jsonb_plpython pageinspect pg_stat_statements README tcn bloom dblink hstore_plperl lo passwordcheck pgstattuple seg tes bool_plperl dict_int hstore_plpython ltree pg_buffercache pg_surgery sepgsql tsm [postgres@Server contrib]$ cd auth_delay/
- 2、编译安装 auth_delay 扩展
代码如下:
[postgres@Server auth_delay]$ make && make install make -C ../../src/backend generated-headers make[1]: 进入目录“/install/postgresql-17beta1/src/backend” make -C ../include/catalog generated-headers make[2]: 进入目录“/install/postgresql-17beta1/src/include/catalog” make[2]: 对“generated-headers”无需做任何事。 make[2]: 离开目录“/install/postgresql-17beta1/src/include/catalog” make -C nodes generated-header-symlinks make[2]: 进入目录“/install/postgresql-17beta1/src/backend/nodes” make[2]: 对“generated-header-symlinks”无需做任何事。 make[2]: 离开目录“/install/postgresql-17beta1/src/backend/nodes” make -C utils generated-header-symlinks make[2]: 进入目录“/install/postgresql-17beta1/src/backend/utils” make -C adt jsonpath_gram.h make[3]: 进入目录“/install/postgresql-17beta1/src/backend/utils/adt” make[3]: “jsonpath_gram.h”已是最新。 make[3]: 离开目录“/install/postgresql-17beta1/src/backend/utils/adt” make[2]: 离开目录“/install/postgresql-17beta1/src/backend/utils” make[1]: 离开目录“/install/postgresql-17beta1/src/backend” gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wcast-function-type -Wshadow=compatible-local -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -O2 -fPIC -fvisibility=hidden -I. -I. -I../../src/include -D_GNU_SOURCE -c -o auth_delay.o auth_delay.c gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wcast-function-type -Wshadow=compatible-local -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -O2 -fPIC -fvisibility=hidden auth_delay.o -L../../src/port -L../../src/common -Wl,--as-needed -Wl,-rpath,'/postgres/server/lib',--enable-new-dtags -fvisibility=hidden -shared -o auth_delay.so make -C ../../src/backend generated-headers make[1]: 进入目录“/install/postgresql-17beta1/src/backend” make -C ../include/catalog generated-headers make[2]: 进入目录“/install/postgresql-17beta1/src/include/catalog” make[2]: 对“generated-headers”无需做任何事。 make[2]: 离开目录“/install/postgresql-17beta1/src/include/catalog” make -C nodes generated-header-symlinks make[2]: 进入目录“/install/postgresql-17beta1/src/backend/nodes” make[2]: 对“generated-header-symlinks”无需做任何事。 make[2]: 离开目录“/install/postgresql-17beta1/src/backend/nodes” make -C utils generated-header-symlinks make[2]: 进入目录“/install/postgresql-17beta1/src/backend/utils” make -C adt jsonpath_gram.h make[3]: 进入目录“/install/postgresql-17beta1/src/backend/utils/adt” make[3]: “jsonpath_gram.h”已是最新。 make[3]: 离开目录“/install/postgresql-17beta1/src/backend/utils/adt” make[2]: 离开目录“/install/postgresql-17beta1/src/backend/utils” make[1]: 离开目录“/install/postgresql-17beta1/src/backend” /usr/bin/mkdir -p '/postgres/server/lib' /usr/bin/install -c -m 755 auth_delay.so '/postgres/server/lib/' [postgres@Server auth_delay]$
- 3、配置 postgresql.conf 装载 auth_delay 扩展
代码如下:
[postgres@Server ~]$ vi $PGDATA/postgresql.conf #auth_delay 模块添加到该参数的值中 shared_preload_libraries = ‘auth_delay' #设置 5 秒的延迟 auth_delay.milliseconds = '5000'
2.3、手动编译安装 passwordcheck 扩展
- 1、切换到源文件的 contrib 目录
代码如下:
[postgres@Server ~]$ cd /install/postgresql-17beta1/ [postgres@Server postgresql-17beta1]$ cd contrib/ [postgres@Server contrib]$ pwd /install/postgresql-17beta1/contrib [postgres@Server contrib]$ ls amcheck cube intarray passwordcheck pg_walinspect tsm_system_rows auth_delay dblink isn pg_buffercache postgres_fdw tsm_system_time auto_explain dict_int jsonb_plperl pgcrypto README unaccent basebackup_to_shell dict_xsyn jsonb_plpython pg_freespacemap seg uuid-ossp basic_archive earthdistance lo pg_prewarm sepgsql vacuumlo bloom file_fdw ltree pgrowlocks spi xml2 bool_plperl fuzzystrmatch ltree_plpython pg_stat_statements sslinfo btree_gin hstore Makefile pgstattuple start-scripts btree_gist hstore_plperl meson.build pg_surgery tablefunc citext hstore_plpython oid2name pg_trgm tcn contrib-global.mk intagg pageinspect pg_visibility test_decoding [postgres@Server contrib]$ [postgres@Server contrib]$ [postgres@Server contrib]$ cd passwordcheck/
- 2、编译 passwordcheck 扩展
代码如下:
[postgres@Server passwordcheck]$ [postgres@Server passwordcheck]$ make && make install make -C ../../src/backend generated-headers make[1]: 进入目录“/install/postgresql-17beta1/src/backend” make -C ../include/catalog generated-headers make[2]: 进入目录“/install/postgresql-17beta1/src/include/catalog” make[2]: 对“generated-headers”无需做任何事。 make[2]: 离开目录“/install/postgresql-17beta1/src/include/catalog” make -C nodes generated-header-symlinks make[2]: 进入目录“/install/postgresql-17beta1/src/backend/nodes” make[2]: 对“generated-header-symlinks”无需做任何事。 make[2]: 离开目录“/install/postgresql-17beta1/src/backend/nodes” make -C utils generated-header-symlinks make[2]: 进入目录“/install/postgresql-17beta1/src/backend/utils” make -C adt jsonpath_gram.h make[3]: 进入目录“/install/postgresql-17beta1/src/backend/utils/adt” make[3]: “jsonpath_gram.h”已是最新。 make[3]: 离开目录“/install/postgresql-17beta1/src/backend/utils/adt” make[2]: 离开目录“/install/postgresql-17beta1/src/backend/utils” make[1]: 离开目录“/install/postgresql-17beta1/src/backend” make -C ../../src/backend generated-headers make[1]: 进入目录“/install/postgresql-17beta1/src/backend” make -C ../include/catalog generated-headers make[2]: 进入目录“/install/postgresql-17beta1/src/include/catalog” make[2]: 对“generated-headers”无需做任何事。 make[2]: 离开目录“/install/postgresql-17beta1/src/include/catalog” make -C nodes generated-header-symlinks make[2]: 进入目录“/install/postgresql-17beta1/src/backend/nodes” make[2]: 对“generated-header-symlinks”无需做任何事。 make[2]: 离开目录“/install/postgresql-17beta1/src/backend/nodes” make -C utils generated-header-symlinks make[2]: 进入目录“/install/postgresql-17beta1/src/backend/utils” make -C adt jsonpath_gram.h make[3]: 进入目录“/install/postgresql-17beta1/src/backend/utils/adt” make[3]: “jsonpath_gram.h”已是最新。 make[3]: 离开目录“/install/postgresql-17beta1/src/backend/utils/adt” make[2]: 离开目录“/install/postgresql-17beta1/src/backend/utils” make[1]: 离开目录“/install/postgresql-17beta1/src/backend” /usr/bin/mkdir -p '/postgres/server/lib' /usr/bin/install -c -m 755 passwordcheck.so '/postgres/server/lib/passwordcheck.so' [postgres@Server passwordcheck]$
- 3、安装 passwordcheck 扩展
代码如下:
#以前的先做下备份 [postgres@Server passwordcheck]$ mv /install/postgresql-17beta1/contrib/passwordcheck/passwordcheck.so /install/postgresql-17beta1/contrib/passwordcheck/passwordcheck.so.bak #拷贝重新编译后的 SO 文件 [postgres@Server passwordcheck]$ cp /install/postgresql-17beta1/contrib/passwordcheck/passwordcheck.so /postgres/server/lib
- 4、配置 postgresql.conf 装载 passwordcheck 扩展
说明:如果已安装有其他扩展,两个扩展之间用 “,”隔开。
代码如下:
Vi $PGDATA/postgresql.conf //加载密码复杂度扩展和登录延迟扩展 shared_preload_libraries = 'auth_delay , passwordcheck'
三、安全检查
3.1、passwordcheck 验证
- 1、使用纯数字密码
代码如下:
postgres=# create user ll with password '123'; 2024-06-27 15:09:14.346 CST [2177] ERROR: password is too short 2024-06-27 15:09:14.346 CST [2177] STATEMENT: create user ll with password '123'; ERROR: password is too short postgres=#
- 2、使用纯字母密码
代码如下:
postgres=# postgres=# create user ll with password 'abcdefg'; ERROR: password is too short postgres=#
- 3、字母加数字搭配,位数不够也不会出错
代码如下:
postgres=# postgres=# create user ll with password 'abcd123'; ERROR: password is too short postgres=#
- 4、使用字母、数字、特殊符号搭配
代码如下:
postgres=# postgres=# create user ll with password 'Sy@123456736'; CREATE ROLE
- 5、更加安全:使用字母、数字、特殊符号搭配,并加使用期限
代码如下:
postgres=# postgres=# create user ll with password 'Sy@123456736' valid until '2024-06-27 17:14:59'; CREATE ROLE
- 6、密码过期后的登录错误:
[postgres@Server ~]$ psql -Ull -dpostgres -h192.168.4.97 Password for user ll: 2024-06-27 17:16:16.140 CST [1995] FATAL: password authentication failed for user "ll" 2024-06-27 17:16:16.140 CST [1995] DETAIL: User "ll" has an expired password. Connection matched file "/postgres/data/pg_hba.conf" line 120: "host postgres,dbtest sy,postgres,ll 192.168.4.0/24 scram-sha-256 " psql: error: connection to server at "192.168.4.97", port 5432 failed: FATAL: password authentication failed for user "ll" [postgres@Server ~]$
总结:
- 1、启用 passwordcheck 扩展后,可以实现密码复杂度要求,如果密码太弱,会拒绝连接。
- 2、创建用户或修改用户密码时,强制限制密码的复杂度,限制密码不能重复使用 例如密码长度,包含数字,字母,大小写,特殊字符等,避免了暴力破解字典中的字符串。
3.2、auth_delay 验证
说明:authentication_timeout = 5s,服务器等待 5s 后再继续处理后续的认证请求。
- 1、模拟登录失败
代码如下:
[postgres@Server ~]$ psql -Usy -ddbtest -h192.168.4.97 Password for user sy: 2024-06-27 15:50:24.665 CST [1602] FATAL: password authentication failed for user "sy" 2024-06-27 15:50:24.665 CST [1602] DETAIL: Connection matched file "/postgres/data/pg_hba.conf" line 120: "host postgres,dbtest sy,postgres 192.168.4.0/24 scram-sha-256 " psql: error: connection to server at "192.168.4.97", port 5432 failed: FATAL: password authentication failed for user "sy" [postgres@Server ~]$
3.3、其他配置
- 1、加密方式,默认采用 scram-sha-256
代码如下:
postgres=# show password_encryption postgres-# ; password_encryption --- scram-sha-256 (1 row)
- 2、主机验证的最长时间
说明:完成服务器认证的最长时间,如果在这个时间内没有完成认证,服务器将关闭连接。
代码如下:
vi $PGDATA/postgresql.conf authentication_timeout = 5s
四、改进措施
4.1、设置密码有效期后,定期检查密码有效期,避免过期
4.1.1、检查密码有效期
代码如下:
postgres=# select \* from pg_roles where rolname='ll'; rolname | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolconnlimit | rolpassword | rolvaliduntil | r olbypassrls | rolconfig | oid ---------+----------+------------+---------------+-------------+-------------+----------------+--------------+-------------+------------------------+-- ------------+-----------+------- ll | f | t | f | f | t | f | -1 | **\*\*\*\*** | 2024-06-27 17:14:59+08 | f | | 25073 (1 row) postgres=# postgres=#
4.1.2、针对新建用户或即将过期的用户,需要提前修改密码并修改密码有效期。
说明:通过自动生成脚本,并计算出失效期,直接使用查询出的创建或修改脚本即可创建或修改用户密码及有效期。
- 1、新建用户
代码如下:
postgres=# select $$create user sy with password 'Sy@426007' valid until '$$||now()::timestamp(0) + '180 day'||$$';$$; ?column? --- create user sy with password 'Sy@426007' valid until '2024-12-24 21:25:07'; (1 row)
- 2、现有用户
代码如下:
postgres=# postgres=# select $$alter user ll with password 'Ll@06279999' valid until '$$||now()::timestamp(0) + '180 day'||$$';$$; ?column? --- alter user ll with password 'Ll@06279999' valid until '2024-12-24 21:25:43'; (1 row) postgres=#
- 3、使用生成脚本创建用户
代码如下:
postgres=# postgres=# alter user ll with password 'Ll@06279999' valid until '2024-12-24 21:37:46'; ALTER ROLE postgres=#
总结:
以上密码策略是基于 passwordcheck 的常规密码检查扩展,如果您觉得以上配置太过复杂,也可以使用 passwordcheck_ cracklib,该模块的密码检查更严格。每当用户使用 CREATE ROLE 或设置密码时,该模块都会检查用户的密码 ALTER ROLE。如果密码被认为太弱,它将被拒绝,并且命令将以错误终止。 passwordcheck_cracklib 下载地址: https://github.com/devrimgunduz/passwordcheck_cracklib
五、查看状态
设置账户的密码安全策略 用户密码存储在系统表 pg_authid 中,为防止用户密码泄露,PostgreSQL 对用户密码进行加密存储,所采用的加密算法由配置参数 password_encryption 决定。
postgres=# select \*from pg_authid where rolname='sy'; oid | rolname | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnl imit | rolpassword | rolvaliduntil -------+---------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------- -----+------------------------------------------------------------------------------------------------------------------------- --------------+--------------- 25065 | sy | t | t | f | f | t | f | f | -1 | SCRAM-SHA-256$4096:SocjVWZoe/zA5QEd9CVTvA==$uQE3xV1gfFj4gXB1qAzI6VH/YnfM/p8+axE+Q+mMwe0=:rUGRWbsrpmDd6wEzW0Ge0Z8SzJ8+Piv NtSppyhIcVFc= | (1 row) postgres=#
六、问题解决
6.1、安装 passwordcheck 时,提示错误,代码如下:
[postgres@Server ~]$ ERROR: could not open extension control file "/postgres/server/lib/passwordcheck.so": No such file or directory。
- 解决:拷贝重新编译后的 so 文件到安装后的 lib 目录。
代码如下:
[postgres@Server passwordcheck]$ cp /install/postgresql-17beta1/contrib/passwordcheck/passwordcheck.so /postgres/server/lib/
七、总结
7.1、加强 PostgreSql 数据库安全防护的措施:
除了 auth_delay、passwordcheck,提高 PostgreSQL 登录安全性的措施还包括:
设置强密码:确保数据库用户密码足够强大和复杂,建议使用大小写字母、数字和特殊字符组合。
- 限制访问权限:为每个数据库用户分配最小必要的权限,避免赋予过高的权限。
- 配置防火墙:限制数据库服务端口的访问范围,只允许来自信任来源的连接。
- 定期备份数据:定期备份数据库以防止数据丢失,同时确保备份数据的安全性。
- 监控数据库活动:监控数据库的活动情况,及时发现异常行为和潜在的安全问题。
- 通过综合运用上述措施,可以显著提高 PostgreSQL 数据库的登录安全性,保护数据库免受未授权访问和攻击。
7.2、温馨提示:
启用 auth_delay、passwordcheck 等扩展可以增加暴力破解数据库密码的难度,但它并不能防止拒绝服务攻击,因为在报告认证失败之前等待的过程仍然会占用连接资源。因此,在实施 auth_delay 时,还需要考虑其他安全措施,如限制并发连接数、设置合理的超时设置等。




