如何通过 SSL 从 Phoenix Web App 连接到 PostgreSQL?

2024-05-10

When trying to run Elixir (Phoenix) Web Application using PostgreSQL Database hosted 3rd party "Database-as-a-Service" (Azure Database for PostgreSQL https://azure.microsoft.com/en-us/pricing/details/postgresql).

我们尝试启动应用程序mix phoenix.server我们看到以下错误:

[info] Running Pxblog.Endpoint with Cowboy using http://localhost:4000
[error] GenServer #PID<0.247.0> terminating
** (FunctionClauseError) no function clause matching in Postgrex.Messages.decode_fields/1
    (postgrex) lib/postgrex/messages.ex:339: Postgrex.Messages.decode_fields("")
    (postgrex) lib/postgrex/messages.ex:344: Postgrex.Messages.decode_fields/1
    (postgrex) lib/postgrex/messages.ex:344: Postgrex.Messages.decode_fields/1
    (postgrex) lib/postgrex/messages.ex:131: Postgrex.Messages.parse/3
    (postgrex) lib/postgrex/protocol.ex:1842: Postgrex.Protocol.msg_decode/1
    (postgrex) lib/postgrex/protocol.ex:1816: Postgrex.Protocol.msg_recv/3
    (postgrex) lib/postgrex/protocol.ex:560: Postgrex.Protocol.auth_recv/3
    (postgrex) lib/postgrex/protocol.ex:475: Postgrex.Protocol.handshake/2
    (db_connection) lib/db_connection/connection.ex:134: DBConnection.Connection.connect/2
    (connection) lib/connection.ex:622: Connection.enter_connect/5
    (stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
Last message: nil
State: Postgrex.Protocol

见解:在 Azure DB 上启用了“强制 SSL”...

通过调查,我们意识到错误的原因是 Azure PostgreSQL 服务Enforce SSL Connection set to Enabled (by default):

我们认为“强制执行 SSL”可以Enabled is good for Security,但我们无法让它与 Phoenix 一起工作......

(暂时的) 解决方案:Disable“强制实施 SSL”

So, we have (temporarily) disabled SSL for now: azure-psql-ssl-disable

但我们会更喜欢 a "永恒的”这个问题的解决方案。

首选解决方案:连接 PostgreSQL 时使用 SSL

如果有人可以澄清(或向我们指出) how通过 SSL 从 Phoenix/Ecto 连接到 PostgreSQL
我们将非常感激! :-)

应用程序(Phoenix)服务器是否需要配置 SSL 证书才能从应用程序服务器连接到数据库服务器...?
e.g: http://www.phoenixframework.org/docs/configuration-for-ssl http://www.phoenixframework.org/docs/configuration-for-ssl ?

Microsoft 有以下帮助指南:https://learn.microsoft.com/en-us/azure/postgresql/concepts-ssl-connection-security https://learn.microsoft.com/en-us/azure/postgresql/concepts-ssl-connection-security It seems建议我们在应用服务器上需要 OpenSSL ...任何人都可以confirm?


背景

我在将 Phoenix/Ecto/Postgrex 连接到 Azure Database for PostgreSQL 服务器时遇到了同样的问题。即使设置后ssl: true在我的 Repo 配置中,即使使用连接,我仍然无法使用 Postgrex 连接到数据库psql "postgresql://...?sslmode=require" -U ...在同一台机器上成功了。返回的错误为ssl: true was:

[error] Postgrex.Protocol (#PID<0.1853.0>) failed to connect: **(DBConnection.ConnectionError) ssl connect: closed

** (DBConnection.ConnectionError) connection not available because of disconnection
    (db_connection) lib/db_connection.ex:926: DBConnection.checkout/2
    ...

在深入研究源代码后,我发现失败的调用实际上是ssl.connect/3电话来自Erlang ssl 模块 http://erlang.org/doc/man/ssl.html:

# deps/postgrex/lib/postgrex/protocol.ex:535

defp ssl_connect(%{sock: {:gen_tcp, sock}, timeout: timeout} = s, status) do
  case :ssl.connect(sock, status.opts[:ssl_opts] || [], timeout) do
    {:ok, ssl_sock} ->
      startup(%{s | sock: {:ssl, ssl_sock}}, status)
    {:error, reason} ->
      disconnect(s, :ssl, "connect", reason)
  end
end

使用 Wireshark 进行一些窥探,我能够在成功连接时看到psql,我可以看到数据包TLSV1.2作为协议,但是当 postgrex 连接时ssl: true我看到数据包SSL作为连接失败之前的协议。

看着Ecto.Adapters.Postgres 选项文档 https://hexdocs.pm/ecto/Ecto.Adapters.Postgres.html#module-options,你会看到有一个ssl_opts配置选项最终被传递给:ssl.connect/3您可以在其中设置versions覆盖用于连接的 TLS 版本。

Solution

我可以通过将以下内容添加到我的 Repo 配置来连接到数据库:

ssl_opts: [
  versions: [:"tlsv1.2"]
]

我的完整配置最终如下所示:

config :myapp, Myapp.Repo,
  adapter: Ecto.Adapters.Postgres,
  username: "myapp@dev-db",
  password: "...",
  database: "myapp_dev",
  port: 5432,
  hostname: "dev-db.postgres.database.azure.com",
  pool_size: 10,
  ssl: true,
  ssl_opts: [
    versions: [:"tlsv1.2"]
  ]

我不太确定为什么需要明确设置 TLS 版本,也许在这方面具有更多专业知识的人可以对此有所了解。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何通过 SSL 从 Phoenix Web App 连接到 PostgreSQL? 的相关文章

随机推荐