↑↓ 选择↵ 打开⌫ 切换范围完整搜索

PG.CENTER 连接 PostgreSQL 文档、百科与生态知识。由 Pigsty 维护。

支持中的版本: 当前版本 (18) / 17 / 16
开发中的版本: 19 / 20devel

20.1. pg_hba.conf 文件 #

客户端认证由一个配置文件控制,该文件按惯例命名为 pg_hba.conf,并存放在数据库集簇的数据目录中。(HBA 代表 host-based authentication,即基于主机的认证。)当数据目录由 initdb 初始化时,会安装一个默认的 pg_hba.conf 文件。不过,也可以把认证配置文件放在别处;请参见配置参数 hba_file。

在启动时以及主服务器进程收到 SIGHUP 信号时,pg_hba.conf 文件会被读取。如果你在运行中的系统上编辑了该文件,就需要通知 postmaster(使用 pg_ctl reload、调用 SQL 函数 pg_reload_conf(),或者使用 kill -HUP)重新读取该文件。

注意

前面的说明不适用于 Microsoft Windows:在 Windows 上,pg_hba.conf 文件中的任何更改会立即被应用到后续的新连接上。

系统视图 pg_hba_file_rules 有助于预先测试对 pg_hba.conf 文件的修改,也可以在加载该文件没有产生预期效果时用于诊断问题。视图中 error 字段非空的行表示文件对应行存在问题。

pg_hba.conf 文件的一般格式是一组记录,每行一条。空白行会被忽略,# 注释字符后面的任何文本也会被忽略。记录可以通过在行尾加反斜线延续到下一行。(反斜线除出现在行尾之外,没有其他特殊含义。)一条记录由若干个字段组成,这些字段之间以空格和/或制表符分隔。如果字段值用双引号括起,则其中可以包含空白。在数据库、用户或地址字段中给关键字加上引号(例如 all 或 replication),会使该词失去其特殊含义,而仅匹配同名的数据库、用户或主机。即使在带引号的文本或注释中,也同样适用反斜线续行。

每条认证记录都指定一种连接类型、一个客户端 IP 地址范围(如果该连接类型需要)、一个数据库名、一个用户名,以及对匹配这些参数的连接要使用的认证方法。第一条同时匹配连接类型、客户端地址、请求数据库和用户名的记录会被用来执行认证。这里不存在“继续向后匹配”或“后备”机制:如果选中某条记录而认证失败,就不会再考虑后续记录。如果没有任何记录匹配,则拒绝访问。

一条记录可以是 include 指令,也可以是认证记录。include 指令用于指定可被包含的文件,这些文件中可以含有额外记录;这些记录会插入到 include 指令所在的位置。include 指令只有两个字段:include、include_if_exists 或 include_dir 指令本身,以及要包含的文件或目录。文件或目录既可以是相对路径,也可以是绝对路径,并且都可以用双引号括起。对于 include_dir 形式,将包含所有文件名不以 . 开头且以 .conf 结尾的文件。include 目录中的多个文件会按照文件名顺序处理(依据 C locale 规则,即数字排在字母前,大写字母排在小写字母前)。

一条记录可以有多种格式:

local         database  user  auth-method [auth-options]
host          database  user  address     auth-method  [auth-options]
hostssl       database  user  address     auth-method  [auth-options]
hostnossl     database  user  address     auth-method  [auth-options]
hostgssenc    database  user  address     auth-method  [auth-options]
hostnogssenc  database  user  address     auth-method  [auth-options]
host          database  user  IP-address  IP-mask      auth-method  [auth-options]
hostssl       database  user  IP-address  IP-mask      auth-method  [auth-options]
hostnossl     database  user  IP-address  IP-mask      auth-method  [auth-options]
hostgssenc    database  user  IP-address  IP-mask      auth-method  [auth-options]
hostnogssenc  database  user  IP-address  IP-mask      auth-method  [auth-options]
include       file
include_if_exists file
include_dir   directory

字段的含义如下:

local #

该记录匹配使用 Unix 域套接字的连接尝试。没有这种类型的记录时,Unix 域套接字连接将被禁止。

host #

该记录匹配使用 TCP/IP 发起的连接尝试。host 记录既匹配 SSL 或非 SSL 连接尝试,也匹配使用 GSSAPI 加密或不使用 GSSAPI 加密的连接尝试。

注意

除非服务器以适当的 listen_addresses 配置参数值启动,否则远程 TCP/IP 连接将不可用,因为默认行为是只在本地回环地址 localhost 上监听 TCP/IP 连接。

hostssl #

该记录匹配使用 TCP/IP 发起的连接尝试,但仅当连接使用 SSL 加密时才匹配。

要使用此选项,服务器必须在构建时启用 SSL 支持。此外,还必须通过设置 ssl 配置参数来启用 SSL(有关更多信息,请参见第 18.9 节)。否则,hostssl 记录将被忽略,只会记录一条警告,说明它无法匹配任何连接。

hostnossl #

该记录类型与 hostssl 的行为相反;它只匹配通过 TCP/IP 发起且不使用 SSL 的连接尝试。

hostgssenc #

该记录匹配使用 TCP/IP 发起的连接尝试,但仅当连接使用 GSSAPI 加密时才匹配。

要使用此选项,服务器必须在构建时启用 GSSAPI 支持。否则,hostgssenc 记录将被忽略,只会记录一条警告,说明它无法匹配任何连接。

hostnogssenc #

该记录类型与 hostgssenc 的行为相反;它只匹配通过 TCP/IP 发起且不使用 GSSAPI 加密的连接尝试。

database #

指定此记录匹配的数据库名称。值 all 指定匹配所有数据库。值 sameuser 指定如果请求的数据库与请求的用户具有相同的名称,则记录匹配。值 samerole 指定请求的用户必须是与请求的数据库具有相同名称的角色的成员。(samegroup 是 samerole 的一种过时但仍被接受的写法。)对于 samerole 而言,超级用户并不会仅因其超级用户身份就被视为某个角色的成员;只有当其显式地直接或间接属于该角色时,才会被视为成员。值 replication 表示当请求的是物理复制连接时匹配,但不匹配逻辑复制连接。请注意,物理复制连接不指定任何特定数据库,而逻辑复制连接会指定数据库。否则,这里可以是某个特定 PostgreSQL 数据库的名称,或者一个正则表达式。多个数据库名和/或正则表达式可以用逗号分隔提供。

如果数据库名以斜线(/)开头,则其余部分会被视为一个正则表达式。(关于 PostgreSQL 正则表达式语法的细节,见第 9.7.3.1 节。)

也可以通过在文件名前加上@来指定一个单独文件,该文件中包含数据库名和/或正则表达式。

user #

指定此记录匹配哪些数据库用户名。值 all 表示匹配所有用户。否则,这里可以是某个特定数据库用户的名称、一个正则表达式(以斜线(/)开头时),或者一个以前缀 + 标识的组名。(请记住,在 PostgreSQL 中,用户和组之间并没有真正区别;+ 标记实际上表示“匹配直接或间接属于该角色的任意角色”,而没有 + 标记的名称只匹配该特定角色。)为此目的,只有在超级用户显式地直接或间接属于该角色时,才会被视为该角色的成员,而不会仅因其超级用户身份而被视为成员。多个用户名和/或正则表达式可以用逗号分隔提供。

如果用户名以斜线(/)开头,则其余部分会被视为一个正则表达式。(关于 PostgreSQL 正则表达式语法的细节,见第 9.7.3.1 节。)

也可以通过在文件名前加上@来指定一个单独文件,该文件中包含用户名和/或正则表达式。

address #

指定此记录匹配的客户端机器地址。此字段可以包含主机名、IP 地址范围或下面提到的特殊关键字之一。

IP 地址范围使用标准的数字表示法来指定起始地址,然后是斜杠(/)和一个 CIDR 掩码长度。掩码长度表示客户端 IP 地址必须匹配的高位比特数。给定 IP 地址中右侧的比特应为零。IP 地址、/和 CIDR 掩码长度之间不得有任何空白。

以这种方式指定的 IPv4 地址范围的典型示例包括 172.20.143.89/32 用于单个主机,或 172.20.143.0/24 用于小型网络,或 10.6.0.0/16 用于较大的网络。IPv6 地址范围可能看起来像::1/128 用于单个主机(在这种情况下是 IPv6 环回地址)或 fe80::7a31:c1ff:0000:0000/96 用于小型网络。0.0.0.0/0 代表所有 IPv4 地址,::0/0 代表所有 IPv6 地址。要指定单个主机,请对 IPv4 使用 32 的掩码长度,对 IPv6 使用 128。在网络地址中,不要省略尾部的零。

以 IPv4 格式给出的条目将仅匹配 IPv4 连接,以 IPv6 格式给出的条目将仅匹配 IPv6 连接,即使所代表的地址在 IPv4-in-IPv6 范围内。

你也可以写 all 来匹配任何 IP 地址,samehost 来匹配服务器自己的任何 IP 地址,或 samenet 来匹配服务器直接连接到的任何子网中的任何地址。

如果指定了主机名(任何不是 IP 地址范围或特殊关键字的内容都被视为主机名),则将该名称与客户端 IP 地址的反向名称解析结果进行比较(例如,如果使用 DNS,则进行反向 DNS 查找)。主机名比较不区分大小写。如果匹配成功,则对主机名执行正向名称解析(例如,进行正向 DNS 查找),以检查其解析为的任何地址是否等于客户端 IP 地址。如果两个方向都匹配,则将条目视为匹配。(在 pg_hba.conf 中使用的主机名应该是客户端 IP 地址的地址到名称解析返回的名称,否则该行将不会匹配。一些主机名数据库允许将 IP 地址与多个主机名关联,但操作系统在要求解析 IP 地址时只会返回一个主机名。)

以点(.)开头的主机名规范匹配实际主机名的后缀。因此,.example.com 将匹配 foo.example.com(但不匹配单独的 example.com)。

当在 pg_hba.conf 中指定主机名时,应确保名称解析相对快速。设置一个本地名称解析缓存可能会有帮助,如 nscd。此外,还可能希望启用配置参数 log_hostname,以便在日志中看到客户端的主机名而不是 IP 地址。

这些字段不适用于 local 记录。

注意

用户有时会想知道为什么主机名以这种看似复杂的方式处理,包括两次名称解析,其中包括对客户端 IP 地址的反向查找。如果客户端的反向 DNS 条目未设置或返回了不符合预期的主机名,则使用该功能会变得复杂。这主要是为了效率:这样,连接尝试最多需要两次解析器查找,一次反向查找和一次正向查找。如果某个地址存在解析器问题,那就只会成为该客户端的问题。一个只进行正向查找的假设替代实现,在每次连接尝试期间都必须解析 pg_hba.conf 中提到的每个主机名。如果列出了许多名称,这可能会非常慢。如果其中一个主机名存在解析器问题,那么这将成为所有人的问题。

此外,实现后缀匹配功能需要进行反向查找,因为需要知道实际客户端主机名以便将其与模式进行匹配。

请注意,这种行为与其他流行的基于主机名的访问控制实现一致,例如 Apache HTTP 服务器和 TCP Wrappers。

IP-address
IP-mask #

这两个字段可以用作 IP-address/mask-length 表示法的替代方案。不指定掩码长度,而是在单独一列中指定实际掩码。例如,255.0.0.0 表示 IPv4 的 CIDR 掩码长度为 8,而 255.255.255.255 表示 CIDR 掩码长度为 32。

这些字段不适用于 local 记录。

auth-method #

指定连接匹配此记录时要使用的认证方法。可选值在此处做了概述;详细说明见第 20.3 节。所有选项都必须使用小写并且区分大小写,因此即使是像 ldap 这样的首字母缩写也必须写成小写。

trust #

无条件允许连接。这种方法允许任何能够连接到 PostgreSQL 数据库服务器的人以任意他们希望的 PostgreSQL 用户身份登录,无需密码或任何其他认证。详见第 20.4 节。

reject #

无条件拒绝连接。这对于“过滤掉”某些主机很有用,例如一个 reject 行可以阻止特定主机连接,而后面的行允许特定网络中的其余主机连接。

scram-sha-256 #

执行 SCRAM-SHA-256 认证以校验用户密码。详见第 20.5 节。

md5 #

执行 SCRAM-SHA-256 或 MD5 认证以校验用户密码。详见第 20.5 节。

password #

要求客户端提供未加密的密码以完成认证。由于密码会以明文形式通过网络发送,因此不应在不受信任的网络上使用。详见第 20.5 节。

gss #

使用 GSSAPI 对用户进行认证。这仅适用于 TCP/IP 连接。详见第 20.6 节。它可以与 GSSAPI 加密配合使用。

sspi #

使用 SSPI 对用户进行认证。这仅适用于 Windows。详见第 20.7 节。

ident #

通过联系客户端上的 ident 服务器获取客户端的操作系统用户名,并检查它是否与请求的数据库用户名匹配。Ident 认证只能用于 TCP/IP 连接。当为本地连接指定时,将改为使用 peer 认证。详见第 20.8 节。

peer #

从操作系统获取客户端的操作系统用户名,并检查是否与请求的数据库用户名匹配。这仅适用于本地连接。有关详细信息,请参见第 20.9 节。

ldap #

使用 LDAP 服务器进行认证。详见第 20.10 节。

radius #

使用 RADIUS 服务器进行认证。详见第 20.11 节。

cert #

使用 SSL 客户端证书进行认证。详见第 20.12 节。

pam #

使用操作系统提供的可插拔认证模块(PAM)服务进行认证。详见第 20.13 节。

bsd #

使用操作系统提供的 BSD 认证服务进行认证。详见第 20.14 节。

auth-options #

在 auth-method 字段之后,可以有一个或多个形如 name=value 的字段,用于指定认证方法的选项。下文会详细说明各认证方法有哪些可用选项。

除了下面列出的特定于方法的选项外,还有一个方法无关的认证选项 clientcert,可以在任何 hostssl 记录中指定。此选项可以设置为 verify-ca 或 verify-full。这两个选项都要求客户端提供有效(受信任的)SSL 证书,而 verify-full 还要求证书中的 cn(通用名称)与用户名或适用映射匹配。这种行为类似于 cert 认证方法(见第 20.12 节),但允许把客户端证书验证与任何支持 hostssl 条目的认证方法配合使用。

对于任何使用客户端证书认证的记录(即使用 cert 认证方法的记录,或使用 clientcert 选项的记录),都可以通过 clientname 选项指定要匹配客户端证书凭据中的哪一部分。此选项有两个可选值。如果指定 clientname=CN,这也是默认值,则用户名将与证书的 Common Name (CN) 匹配。如果改为指定 clientname=DN,则用户名将与证书的完整 Distinguished Name (DN) 匹配。此选项可能更适合与用户名映射配合使用。比较时使用的是 RFC 2253 格式的 DN。要查看以这种格式表示的客户端证书 DN,请执行

openssl x509 -in myclient.crt -noout -subject -nameopt RFC2253 | sed "s/^subject=//"

在使用此选项时需要小心,特别是在使用正则表达式匹配 DN 时。

include #

这一行会被给定文件的内容替换。

include_if_exists #

如果给定文件存在,这一行会被该文件的内容替换;否则会记录一条消息,说明该文件已被跳过。

include_dir #

这一行会被目录中找到的所有文件内容替换,前提是这些文件名不以 . 开头并且以 .conf 结尾;这些文件会按照文件名字典序处理(依据 C locale 规则,即数字排在字母前,大写字母排在小写字母前)。

由 @ 构造引用的文件会被读取为名称列表,其中的名称可以用空白或逗号分隔。注释仍然用 # 引入,与 pg_hba.conf 中相同,并且允许嵌套的 @ 构造。除非 @ 后面的文件名是绝对路径,否则它会被视为相对于引用它的文件所在目录。

由于每次连接尝试都会按顺序检查 pg_hba.conf 记录,因此记录的顺序很重要。通常,靠前的记录使用较严格的连接匹配条件和较弱的认证方法,靠后的记录使用较宽松的匹配条件和较强的认证方法。例如,可能希望对本地 TCP/IP 连接使用 trust 认证,而要求远程 TCP/IP 连接提供密码。此时,为来自 127.0.0.1 的连接指定 trust 认证的记录,应放在为更大范围的允许客户端 IP 地址指定密码认证的记录之前。

提示

要连接到一个特定数据库,一个用户不仅要通过 pg_hba.conf 检查,还必须有该数据库上的 CONNECT 权限。如果你希望限制哪些用户能够连接到哪些数据库,授予/撤销 CONNECT 权限通常比在 pg_hba.conf 项中设置规则简单。

例 20.1 展示了一些 pg_hba.conf 条目示例。有关不同认证方法的详细信息,参见下一节。

例 20.1. 示例 pg_hba.conf 项

# 允许本地系统上的任何用户
# 通过 Unix 域套接字(本地连接的默认方式)以任意
# 数据库用户名连接到任意数据库。
#
# TYPE  DATABASE        USER            ADDRESS                 METHOD
local   all             all                                     trust

# 相同的规则,但是使用本地环回 TCP/IP 连接。
#
# TYPE  DATABASE        USER            ADDRESS                 METHOD
host    all             all             127.0.0.1/32            trust

# 和前一行相同,但是使用了一个独立的掩码列
#
# TYPE  DATABASE        USER            IP-ADDRESS      IP-MASK             METHOD
host    all             all             127.0.0.1       255.255.255.255     trust

# IPv6 上相同的规则
#
# TYPE  DATABASE        USER            ADDRESS                 METHOD
host    all             all             ::1/128                 trust

# 使用主机名的相同规则(通常同时覆盖 IPv4 和 IPv6)。
#
# TYPE  DATABASE        USER            ADDRESS                 METHOD
host    all             all             localhost               trust

# 使用 DATABASE 正则表达式的相同规则,它允许连接到任何
# 名称以 "db" 开头并以两到四位数字结尾的数据库
# (例如 "db1234" 或 "db12")。
#
# TYPE  DATABASE        USER            ADDRESS                 METHOD
host    "/^db\d{2,4}$"  all             localhost               trust

# 允许来自任意具有 IP 地址192.168.93.x 的主机上任意
# 用户以 ident 为该连接所报告的相同用户名连接到
# 数据库 "postgres"(通常是操作系统用户名)。
#
# TYPE  DATABASE        USER            ADDRESS                 METHOD
host    postgres        all             192.168.93.0/24         ident

# 如果用户的密码被正确提供,允许来自主机 192.168.12.10
# 的任意用户连接到数据库 "postgres"。
#
# TYPE  DATABASE        USER            ADDRESS                 METHOD
host    postgres        all             192.168.12.10/32        scram-sha-256

# 如果用户的密码被正确提供,允许 example.com 域中主机上
# 的任意用户连接到任意数据库。
#
# 为大部分用户要求SCRAM认证,但是用户'mike'是个例外,
# 他使用的是不支持SCRAM认证的旧客户端。
#
# TYPE  DATABASE        USER            ADDRESS                 METHOD
host    all             mike            .example.com            md5
host    all             all             .example.com            scram-sha-256

# 如果没有前面的 "host" 行,这三行
# 将拒绝所有来自 192.168.54.1的连接(因为该条目将首先被匹配),
# 但是允许来自互联网其他任何地方的
# GSSAPI 加密连接。零掩码表示不会考虑主机 IP 地址中的任何位,
# 因此它会匹配任意主机。未加密的 GSSAPI 连接
# (由于 "hostgssenc" 只匹配加密的 GSSAPI 连接,因此它们会继续匹配到第三行)
# 也是允许的,但只能来自 192.168.12.10。
#
# TYPE  DATABASE        USER            ADDRESS                 METHOD
host    all             all             192.168.54.1/32         reject
hostgssenc all          all             0.0.0.0/0               gss
host    all             all             192.168.12.10/32        gss

# 允许来自 192.168.x.x 主机的用户连接到任意数据库,如果它们能够
# 通过 ident 检查。例如,假设 ident说用户是 "bryanh" 并且他要求以
# PostgreSQL 用户 "guest1" 连接,如果在 pg_ident.conf 有一个映射
# "omicron" 的条目表明 "bryanh" 被允许以 "guest1" 连接,则该连接将被允许。
#
# TYPE  DATABASE        USER            ADDRESS                 METHOD
host    all             all             192.168.0.0/16          ident map=omicron

# 如果这些是本地连接的唯一四行,它们将允许本地用户只连接到它们
# 自己的数据库(与其数据库用户名同名的数据库),不过用户名以
# "helpdesk" 结尾的用户、管理员以及角色 "support" 的成员除外
# (它们可以连接到所有数据库)。文件 $PGDATA/admins 包含一个
# 管理员名字的列表。在所有情况下都要求密码。
#
# TYPE  DATABASE        USER            ADDRESS                 METHOD
local   sameuser        all                                     md5
local   all             /^.*helpdesk$                           md5
local   all             @admins                                 md5
local   all             +support                                md5

# 上面的最后两行可以被整合为一行:
local   all             @admins,+support                        md5

# 数据库列也可以用列表和文件名:
local   db1,db2,@demodbs  all                                   md5

报告文档问题

阅读 上游文档. 通过 PostgreSQL 文档反馈表单.