Skip to content

PostgreSQL RADIUS 认证详解

概述

RADIUS (Remote Authentication Dial-In User Service) 认证是 PostgreSQL 支持的一种外部认证方法,它允许数据库服务器通过外部 RADIUS 服务器验证用户身份。这种认证方式在企业环境中特别有用,因为它可以实现用户身份的集中管理和统一认证。

INFO

什么是 RADIUS?

RADIUS 是一种网络协议,广泛用于网络访问服务器的身份验证、授权和计费。它最初为拨号访问而设计,现在被广泛应用于各种网络访问场景。

RADIUS 认证工作原理

认证流程

关键特性

  • 仅密码验证:RADIUS 只负责验证用户名和密码组合
  • 数据库用户必须存在:用户必须先在 PostgreSQL 中创建才能使用 RADIUS 认证
  • 加密传输:密码在传输过程中会被加密
  • 不支持计费:PostgreSQL 的 RADIUS 实现不包含计费功能

RADIUS 认证需要用户已经在 PostgreSQL 数据库中存在。RADIUS 服务器只负责验证密码,不提供用户信息。

配置参数详解

必需参数

radiusservers

指定要连接的 RADIUS 服务器地址。

bash
# 单个服务器配置
radiusservers=radius.company.com

# 多个服务器配置(高可用)
radiusservers="radius1.company.com,radius2.company.com"

radiussecrets

RADIUS 服务器的共享密钥,用于加密通信。

bash
# 单个密钥
radiussecrets=MySecretKey123456

# 多个服务器对应不同密钥
radiussecrets="secret1,secret2"

共享密钥必须在 PostgreSQL 和 RADIUS 服务器上完全一致,建议使用至少 16 个字符的强密钥。

可选参数

radiusports

指定 RADIUS 服务器端口号。

bash
# 使用默认端口 1812
# radiusports 不指定即可

# 自定义端口
radiusports=1645

# 多服务器不同端口
radiusports="1812,1645"

radiusidentifiers

NAS (Network Access Server) 标识符,用于标识请求来源。

bash
# 默认标识符
# radiusidentifiers 不指定时使用 "postgresql"

# 自定义标识符
radiusidentifiers=prod-db-cluster

# 多服务器不同标识符
radiusidentifiers="db-cluster-1,db-cluster-2"

实际配置示例

基本配置示例

问题场景:公司需要让所有员工使用统一的域账户访问 PostgreSQL 数据库,实现单点登录。

解决方案:配置 RADIUS 认证连接到公司的 RADIUS 服务器。

步骤 1:配置 pg_hba.conf

bash
# /etc/postgresql/15/main/pg_hba.conf

# 为特定数据库配置 RADIUS 认证
host    myapp_db    all    192.168.1.0/24    radius radiusservers=radius.company.com radiussecrets=CompanySecret2023

配置说明

  • host:允许 TCP/IP 连接
  • myapp_db:指定数据库名称
  • all:允许所有用户(用户仍需在数据库中存在)
  • 192.168.1.0/24:限制访问的 IP 地址范围
  • radius:指定认证方法为 RADIUS

步骤 2:在 PostgreSQL 中创建用户

sql
-- 创建与 RADIUS 服务器中相同的用户名
CREATE USER john_doe WITH LOGIN;
CREATE USER jane_smith WITH LOGIN;

-- 为用户分配适当的权限
GRANT CONNECT ON DATABASE myapp_db TO john_doe;
GRANT USAGE ON SCHEMA public TO john_doe;
GRANT SELECT, INSERT, UPDATE ON ALL TABLES IN SCHEMA public TO john_doe;

步骤 3:测试连接

bash
# 客户端连接测试
psql -h 192.168.1.100 -U john_doe -d myapp_db
# 系统会提示输入密码,这里输入 RADIUS 服务器中的密码

高可用配置示例

问题场景:确保 RADIUS 认证的高可用性,当主 RADIUS 服务器故障时自动切换到备用服务器。

解决方案:配置多个 RADIUS 服务器。

bash
# pg_hba.conf 高可用配置
host all all 0.0.0.0/0 radius \
    radiusservers="radius1.company.com,radius2.company.com" \
    radiussecrets="PrimarySecret2023,BackupSecret2023" \
    radiusports="1812,1812" \
    radiusidentifiers="primary-db,backup-db"

工作机制

  1. PostgreSQL 首先尝试连接 radius1.company.com
  2. 如果主服务器无响应,自动尝试 radius2.company.com
  3. 如果收到拒绝响应,认证立即失败(不会尝试下一个服务器)

复杂环境配置示例

问题场景:在参数值中需要包含逗号或空格的复杂配置。

解决方案:使用双引号嵌套语法。

bash
# 包含空格的密钥配置
host myapp all 192.168.1.0/24 radius \
    radiusservers="server1.company.com,server2.company.com" \
    radiussecrets="""secret with spaces"",""another secret"""

安全考虑

加密安全性

只有在 PostgreSQL 构建时支持 OpenSSL 的情况下,加密向量才是密码学安全的。否则数据传输只能视为模糊处理。

检查 OpenSSL 支持

sql
-- 检查 PostgreSQL 是否支持 SSL
SHOW ssl;

-- 查看编译选项
SELECT name, setting
FROM pg_settings
WHERE name LIKE '%ssl%';

安全最佳实践

  1. 强密钥策略
bash
# 生成强随机密钥(Linux/Unix)
openssl rand -base64 32

# 示例输出:kJ8N3mR5pQ7xF2vL9wC6tE4sA1nH8bY3
  1. 网络隔离
bash
# 限制 RADIUS 流量仅在内网
iptables -A INPUT -p udp --dport 1812 -s 192.168.0.0/16 -j ACCEPT
iptables -A INPUT -p udp --dport 1812 -j DROP
  1. 监控和日志
bash
# PostgreSQL 日志配置
log_connections = on
log_disconnections = on
log_failed_connections = on

故障排除

常见问题诊断

1. 连接被拒绝

问题现象

psql: FATAL: RADIUS authentication failed for user "john_doe"

诊断步骤

bash
# 验证 pg_hba.conf 配置
sudo grep -n radius /etc/postgresql/15/main/pg_hba.conf

# 检查 PostgreSQL 日志
sudo tail -f /var/log/postgresql/postgresql-15-main.log
bash
# 使用 radtest 工具测试(需要安装 freeradius-utils)
radtest john_doe password123 radius.company.com 1812 testing123

# 示例成功输出:
# Sent Access-Request Id 1 from 0.0.0.0:12345 to 192.168.1.100:1812 length 73
# Received Access-Accept Id 1 from 192.168.1.100:1812 to 0.0.0.0:12345 length 20

2. 用户不存在错误

问题现象

psql: FATAL: role "john_doe" does not exist

解决方案

sql
-- 在 PostgreSQL 中创建用户
CREATE USER john_doe WITH LOGIN;

-- 验证用户已创建
\du john_doe

3. 超时问题

问题现象:连接挂起或超时

解决方案

bash
# 检查网络连通性
telnet radius.company.com 1812

# 检查防火墙规则
sudo ufw status | grep 1812

监控配置

设置详细日志

bash
# postgresql.conf
log_min_messages = info
log_connections = on
log_disconnections = on
log_duration = on
log_statement = 'all'

日志分析示例

bash
# 查看 RADIUS 认证日志
grep "RADIUS" /var/log/postgresql/postgresql-15-main.log

# 示例日志输出:
# 2024-06-04 10:30:15.123 UTC [12345] LOG: RADIUS authentication successful for user "john_doe"
# 2024-06-04 10:30:16.456 UTC [12346] LOG: RADIUS authentication failed for user "jane_doe"

性能优化

连接池配置

当使用 RADIUS 认证时,每次连接都需要与 RADIUS 服务器通信,建议使用连接池减少认证频率:

bash
# pgbouncer 配置示例
[databases]
myapp_db = host=localhost port=5432 dbname=myapp_db

[pgbouncer]
listen_port = 6432
auth_type = trust  # 在连接池层不再进行认证
pool_mode = session
max_client_conn = 1000
default_pool_size = 20

缓存策略

虽然 PostgreSQL 不直接提供 RADIUS 认证缓存,但可以通过应用层实现:

python
# Python 示例:应用层认证缓存
import psycopg2
import time
from functools import lru_cache

class DatabaseConnector:
    def __init__(self):
        self.connection_cache = {}

    @lru_cache(maxsize=100)
    def get_connection(self, username, password, host="localhost"):
        """
        缓存数据库连接,减少 RADIUS 认证频率
        注意:实际生产环境中需要考虑安全性
        """
        cache_key = f"{username}@{host}"

        # 检查缓存(简化示例,实际需要考虑过期时间)
        if cache_key in self.connection_cache:
            conn_info = self.connection_cache[cache_key]
            if time.time() - conn_info['timestamp'] < 300:  # 5分钟缓存
                return conn_info['connection']

        # 创建新连接
        try:
            conn = psycopg2.connect(
                host=host,
                database="myapp_db",
                user=username,
                password=password
            )

            # 缓存连接
            self.connection_cache[cache_key] = {
                'connection': conn,
                'timestamp': time.time()
            }

            return conn

        except psycopg2.Error as e:
            print(f"认证失败: {e}")
            return None

与其他认证方法的比较

认证方法优点缺点适用场景
RADIUS集中管理、企业集成、单点登录网络依赖、配置复杂大型企业环境
LDAP目录服务集成、支持复杂查询配置复杂、协议开销企业目录集成
Password简单、无外部依赖密码管理分散小型应用
Certificate高安全性、无密码证书管理复杂高安全要求

总结

RADIUS 认证为 PostgreSQL 提供了企业级的集中身份验证能力,特别适合需要统一用户管理的大型企业环境。通过合理配置和优化,可以在保证安全性的同时提供良好的用户体验。

TIP

最佳实践建议

  1. 安全优先:使用强密钥和网络隔离
  2. 高可用设计:配置多个 RADIUS 服务器
  3. 性能优化:合理使用连接池和缓存
  4. 监控告警:建立完善的日志和监控机制
  5. 定期维护:定期检查配置和更新密钥