Фон
Изпитвах същия проблем при свързването на Phoenix/Ecto/Postgrex към Azure Database за PostgreSQL сървър. Дори след настройка на ssl: true
в моята Repo конфигурация все още не успях да се свържа с базата данни с Postgrex, въпреки че се свързвах с psql "postgresql://...?sslmode=require" -U ...
на същата машина успя. Грешката се върна с ssl: true
беше:
[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
извикване от ssl модула Erlang
:
# 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
, ще видите, че има ssl_opts
конфигурационна опция, която в крайна сметка се предава на :ssl.connect/3
в който можете да задавате versions
за да замените версията(ите) на TLS, използвани за свързване.
Решение
Успях да се свържа с базата данни, като добавих следното към моята Repo конфигурация:
ssl_opts: [
versions: [:"tlsv1.2"]
]
Пълната ми конфигурация в крайна сметка изглеждаше така:
config :myapp, Myapp.Repo,
adapter: Ecto.Adapters.Postgres,
username: "[email protected]",
password: "...",
database: "myapp_dev",
port: 5432,
hostname: "dev-db.postgres.database.azure.com",
pool_size: 10,
ssl: true,
ssl_opts: [
versions: [:"tlsv1.2"]
]
Не съм много сигурен защо TLS версията трябва да бъде зададена изрично, може би някой с повече опит в тази област може да хвърли малко светлина върху това.