Skip to content

PostgreSQL 暴力攻击防护

fail2ban 配置

fail2ban 是防止暴力攻击的有效工具,可以监控日志并自动封禁恶意IP。

1. 安装与配置

bash
# 安装 fail2ban
sudo apt-get install fail2ban
# 或
sudo yum install fail2ban

2. 配置 fail2ban 规则

bash
# 创建 PostgreSQL 配置文件
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.local

在 jail.local 文件中添加 PostgreSQL 规则:

ini
# PostgreSQL 暴力攻击防护配置
[postgresql]
enabled  = true
port     = 5432
filter   = postgresql
logpath  = /var/log/postgresql/postgresql-15-main.log
maxretry = 3
findtime = 600
bantime  = 3600
ignoreip = 127.0.0.1 192.168.1.0/24

3. 创建 PostgreSQL 过滤器

bash
# 创建 PostgreSQL 过滤器配置
sudo nano /etc/fail2ban/filter.d/postgresql.conf

添加以下内容:

ini
# Fail2Ban filter for PostgreSQL authentication failures
#

[Definition]

# 匹配 PostgreSQL 认证失败日志
failregex = FATAL:  password authentication failed for user \"<F-USER>.*</F-USER>"
            FATAL:  no pg_hba.conf entry for host \"<HOST>", user \"<F-USER>.*</F-USER>", database \"<F-DATABASE>.*</F-DATABASE>", SSL off
            FATAL:  no pg_hba.conf entry for host \"<HOST>", user \"<F-USER>.*</F-USER>", database \"<F-DATABASE>.*</F-DATABASE>", SSL on

ignoreregex =

4. 启动和测试 fail2ban

bash
# 启动 fail2ban 服务
sudo systemctl start fail2ban
sudo systemctl enable fail2ban

# 检查 fail2ban 状态
sudo fail2ban-client status
sudo fail2ban-client status postgresql

# 手动解封 IP
sudo fail2ban-client set postgresql unbanip 192.168.1.100

密码策略配置

1. 使用 pgcrypto 实现强密码

sql
-- 安装 pgcrypto 扩展
CREATE EXTENSION IF NOT EXISTS pgcrypto;

-- 创建用户表,使用强密码
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    username VARCHAR(50) UNIQUE NOT NULL,
    password TEXT NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 插入用户,使用强密码哈希
INSERT INTO users (username, password) 
VALUES (
    'admin',
    crypt('StrongPassword123!', gen_salt('bf', 12)) -- 成本因子 12,增强安全性
);

-- 验证密码
SELECT * FROM users 
WHERE username = 'admin' 
AND password = crypt('StrongPassword123!', password);

2. 使用 passwordcheck 扩展

bash
# 安装 passwordcheck 扩展
sudo apt-get install postgresql-15-passwordcheck
# 或
sudo yum install postgresql15-passwordcheck

# 修改 postgresql.conf 启用扩展
shared_preload_libraries = 'passwordcheck'

# 重启 PostgreSQL
sudo systemctl restart postgresql

pg_hba.conf 配置

pg_hba.conf 是 PostgreSQL 的主机基础认证配置文件,可以限制哪些 IP 可以连接到数据库。

1. 基础配置

txt
# PostgreSQL 主机基础认证配置
# TYPE  DATABASE    USER        CIDR-ADDRESS          METHOD

# 允许本地连接
local   all         all                               peer

# 允许特定 IP 连接
host    all         all         192.168.1.0/24        md5
host    all         admin       10.0.0.50/32         md5

# 允许特定用户从特定 IP 连接特定数据库
host    mydb        myuser      192.168.1.10/32      md5

# 拒绝其他所有连接
host    all         all         0.0.0.0/0             reject
host    all         all         ::/0                  reject

2. 高级配置

txt
# 使用 scram-sha-256 认证(更安全)
host    all         all         192.168.1.0/24        scram-sha-256

# 要求 SSL 连接
hostssl all         all         192.168.1.0/24        md5

# 拒绝特定 IP
host    all         all         10.0.0.100/32         reject

# 限制连接数量(结合 fail2ban 使用)
host    all         all         0.0.0.0/0             md5

其他防护措施

1. 限制连接数

sql
-- 修改 postgresql.conf 限制最大连接数
max_connections = 100

-- 限制特定用户的连接数
ALTER ROLE myuser CONNECTION LIMIT 10;

-- 限制特定数据库的连接数
ALTER DATABASE mydb CONNECTION LIMIT 50;

2. 使用连接池

bash
# 使用 PgBouncer 或 PGPool-II 作为连接池
# 配置 PgBouncer 限制连接数
max_client_conn = 1000
default_pool_size = 20
min_pool_size = 5
reserve_pool_size = 5

3. 监控登录尝试

sql
-- 查看当前连接
SELECT usename, client_addr, application_name, backend_start 
FROM pg_stat_activity 
WHERE state = 'active';

-- 查看失败的连接尝试(需要 pgaudit 扩展)
SELECT * FROM pg_audit_log 
WHERE command_tag = 'FATAL'
ORDER BY statement_timestamp DESC;

4. 使用防火墙

bash
# 使用 iptables 限制 PostgreSQL 端口访问
iptables -A INPUT -p tcp -s 192.168.1.0/24 --dport 5432 -j ACCEPT
iptables -A INPUT -p tcp --dport 5432 -j DROP

# 使用 ufw 限制 PostgreSQL 端口访问
sudo ufw allow from 192.168.1.0/24 to any port 5432
sudo ufw deny 5432
sudo ufw enable

暴力攻击防护最佳实践

1. 多层次防护策略

  • 第一层:防火墙限制(iptables/ufw)
  • 第二层:pg_hba.conf 访问控制
  • 第三层:fail2ban 自动封禁
  • 第四层:强密码策略
  • 第五层:连接数限制
  • 第六层:监控与告警

2. 定期审计

bash
# 定期检查 fail2ban 日志
sudo cat /var/log/fail2ban.log | grep -i postgresql

# 检查 PostgreSQL 认证日志
sudo grep -i "FATAL" /var/log/postgresql/postgresql-15-main.log | tail -n 20

# 定期检查当前连接
sudo -u postgres psql -c "SELECT usename, client_addr, count(*) FROM pg_stat_activity GROUP BY usename, client_addr;"

3. 安全更新

bash
# 定期更新系统和 PostgreSQL
sudo apt-get update && sudo apt-get upgrade -y
sudo yum update -y

# 定期更新 fail2ban
sudo apt-get update && sudo apt-get install --only-upgrade fail2ban

常见问题(FAQ)

Q1:fail2ban 误封了合法 IP 怎么办?

A1:可以手动解封 IP:

bash
sudo fail2ban-client set postgresql unbanip 192.168.1.100

或者在 jail.local 中添加 ignoreip 配置,排除合法 IP 段。

Q2:如何调整 fail2ban 的敏感度?

A2:修改 jail.local 中的 maxretry、findtime 和 bantime 参数:

  • maxretry:允许的失败尝试次数
  • findtime:在多长时间内统计失败尝试
  • bantime:封禁时间(秒)

Q3:passwordcheck 扩展支持哪些密码策略?

A3:passwordcheck 扩展默认检查:

  • 密码长度至少 8 个字符
  • 密码包含至少一个大写字母
  • 密码包含至少一个小写字母
  • 密码包含至少一个数字
  • 密码不包含用户名

Q4:如何监控暴力攻击尝试?

A4:

  • 使用 fail2ban 监控认证失败日志
  • 使用 pgaudit 扩展记录详细审计日志
  • 配置日志告警,当认证失败次数超过阈值时发送告警

Q5:如何防止 DDoS 攻击?

A5:

  • 使用防火墙限制连接速率
  • 配置连接池限制并发连接数
  • 使用 CDN 或 DDoS 防护服务
  • 优化 PostgreSQL 配置,提高抗攻击能力

Q6:如何验证暴力攻击防护是否生效?

A6:

  • 从测试 IP 故意多次输入错误密码,检查是否被封禁
  • 检查 fail2ban 状态,确认封禁记录
  • 检查 PostgreSQL 日志,确认认证失败记录
  • 模拟大量连接,检查系统资源使用情况