分享到

简介

使用 PostgreSQL 数据库时,首先需要考虑的事情之一是如何连接和交互数据库实例。这需要在数据库客户端(您用于与数据库交互的组件)和数据库服务器(实际存储、组织和提供数据访问的 PostgreSQL 实例)之间进行协调。

为了成功管理这一点,您需要了解如何配置 PostgreSQL 实例,以允许您需要的访问类型和 身份验证 方法。在本指南中,我们将介绍如何修改数据库服务器的身份验证机制,以满足您环境的需求。

在配套指南中,我们介绍了 如何使用数据库客户端连接到 PostgreSQL 实例。建议阅读这两份指南,以便更全面地了解 PostgreSQL 中的身份验证工作原理。

了解 PostgreSQL 的身份验证文件

如果您想修改决定用户如何验证 PostgreSQL 实例身份的规则,可以通过修改服务器的配置来实现。

您需要修改的特定文件名为 pg_hba.conf

请注意,您必须重启 PostgreSQL 实例,任何新的身份验证配置才能生效。不同的操作系统将以不同的方式处理此操作。在大多数 Linux 发行版中,您可以键入 sudo systemctl restart postgresql。如果您通过 brew 安装了 PostgreSQL,您可以尝试键入 brew services restart postgresql。在更广泛的系统上可能有效的另一种方法是 pg_ctl restart

查找 pg_hba.conf 文件

要在服务器上找到 pg_hba.conf 文件,您可以查看 PostgreSQL 配置目录。具体位置取决于您使用的操作系统和 PostgreSQL 版本。

如果您不知道身份验证配置文件的位置,但您确实可以访问数据库,则可以查询 PostgreSQL 以获取文件位置,正如 Craig Ringer 在这篇文章中演示的那样

如果您在命令行中,可以键入以下命令,该命令查询 pg_hba.conf 文件的位置,并告诉 PostgreSQL 仅打印文件位置而不进行格式化

psql -t -P format=unaligned -c 'SHOW hba_file;'
/etc/postgresql/10/main/pg_hba.conf

如果您已经打开了 PostgreSQL 会话,则只需键入

SHOW hba_file;
hba_file
-------------------------------------
/etc/postgresql/10/main/pg_hba.conf
(1 row)

获得 pg_hba.conf 文件的位置后,在文本编辑器中打开它以查看配置并进行更改

vim /etc/postgresql/10/main/pg_hba.conf

默认情况下,该文件包含当前配置以及许多有用的注释。

了解 pg_hba.conf 文件格式

pg_hba.conf 文件使用以纯文本实现的类似表格的结构。删除空行和注释后,基本文件可能如下所示

# TYPE DATABASE USER ADDRESS METHOD OPTIONS
local all postgres peer
local all all peer
host all all 127.0.0.1/32 md5
host all all ::1/128 md5
local replication all peer
host replication all 127.0.0.1/32 md5
host replication all ::1/128 md5

让我们看一下不同字段的含义以及如何解释文件内容。

pg_hba.conf 文件的结构和解释方式

pg_hba.conf 文件中的每一行都描述了客户端验证系统身份的一种方式。每行的大部分内容描述了用于与传入连接请求进行比较的匹配条件。最后一部分指定了允许的身份验证方法以及身份验证所需的任何选项。

当 PostgreSQL 根据身份验证规则评估连接请求时,它会按顺序从上到下进行。如果一行的配置与连接请求的特征相匹配,PostgreSQL 将使用该行上指定的身份验证信息来决定是否验证客户端的身份。

如果客户端成功通过身份验证,则会建立连接。如果身份验证不成功,则连接将被拒绝。PostgreSQL 不会 继续处理以查看其他规则是否与请求匹配。因此,规则的顺序非常重要。

在每一行中,字段都用空格(空格或制表符)分隔。尽管通常将这些字段格式化为列在视觉上很有帮助,但 PostgreSQL 并不要求这样做。

pg_hba.conf 文件中每个字段的含义

现在您已经对文件的结构和解释方式有了一些了解,我们可以开始讨论每个字段的含义。

我们将介绍的字段是

  • 连接类型
  • 数据库
  • 用户名
  • 地址
  • 身份验证方法
  • 身份验证方法的选项

连接类型

每个记录中的第一个字段指定要匹配的连接请求类型。只有使用指定连接的连接才会匹配每个规则。

连接类型必须是以下之一

  • local:带有 local 的记录匹配通过本地 Unix 域套接字文件而不是通过网络建立的连接。出于安全和性能原因,尽可能首选本地连接。
  • host:以 host 开头的行匹配通过网络发出的任何连接请求。这是网络连接的通用捕获所有类型。以下类型提供更精细的匹配。
  • hostsslhostssl 连接类型匹配通过网络使用 TLS/SSL 加密建立的任何连接。允许外部连接时,这通常是最佳的连接类型。
  • hostnosslhostnossl 类型匹配任何未使用 TLS/SSL 保护的网络连接。

从 PostgreSQL 12 开始,还增加了对 GSSAPI 连接 的支持,引入了以下附加选项

  • hostgssenchostgssenc 连接类型匹配任何使用 GSSAPI 加密的网络连接。此选项仅适用于那些已经使用 GSSAPI 进行安全保护的用户。
  • hostnogssenchostnogssen 类型匹配每个不使用 GSSAPI 加密的网络连接。

数据库

下一个字段指定请求尝试访问的数据库。连接请求中指定的数据库必须满足此列中找到的值,该行才能匹配。

值可以是以下任何一项

  • all:数据库值 all 是一个捕获所有值,它匹配任何请求的数据库。如果您不希望当前匹配规则评估数据库值,这将非常有用。
  • sameusersameuser 值匹配请求的数据库和用户名相同的连接。
  • samerole:如果指定的用户是与请求的数据库同名的角色的成员,则 samerole 数据库值将匹配连接。
  • replication:使用 replication 值将匹配任何用于数据库复制的传入连接。用于复制的连接不提供数据库目标,因此这会匹配复制请求。
  • [特定数据库名称]:您还可以提供一个或多个特定数据库名称以进行匹配。只有当连接请求其中一个列出的数据库时,这些才会匹配连接。您可以使用逗号分隔多个数据库名称,或者通过在文件名前加上 @ 符号来指定要从中读取名称的文件。

用户

下一个字段用于匹配连接请求提供的用户。连接的用户值必须满足规则的用户字段才能匹配规则。

用户字段可以采用以下选项

  • all:值 all 告诉 PostgreSQL 连接用户参数中的任何值都满足此规则的用户要求。
  • [特定用户或组名]:用户字段的唯一其他选项是提供特定用户、用户列表或组。可以通过用逗号分隔值来指定多个用户。如果名称以 + 符号开头,则它被解释为组名而不是用户名。在这种情况下,如果请求的用户是规则指定的组的成员,则规则将匹配。同样,您可以通过提供文件名前面带有 @ 符号的文件名,来告诉 PostgreSQL 从文件中读取值,而不是内联提供它们。

地址

对于所有以 host 开头的连接类型(hosthostsslhostnossl,以及 PostgreSQL 12 及更高版本中的 hostgssenchostnogssenc),接下来是一个地址字段。对于 local 连接,此字段将被跳过。

地址字段指定客户端机器的地址或模式,以与连接的地址进行匹配。这意味着连接是根据其来源位置进行评估的。连接的来源必须满足规则的地址值,规则才能匹配。

地址字段可以填写以下任何一项

  • all:地址值 all 告诉 PostgreSQL 任何客户端地址都将满足此条件。
  • samehost:值 samehost 用于指示来自服务器自身 IP 地址之一的任何网络连接都应匹配。
  • samenetsamenet 值指示来自服务器网络子网的任何 IP 地址都将匹配。
  • [CIDR IP 地址范围]:您还可以使用 CIDR 表示法 提供 IP 地址范围。这可以指定单个 IP 地址(对于 IPv4 地址使用 /32 子网,对于 IPv6 地址使用 /128 子网),或者通过提供更广泛的 CIDR 掩码来指定地址范围。IP 地址范围将仅匹配使用指定的 IP 协议从指定范围内建立的客户端连接。
  • [主机名]:也可以直接指定主机名。在这种情况下,将使用正向和反向 DNS 查询评估客户端的主机名,以确保其按预期解析。如果指定的主机名以点开头,则任何在该域上正确解析的主机都将满足要求。

身份验证方法

如果连接满足所有先前的匹配条件,则应用给定的身份验证方法。这是每行中的下一个字段。

身份验证方法是 PostgreSQL 决定是否接受与规则匹配的连接的方式。它可以设置为以下任何选项

  • trust:值 trust 立即接受连接,无需进一步要求。这假设其他外部身份验证方法已就位。在大多数情况下不建议使用。
  • reject:值 reject 立即拒绝连接。这主要用于过滤掉与不需要的模式匹配的连接。
  • scram-sha-256scram-sha-256 方法将使用 SCRAM-SHA-256 身份验证 检查用户提供的密码。如果您的所有客户端都支持它,那么这是目前密码身份验证最安全的选择。
  • md5md5 方法也检查用户密码。此方法不如 scram-sha-256 安全,但支持更广泛。如果密码使用 SCRAM 加密,即使指定了 md5,当前实现也会自动使用 scram-sha-256
  • passwordpassword 方法是安全性最低的密码身份验证方法。它以纯文本形式发送密码,除非连接使用 TLS/SSL 加密整个连接,否则不应使用。
  • gssgss 方法使用 GSSAPI 进行身份验证。无论连接是否使用 GSSAPI 加密,都可以将其用于身份验证。这允许通过 Kerberos 和类似软件进行身份验证。
  • sspisspi 方法使用仅 Windows 的安全支持提供程序接口 API 来验证客户端身份。
  • identident 方法与客户端的 ident 服务器检查发起连接的用户。由于这依赖于客户端的机器,因此仅应将其用于客户端机器受到严格控制的受信任网络。
  • peerpeer 身份验证方法用于本地连接。它向本地操作系统询问客户端的系统用户名。它检查名称是否与请求的数据库名称匹配。
  • ldapldap 方法通过使用 LDAP 服务器 验证用户名和密码来进行身份验证。
  • radius:选择 radius 以使用 RADIUS 服务器 检查用户名和密码组合。
  • certcert 方法使用 TLS/SSL 客户端证书验证客户端身份。这仅适用于 TLS/SSL 连接。客户端证书必须是有效的、受信任的证书才能被接受。
  • pampam 选项会将身份验证推迟到操作系统的 PAM 服务
  • bsdbsd 方法使用 BSD 身份验证服务 来验证用户名和密码。此方法仅在 OpenBSD 主机上可用。

上述某些方法仅适用于某些类型的连接或具有就位的其他基础设施。对于大多数部署,rejectpeerscram-sha-256md5 足以开始使用其他方法,例如 ldap,具体取决于您的基础设施。

身份验证选项

在身份验证方法之后,可能会出现最后一个可选列,以提供身份验证方法的其他选项。此列的使用在很大程度上取决于所选身份验证方法的类型。

对于引用外部服务器的身份验证方法,这些选项通常指定主机和连接信息,以便 PostgreSQL 可以成功查询身份验证服务。许多身份验证方法通用的另一个选项是 map 参数,它允许您在系统用户名和 PostgreSQL 数据库用户名之间进行转换。

每种身份验证方法都有自己的一组有效选项。请务必在 PostgreSQL 文档 中查看每种方法的页面上的适用选项。

配置常用身份验证策略

我们已经介绍了一些主要的身份验证选项,但是如何使用这些选项来实现合理的策略呢?在本节中,我们将介绍如何配置一些最常用的身份验证策略。

允许本地用户连接到匹配的数据库

通常配置 PostgreSQL 以允许同一机器上的用户验证到相同的 PostgreSQL 用户名。例如,使用 peer 身份验证,如果 PostgreSQL 也具有名为 john 的用户名,则名为 john 的操作系统用户将能够自动登录而无需密码。

这适用于使用 PostgreSQL 套接字文件建立的任何本地连接。如果您指定任何网络地址,即使它是 127.0.0.1 本地环回设备,连接也不会使用套接字,并且不会匹配 peer 身份验证行。但是,与 localhost 的连接将使用套接字文件,并将匹配这些行。

要允许所有 PostgreSQL 用户从匹配的操作系统用户进行身份验证,请添加一行,该行匹配 local 连接类型,允许所有数据库和用户名,并使用 peer 身份验证

# TYPE DATABASE USER ADDRESS METHOD OPTIONS
local all all peer

如果您想限制这一点,以便只有 johnsue PostgreSQL 用户可以通过这种方式进行身份验证,请限制 USER 列的范围

# TYPE DATABASE USER ADDRESS METHOD OPTIONS
local all john,sue peer

如果您需要允许名为 sue 的操作系统用户验证到名为 susan 的数据库用户,则可以在行尾指定 map 选项。选择一个映射名称来标识此映射

# TYPE DATABASE USER ADDRESS METHOD OPTIONS
local all john,sue peer map=my-map-name

然后,您可以通过在同一目录中打开 pg_ident.conf 文件来映射您的用户

vim pg_ident.conf

通过在此文件中添加一行来创建您需要的映射,指定您选择的映射名称、操作系统用户名和 PostgreSQL 用户名,并用空格分隔

# MAPNAME SYSTEM-USERNAME PG-USERNAME
my-map-name sue susan

现在,sue 操作系统将能够使用 peer 身份验证验证到 susan PostgreSQL 用户,就像它们匹配一样。

允许使用密码从同一台机器进行网络连接

要使用密码验证来自 PostgreSQL 服务器机器的网络连接(非套接字连接),您需要匹配 host 连接类型,而不是 local。然后,您可以将可接受的地址限制为本地环回设备,并允许用户使用 md5scram-sha-256 进行身份验证。

例如,如果 PostgreSQL 所在机器上的用户尝试通过指定 127.0.0.1 作为主机进行连接,PostgreSQL 可以执行密码身份验证。

要进行此设置,我们需要使用 host 连接类型。接下来,我们需要指定可接受地址的范围。由于此规则应仅匹配本地连接,我们将指定本地环回设备。我们将需要添加两行单独的行来匹配 IPv4 和 IPv6 环回设备。

之后,您可以指定要用于身份验证的密码方案。scram-sha-256 方法更安全,但 md5 方法得到更广泛的支持。

完成的身份验证行将如下所示

# TYPE DATABASE USER ADDRESS METHOD OPTIONS
host all all 127.0.0.1/32 md5
host all all ::1/128 md5

您可以通过将相应的列从 all 更改为特定实体的逗号分隔列表来限制允许使用此方法进行身份验证的数据库或用户。

允许自动维护

定期执行各种自动化维护任务。为了确保这些操作可以按预期进行身份验证和运行,您需要确保管理帐户能够以非交互方式进行身份验证。

默认情况下,postgres 帐户配置为此角色,使用 peer 身份验证。此行很可能已存在于您的 pg_hba.conf 文件中

# TYPE DATABASE USER ADDRESS METHOD OPTIONS
local all postgres peer

确保您的文件中存在此行或类似的行,尤其是在您更改许多其他身份验证方法时。

允许用于复制的连接

复制是一个特殊的过程,它将数据从一个数据库复制到另一个数据库,通常以频繁的方式进行。与其他类型的连接不同,复制连接不指定它们要连接的特定数据库。

数据库列中的 replication 关键字用于匹配这些复制连接。任何具有复制权限的用户都能够建立复制连接。

为了允许所有本地复制连接,以反映我们之前用于常规连接的值(Unix 套接字连接使用 peer,本地网络连接使用 md5),我们可以添加以下行

# TYPE DATABASE USER ADDRESS METHOD OPTIONS
local replication all peer
host replication all 127.0.0.1/32 md5
host replication all ::1/128 md5

要允许从其他位置进行复制,您可以添加其他地址。例如,要允许从本地 192.0.2.0/24 网络上的任何机器进行复制,您可以添加如下所示的行

# TYPE DATABASE USER ADDRESS METHOD OPTIONS
host replication all 192.0.2.0/24 md5

这将允许来自该网络内机器的任何复制连接使用 md5 加密密码进行身份验证。

允许从本地网络使用密码进行连接

上面,我们演示了如何为本地复制连接配置密码身份验证。这可以推广到允许任何本地网络连接的密码身份验证。

要允许来自本地 192.0.2.0/24 网络的任何连接进行 md5 密码身份验证,您可以添加如下所示的行

# TYPE DATABASE USER ADDRESS METHOD OPTIONS
host all all 192.0.2.0/24 md5

这将允许 192.0.2.0/24 网络内的所有主机通过网络使用 md5 加密密码向 PostgreSQL 进行身份验证。

允许使用 SSL 和密码进行远程连接

要允许来自可信网络外部的连接,您应始终通过安全加密(如 TLS/SSL)隧道连接。如果您需要允许这些连接,则应匹配 hostssl 连接类型。

例如,要允许来自可以连接到数据库服务器的任何位置的密码身份验证,但前提是使用 TLS/SSL,您可以在身份验证文件中添加如下所示的行

# TYPE DATABASE USER ADDRESS METHOD OPTIONS
hostssl all all all md5

这将允许任何使用 TLS/SSL 的外部连接使用 md5 加密密码进行身份验证。您可以通过指定更严格的地址来轻松限制访问。

如果您使用 hostssl 连接类型,则必须为 PostgreSQL 实例配置 SSL。您将必须生成或以其他方式获取 SSL 证书、SSL 密钥和 SSL 根证书,然后修改 postgresql.conf 配置文件,如 PostgreSQL 关于配置 SSL 的文档中所述。

允许使用 SSL 和 SSL 客户端证书进行远程连接

如果您已经强制外部连接使用 SSL,您可能需要考虑使用 SSL 客户端证书进行身份验证,而不是密码。这将允许客户端出示其客户端 SSL 证书。服务器检查证书是否有效并由受信任的证书颁发机构签名。如果是,它将根据提供的规则允许身份验证。

要设置 SSL 客户端身份验证,我们可以使用与之前使用的行类似的行

# TYPE DATABASE USER ADDRESS METHOD OPTIONS
hostssl all all all cert

使用此配置,服务器不会提示用户输入密码,而是需要有效的 SSL 证书。证书的公用名 (CN) 字段必须与正在请求的数据库用户匹配,否则需要使用 map 文件进行配置。

例如,对于 CN 为 katherine 的证书要向名为 kate 的 PostgreSQL 用户进行身份验证,您需要在 pg_hba.conf 文件中指定一个映射文件

# TYPE DATABASE USER ADDRESS METHOD OPTIONS
hostssl all all all cert map=my-map-name

之后,您需要编辑 pg_ident.conf 文件以显式地将这两个用户映射在一起

vim pg_ident.conf
# MAPNAME SYSTEM-USERNAME PG-USERNAME
my-map-name katherine kate

您可以在PostgreSQL 关于 TLS/SSL 客户端证书的文档中了解如何创建和配置客户端证书。

结论

在本指南中,我们从服务器端介绍了 PostgreSQL 身份验证。我们演示了如何修改 PostgreSQL 实例的配置以更改允许客户端进行身份验证的方式。在讨论了身份验证文件中可用的不同选项之后,我们介绍了如何使用我们之前学到的知识来实现一些常见的身份验证策略。

了解如何配置身份验证,并结合了解如何使用 PostgreSQL 客户端进行连接,使您能够授予合法客户端访问权限,同时防范不必要的连接。此配置是保护数据库实例安全和防止可能阻碍您操作的破坏性登录问题的重要组成部分。

关于作者
Justin Ellingwood

Justin Ellingwood

Justin 自 2013 年以来一直撰写关于数据库、Linux、基础设施和开发者工具的文章。他目前与妻子和两只兔子住在柏林。他通常不必以第三人称写作,这对所有相关方来说都是一种解脱。