Skip to content

PostgreSQL 连接安全

连接安全概述

连接安全是指保护数据库连接过程中的安全,防止未授权用户连接到数据库,以及保护数据在传输过程中的安全。PostgreSQL提供了多种连接安全机制,包括SSL/TLS加密、认证方式、连接管理和访问控制等。连接安全是数据库安全的第一道防线,对于保护数据库至关重要。

连接安全威胁

常见的连接安全威胁包括:

  1. 未授权连接:未经授权的用户尝试连接到数据库
  2. 密码破解:攻击者使用暴力破解或字典攻击获取密码
  3. 中间人攻击:攻击者拦截和修改数据库连接
  4. 连接劫持:攻击者劫持合法的数据库连接
  5. 拒绝服务攻击:攻击者发送大量连接请求,导致数据库无法响应
  6. 明文传输:数据在传输过程中未加密,被窃听或篡改

连接安全原则

连接安全应遵循以下原则:

  1. 使用加密连接:使用SSL/TLS加密数据传输
  2. 强认证方式:使用强认证方式,如密码加密、证书认证等
  3. 最小权限:只授予用户完成工作所需的最小权限
  4. 连接限制:限制用户的连接数、连接来源等
  5. 监控与审计:监控和审计数据库连接
  6. 定期更新:定期更新PostgreSQL和相关组件,修复安全漏洞

SSL/TLS配置

1. SSL/TLS基础

SSL(Secure Sockets Layer)和TLS(Transport Layer Security)是用于保护网络通信安全的协议,PostgreSQL支持使用SSL/TLS加密连接。

2. 生成SSL证书

可以使用OpenSSL生成自签名SSL证书,或使用可信CA颁发的证书。

生成自签名证书

bash
# 创建证书目录
mkdir -p /etc/postgresql/ssl
cd /etc/postgresql/ssl

# 生成CA私钥
openssl genrsa -des3 -out ca.key 2048

# 生成CA证书
openssl req -new -x509 -days 365 -key ca.key -out ca.crt

# 生成服务器私钥
openssl genrsa -out server.key 2048

# 生成服务器证书请求
openssl req -new -key server.key -out server.csr

# 使用CA签名服务器证书
openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt

# 移除私钥密码
openssl rsa -in server.key -out server.key

# 设置权限
chown postgres:postgres *.key *.crt *.csr *.srl
chmod 600 *.key
chmod 644 *.crt *.csr *.srl

3. 配置PostgreSQL使用SSL

在postgresql.conf中配置SSL:

sql
-- 启用SSL
ssl = on

-- SSL证书文件
ssl_cert_file = '/etc/postgresql/ssl/server.crt'
ssl_key_file = '/etc/postgresql/ssl/server.key'
ssl_ca_file = '/etc/postgresql/ssl/ca.crt'  -- 可选,用于客户端证书验证
ssl_crl_file = '/etc/postgresql/ssl/ca.crl'  -- 可选,证书吊销列表

-- SSL加密设置
ssl_prefer_server_ciphers = on
ssl_ecdh_curve = 'prime256v1'  -- 使用强加密曲线
ssl_min_protocol_version = 'TLSv1.2'  -- 最小TLS版本

-- 重启PostgreSQL服务
sudo systemctl restart postgresql

4. 验证SSL配置

使用psql验证SSL配置:

bash
-- 连接到数据库,检查SSL状态
psql "host=localhost port=5432 dbname=postgres user=postgres sslmode=require"

-- 查看SSL连接信息
\conninfo

输出示例:

You are connected to database "postgres" as user "postgres" via socket in "/var/run/postgresql" at port "5432".
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)

认证方式

PostgreSQL支持多种认证方式,包括密码认证、证书认证、LDAP认证等。

1. 密码认证

密码认证是最常用的认证方式,PostgreSQL支持多种密码加密方式。

配置密码认证

在pg_hba.conf中配置密码认证:

# TYPE  DATABASE        USER            ADDRESS                 METHOD
host    all             all             0.0.0.0/0               scram-sha-256
host    all             all             ::/0                    scram-sha-256

密码加密方式

PostgreSQL支持以下密码加密方式:

  • md5:使用MD5哈希密码,安全性较低,不推荐使用
  • scram-sha-256:使用SCRAM-SHA-256算法加密密码,安全性较高,推荐使用

在postgresql.conf中配置密码加密方式:

sql
password_encryption = scram-sha-256

2. 证书认证

证书认证是指使用SSL证书进行认证,客户端需要提供有效的证书才能连接到数据库。

配置证书认证

在pg_hba.conf中配置证书认证:

# TYPE  DATABASE        USER            ADDRESS                 METHOD
hostssl all             all             0.0.0.0/0               cert clientcert=1
hostssl all             all             ::/0                    cert clientcert=1

生成客户端证书

bash
# 生成客户端私钥
openssl genrsa -out client.key 2048

# 生成客户端证书请求
openssl req -new -key client.key -out client.csr

# 使用CA签名客户端证书
openssl x509 -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt

# 设置权限
chmod 600 client.key
chmod 644 client.crt

使用证书连接

bash
# 使用证书连接到数据库
psql "host=localhost port=5432 dbname=postgres user=postgres sslmode=verify-full sslrootcert=ca.crt sslcert=client.crt sslkey=client.key"

3. LDAP认证

LDAP认证是指使用LDAP服务器进行认证,适用于企业环境。

配置LDAP认证

在pg_hba.conf中配置LDAP认证:

# TYPE  DATABASE        USER            ADDRESS                 METHOD
host    all             all             0.0.0.0/0               ldap ldapserver=ldap.example.com ldapport=389 ldapbasedn="dc=example,dc=com" ldapsearchattribute=uid

4. PAM认证

PAM(Pluggable Authentication Modules)认证是指使用PAM模块进行认证,适用于Linux系统。

配置PAM认证

在pg_hba.conf中配置PAM认证:

# TYPE  DATABASE        USER            ADDRESS                 METHOD
host    all             all             0.0.0.0/0               pam pamservice=postgresql

创建PAM配置文件

bash
# 创建PAM配置文件
sudo vi /etc/pam.d/postgresql

# 添加以下内容
auth    required    pam_unix.so    nullok
auth    required    pam_succeed_if.so    user != root quiet
account required    pam_unix.so

连接管理

1. 限制连接数

限制数据库的最大连接数,防止拒绝服务攻击:

sql
-- 在postgresql.conf中配置
max_connections = 100  -- 最大连接数

-- 为超级用户保留的连接数
superuser_reserved_connections = 3

2. 限制用户连接数

限制单个用户的连接数:

sql
-- 创建用户时限制连接数
CREATE ROLE myuser WITH LOGIN PASSWORD 'mypassword' CONNECTION LIMIT 5;

-- 修改用户连接数
ALTER ROLE myuser WITH CONNECTION LIMIT 10;

-- 查看用户连接数限制
SELECT rolname, rolconnlimit FROM pg_roles WHERE rolname = 'myuser';

3. 限制连接来源

限制允许连接到数据库的IP地址或网络:

在pg_hba.conf中配置:

# TYPE  DATABASE        USER            ADDRESS                 METHOD
host    all             all             192.168.1.0/24          scram-sha-256  -- 只允许192.168.1.0/24网络连接
host    all             all             10.0.0.0/8              scram-sha-256  -- 只允许10.0.0.0/8网络连接
host    all             all             127.0.0.1/32            scram-sha-256  -- 只允许本地连接

4. 连接超时设置

设置连接超时,防止连接长时间占用资源:

sql
-- 在postgresql.conf中配置
connect_timeout = 10  -- 连接超时时间(秒)
idle_in_transaction_session_timeout = 600000  -- 空闲事务超时时间(毫秒)
statement_timeout = 30000  -- 语句执行超时时间(毫秒)

5. 连接池配置

使用连接池管理数据库连接,提高连接效率和安全性:

使用pgBouncer

pgBouncer是一款流行的PostgreSQL连接池工具。

bash
# 安装pgBouncer
sudo apt-get update
sudo apt-get install pgbouncer

# 配置pgBouncer
vi /etc/pgbouncer/pgbouncer.ini

[databases]
* = host=localhost port=5432

[pgbouncer]
listen_addr = 0.0.0.0
listen_port = 6432
auth_type = scram-sha-256
auth_file = /etc/pgbouncer/userlist.txt
pool_mode = transaction
max_client_conn = 1000
default_pool_size = 20
min_pool_size = 5
reserve_pool_size = 5
reserve_pool_timeout = 5

# 启动pgBouncer
sudo systemctl start pgbouncer

访问控制

1. 基于IP的访问控制

在pg_hba.conf中配置基于IP的访问控制:

# TYPE  DATABASE        USER            ADDRESS                 METHOD
host    all             all             192.168.1.0/24          scram-sha-256
host    all             all             10.0.0.0/8              reject  -- 拒绝10.0.0.0/8网络连接

2. 基于用户的访问控制

授予用户适当的权限,遵循最小权限原则:

sql
-- 创建只读用户
CREATE ROLE readonly WITH LOGIN PASSWORD 'readonlypassword';
GRANT CONNECT ON DATABASE mydatabase TO readonly;
GRANT USAGE ON SCHEMA myschema TO readonly;
GRANT SELECT ON ALL TABLES IN SCHEMA myschema TO readonly;

-- 创建读写用户
CREATE ROLE readwrite WITH LOGIN PASSWORD 'readwritepassword';
GRANT CONNECT ON DATABASE mydatabase TO readwrite;
GRANT USAGE ON SCHEMA myschema TO readwrite;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA myschema TO readwrite;

3. 基于数据库的访问控制

限制用户对特定数据库的访问:

sql
-- 只授予用户访问特定数据库的权限
GRANT CONNECT ON DATABASE mydatabase TO myuser;

4. 基于模式的访问控制

限制用户对特定模式的访问:

sql
-- 只授予用户访问特定模式的权限
GRANT USAGE ON SCHEMA myschema TO myuser;

连接安全监控与审计

1. 监控连接状态

使用pg_stat_activity视图监控当前连接状态:

sql
-- 查看当前连接
SELECT 
    pid, 
    usename, 
    datname, 
    application_name, 
    client_addr, 
    client_port, 
    backend_start, 
    state, 
    query
FROM pg_stat_activity;

-- 查看活跃连接
SELECT * FROM pg_stat_activity WHERE state = 'active';

-- 查看空闲连接
SELECT * FROM pg_stat_activity WHERE state = 'idle';

-- 查看空闲事务连接
SELECT * FROM pg_stat_activity WHERE state = 'idle in transaction';

2. 审计连接日志

配置PostgreSQL的连接日志,记录连接信息:

sql
-- 在postgresql.conf中配置
log_connections = on          -- 记录连接信息
log_disconnections = on       -- 记录断开连接信息
log_authfailures = on         -- 记录认证失败信息
log_line_prefix = '%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h '  -- 日志格式

3. 使用pgAudit扩展

pgAudit扩展可以提供更详细的连接审计日志:

sql
-- 安装pgAudit扩展
CREATE EXTENSION pgaudit;

-- 配置pgAudit
ALTER SYSTEM SET pgaudit.log = 'read, write, function, role, session';
ALTER SYSTEM SET pgaudit.log_catalog = on;
ALTER SYSTEM SET pgaudit.log_level = notice;

-- 重启PostgreSQL服务
SELECT pg_reload_conf();

版本差异

PostgreSQL 12+ 连接安全增强

  1. SSL/TLS增强:支持TLS 1.3,提高连接安全性
  2. 密码加密增强:默认使用scram-sha-256密码加密,提高密码安全性
  3. 连接池增强:支持更多的连接池配置选项
  4. 审计日志增强:提供更详细的连接审计日志

PostgreSQL 13+ 连接安全增强

  1. 证书认证增强:支持更多的证书认证选项
  2. LDAP认证增强:支持更多的LDAP认证选项
  3. 连接管理增强:支持更多的连接管理选项
  4. SSL/TLS配置增强:支持更灵活的SSL/TLS配置

PostgreSQL 14+ 连接安全增强

  1. 逻辑复制安全:增强逻辑复制的安全性
  2. 扩展权限增强:支持扩展的权限管理
  3. 连接监控增强:提供更详细的连接监控信息
  4. SSL/TLS性能优化:优化SSL/TLS连接性能

常见问题(FAQ)

Q1: 如何配置PostgreSQL使用SSL/TLS?

A1: 可以按照以下步骤配置PostgreSQL使用SSL/TLS:

  1. 生成SSL证书(服务器证书和私钥)
  2. 在postgresql.conf中启用SSL,配置证书文件路径
  3. 在pg_hba.conf中配置使用SSL连接
  4. 重启PostgreSQL服务
  5. 验证SSL配置

Q2: 如何选择合适的认证方式?

A2: 选择合适的认证方式需要考虑以下因素:

  • 安全性要求:证书认证安全性最高,密码认证次之
  • 企业环境:LDAP认证适用于企业环境,便于集中管理用户
  • 性能要求:证书认证性能较低,密码认证性能较高
  • 管理复杂度:证书认证管理复杂度较高,密码认证次之

Q3: 如何限制数据库连接数?

A3: 可以通过以下方法限制数据库连接数:

  1. 在postgresql.conf中设置max_connections参数,限制数据库的最大连接数
  2. 使用ALTER ROLE命令限制单个用户的连接数
  3. 使用连接池工具(如pgBouncer)管理连接数
  4. 在pg_hba.conf中限制连接来源

Q4: 如何防止密码破解?

A4: 可以通过以下方法防止密码破解:

  1. 使用强密码策略,如密码长度、复杂度要求
  2. 使用安全的密码加密方式,如scram-sha-256
  3. 限制登录尝试次数,防止暴力破解
  4. 使用证书认证或其他强认证方式
  5. 定期更换密码

Q5: 如何监控数据库连接?

A5: 可以通过以下方法监控数据库连接:

  1. 使用pg_stat_activity视图监控当前连接状态
  2. 配置PostgreSQL的连接日志,记录连接信息
  3. 使用pgAudit扩展提供更详细的连接审计日志
  4. 使用第三方监控工具,如Prometheus、Grafana等

Q6: 如何使用连接池?

A6: 可以使用以下连接池工具:

  1. pgBouncer:轻量级的PostgreSQL连接池工具
  2. Pgpool-II:功能丰富的PostgreSQL连接池工具
  3. Citus:分布式PostgreSQL的连接池工具
  4. 应用程序内置连接池:如Java的HikariCP、Python的psycopg2连接池等

总结

连接安全是PostgreSQL数据库安全的重要组成部分,通过合理的SSL/TLS配置、认证方式选择、连接管理和访问控制等措施,可以保护数据库连接的安全性,防止未授权访问和数据泄露。在实际生产环境中,应该根据业务需求和安全性要求,制定合适的连接安全策略,确保数据库连接的安全性和可靠性。

连接安全的关键是:

  1. 使用SSL/TLS加密数据传输
  2. 选择合适的认证方式,如scram-sha-256密码认证或证书认证
  3. 限制连接数、连接来源和连接超时
  4. 使用连接池管理数据库连接
  5. 监控和审计连接状态
  6. 定期更新PostgreSQL和相关组件,修复安全漏洞

通过不断学习和实践,可以更好地掌握PostgreSQL的连接安全技术,提高数据库的安全性和可靠性。