Appearance
PostgreSQL Ident 认证详解
概述
Ident 认证是 PostgreSQL 提供的一种身份验证方法,它通过从 ident 服务器获取客户端的操作系统用户名,并将其用作允许的数据库用户名。这种认证方式基于 RFC 1413 定义的"标识协议"。
WARNING
Ident 认证仅在 TCP/IP 连接上受支持。当为本地(非 TCP/IP)连接指定 ident 时,PostgreSQL 将自动改为使用对等身份验证(peer authentication)。
工作原理
Ident 协议机制
Ident 认证的工作流程如下:
基本概念
组件 | 描述 | 端口 |
---|---|---|
Ident 服务器 | 运行在客户端机器上的服务 | TCP 113 |
PostgreSQL 服务器 | 数据库服务器 | 通常 5432 |
客户端应用 | 连接数据库的应用程序 | 随机端口 |
配置选项
pg_hba.conf 配置
在 pg_hba.conf
文件中配置 Ident 认证:
bash
# TYPE DATABASE USER ADDRESS METHOD
host mydatabase dbuser 192.168.1.0/24 ident
host all all 10.0.0.0/8 ident map=mymap
支持的配置参数
map 参数
map
参数允许在系统用户名和数据库用户名之间进行映射。
bash
# 不使用映射,系统用户名必须与数据库用户名完全匹配
host mydb john 192.168.1.100/32 ident
bash
# 使用名为 "mymap" 的用户名映射
host mydb dbuser 192.168.1.0/24 ident map=mymap
实际应用示例
示例 1:基本 Ident 认证配置
问题陈述:在企业内部网络中,需要让系统用户直接使用其操作系统账户连接 PostgreSQL 数据库。
解决方案:
- 配置 pg_hba.conf:
bash
# 允许内网用户使用 ident 认证
host company_db all 192.168.1.0/24 ident
- 确保客户端运行 ident 服务:
bash
# 在 Linux 系统上检查 ident 服务状态
sudo systemctl status identd
# 启动 ident 服务(如果未运行)
sudo systemctl start identd
- 创建对应的数据库用户:
sql
-- 为系统用户 'john' 创建数据库用户
CREATE USER john;
GRANT CONNECT ON DATABASE company_db TO john;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO john;
分析过程:
- PostgreSQL 接收来自 IP
192.168.1.100
的连接请求 - 查询该 IP 的 ident 服务器,获取发起连接的系统用户名(如 'john')
- 检查数据库中是否存在名为 'john' 的用户
- 如果存在且有相应权限,则允许连接
输入和输出:
bash
# 客户端连接命令
psql -h database.company.com -d company_db -U john
# 成功连接输出
psql (15.3)
Type "help" for help.
company_db=>
示例 2:使用用户名映射的 Ident 认证
问题陈述:系统用户名与期望的数据库用户名不匹配,需要建立映射关系。
解决方案:
- 配置用户名映射文件(
pg_ident.conf
):
bash
# MAPNAME SYSTEM-USERNAME PG-USERNAME
mymap john db_john
mymap mary db_mary
mymap admin dba
- 配置 pg_hba.conf:
bash
host mycompany db_john,db_mary 192.168.1.0/24 ident map=mymap
host postgres dba 192.168.1.10/32 ident map=mymap
- 创建映射的数据库用户:
sql
-- 创建映射后的数据库用户
CREATE USER db_john;
CREATE USER db_mary;
CREATE USER dba SUPERUSER;
-- 分配权限
GRANT CONNECT ON DATABASE mycompany TO db_john, db_mary;
GRANT ALL PRIVILEGES ON DATABASE postgres TO dba;
分析过程:
- 系统用户 'john' 连接数据库时,PostgreSQL 查询 ident 服务器获取 'john'
- 根据 'mymap' 映射规则,将 'john' 映射为 'db_john'
- 检查 'db_john' 用户的权限并允许连接
测试示例:
bash
# 系统用户 john 连接(会被映射为 db_john)
psql -h localhost -d mycompany -U db_john
# 系统管理员连接(会被映射为 dba)
psql -h localhost -d postgres -U dba
sql
-- 连接后检查当前用户
SELECT current_user;
-- 输出: db_john
-- 检查可访问的数据库
\l
-- 检查当前数据库权限
\dp
安全考虑
安全风险分析
安全最佳实践
DANGER
重要安全警告 RFC 1413 明确声明:"标识协议不打算作为授权或访问控制协议。" 因此,Ident 认证存在固有的安全风险。
1. 适用场景限制
bash
# 仅在以下情况下使用 Ident 认证:
# - 完全受控的内部网络
# - 客户端机器可信
# - 数据库和系统管理员紧密合作
2. 网络安全配置
bash
# 限制连接来源
host mydb all 127.0.0.1/32 ident # 仅本机
host mydb all 192.168.1.0/24 ident # 仅内网
3. 避免加密选项
WARNING
一些 ident 服务器提供加密选项,会返回加密的用户名。PostgreSQL 无法解密这些字符串,因此绝不能使用此选项。
故障排除
常见问题诊断
问题 | 可能原因 | 解决方案 |
---|---|---|
连接被拒绝 | Ident 服务未运行 | 启动客户端 ident 服务 |
用户名不匹配 | 缺少用户映射 | 配置 pg_ident.conf |
超时错误 | 网络问题或防火墙 | 检查端口 113 连通性 |
调试步骤
- 检查 ident 服务状态:
bash
# Linux 系统
netstat -tlnp | grep :113
systemctl status identd
# 测试 ident 响应
telnet client_ip 113
- 查看 PostgreSQL 日志:
bash
# 启用详细日志
log_connections = on
log_disconnections = on
log_line_prefix = '%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h '
- 手动测试 ident 查询:
bash
# 使用 ident 客户端工具测试
echo "LOCAL_PORT, REMOTE_PORT" | nc client_ip 113
性能考量
性能影响分析
优化建议
- 设置合理的超时时间:
bash
# postgresql.conf
ident_timeout = 5s # 默认 10s,可适当缩短
- 使用连接池:
bash
# 减少频繁的认证开销
# 使用 pgbouncer 或应用层连接池
与其他认证方法的比较
认证方法 | 安全性 | 性能 | 复杂度 | 适用场景 |
---|---|---|---|---|
Ident | 低 | 中等 | 低 | 受控内网 |
Peer | 中 | 高 | 低 | 本地连接 |
Password | 高 | 高 | 中 | 通用场景 |
Certificate | 很高 | 中 | 高 | 高安全要求 |
TIP
选择建议在现代环境中,建议优先考虑更安全的认证方法,如证书认证或 SCRAM-SHA-256 密码认证,而不是 Ident 认证。
总结
Ident 认证虽然配置简单,但存在显著的安全风险。它适用于完全受控的内部网络环境,其中所有客户端机器都是可信的。在实际部署中,需要仔细评估安全需求,并考虑使用更安全的认证替代方案。
INFO
关键要点
- Ident 认证依赖客户端 ident 服务器的诚实性
- 仅适用于 TCP/IP 连接
- 支持用户名映射功能
- 在安全敏感环境中应避免使用
- 需要客户端运行 ident 服务(端口 113)