使用 SSH 隧道的 PostgreSQL/psycopg2 密码验证

Posted

技术标签:

【中文标题】使用 SSH 隧道的 PostgreSQL/psycopg2 密码验证【英文标题】:PostgreSQL/psycopg2 Password Authentication using SSH Tunneling 【发布时间】:2020-05-31 19:27:19 【问题描述】:

我正在尝试通过 ssh 隧道连接到 PostgreSQL 数据库。它设置为侦听端口 3333 并转发到装有数据库的机器上的端口 5432。我可以通过隧道使用psql 命令和密码验证进行连接,但由于某种原因,当我尝试通过隧道使用psycopg2 进行连接时,我收到错误FATAL: password authentication failed for user database_user。我尝试在用户名和密码周围加上引号,但无济于事。

成功的psql 命令:

psql -h localhost -p 3333 -U database_name database_user 
#This command brings up password prompt

pscyopg2 命令失败:

psycopg2.connect("dbname='database_name' user='database_user' host='localhost' password='database_password' port=3333")

输出:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/database_user/.local/share/virtualenvs/project-QNhT-Vzg/lib/python3.7/site-packages/psycopg2/__init__.py", line 126, in connect
    conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
psycopg2.OperationalError: FATAL:  password authentication failed for user "database_user"
FATAL:  password authentication failed for user "database_user"

这是我pg_hba.conf的一部分供参考:

# Database administrative login by Unix domain socket
local   all             postgres                                peer

# TYPE  DATABASE        USER            ADDRESS                 METHOD

# "local" is for Unix domain socket connections only
local   all             all                                     peer
# IPv4 local connections:
host    all             all             127.0.0.1/32            md5
# IPv6 local connections:
host    all             all             ::1/128                 md5
# Allow replication connections from localhost, by a user with the
# replication privilege.
local   replication     all                                     peer
host    replication     all             127.0.0.1/32            md5
host    replication     all             ::1/128                 md5

【问题讨论】:

这不足以找出您的问题。有防火墙吗? postgres 是否在监听接口?您能否解决这些问题并添加特定的 Python 代码和错误跟踪,因为它肯定包含有关问题所在的信息。 看来您的密码不是您想的那样。您可以访问 postgres,并且 ACL (pg_hba) 是正确的。错误很典型:密码不匹配。你确定没有错别字?你设置了这个密码吗?当您尝试使用 psql 时,您是处于本地模式还是主机模式? 不知何故它最终通过使用单引号中的密码创建一个环境变量来工作。如果您回答有关检查密码的问题,我会将其标记为已接受的答案。谢谢你的帮助! @jlandercy 您好 Gunnar,添加了包含更多详细信息和检查清单的答案。干杯 【参考方案1】:

在调试连接问题时,总是值得记住在到达服务之前我们必须经过哪些层。当你连接 PostgreSQL 服务时,至少会有三层:

网络:防火墙、NAT、端口转发 PostgreSQL ACL PostgreSQL 登录

了解导致问题的层很重要,PostgreSQL 客户端(在您的场景中包含在 psycopg2 中)错误将通过发出临时错误消息帮助您解决此问题:

网络问题一般会出现一个典型的:Is the server running locally and accepting connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?表示你根本没有成功连接PostgreSQL服务,问题在服务之前; ACL 问题通常会引发典型的:No pg_hba.conf entry for host &lt;hostname&gt;, user &lt;username&gt;, database &lt;database&gt;,这意味着您确实连接了 PostgreSQL 服务,但该连接在 ACL 中未被引用为有效; 登录问题通常会引发您遇到的错误:password authentication failed for user "&lt;user&gt;",这意味着您确实连接了 PostgreSQL 服务并且连接符合 ACL 条目但身份验证失败。

在后面的场景中,重要的是要知道触发了哪个条目,因为它定义了身份验证模式。在您的情况下,它是一个 md5 条目(因为在 peer 模式下没有密码,并且您的 SSH 隧道应该映射本地主机,因此您被视为 host 而不是 local 对于 postgreSQL 的观点):

host    all             all             127.0.0.1/32            md5

显然您的密码不是您所期望的。要解决此问题,请确保:

你已经给postgreSQL用户设置了密码,并检查了LOGIN权限(不是unix/SSH用户,有不同的概念); 您在psycopg2 连接中使用相同的密码,那么您必须能够连接;

阅读您的评论,您的密码中似乎也有 ' 引号。所以你的连接密码可能是:

psycopg2.connect("dbname='database_name' user='database_user' host='localhost' password="'database_password'" port=3333")

或者如果需要引号,它可能表明您使用了一些需要转义的特殊字符。您还可以尝试使用更简单的密码进行调试,然后使用更强的密码。

【讨论】:

以上是关于使用 SSH 隧道的 PostgreSQL/psycopg2 密码验证的主要内容,如果未能解决你的问题,请参考以下文章

使用 PgAdmin 4 设置 SSH 隧道

如何检查是不是正在使用 ssh 隧道?

PyCharm SSH 隧道通过本地 ssh 配置 (~/.ssh/config)

如何使用 Python 和 Paramiko 创建 SSH 隧道?

如何使用 python 打开 SSH 隧道?

虚拟环境实现SSH隧道