分享到

引言

使用 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 进行安全保护的用户有意义。
  • hostnogssenchostnogssenc 类型匹配所有不使用 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 加密,当前实现将自动使用 scram-sha-256,即使指定了 md5
  • 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 主机。

上述某些方法仅适用于某些类型的连接或需要额外基础设施的情况下。对于大多数部署,rejectpeer 以及 scram-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 身份验证对 PostgreSQL 用户 susan 进行身份验证。

允许来自同一机器的网络连接使用密码

要使用密码对来自 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 关键字用于匹配这些复制连接。任何具有 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、基础设施和开发者工具的文章。他目前与妻子和两只兔子住在柏林。他通常不必用第三人称写作,这让所有相关方都感到欣慰。
© . All rights reserved.