Sfondo
Ho riscontrato lo stesso problema durante la connessione di Phoenix/Ecto/Postgrex al database di Azure per il server PostgreSQL. Anche dopo aver impostato ssl: true
nella mia configurazione Repo, non ero ancora in grado di connettermi al database con Postgrex anche se mi connettevo usando psql "postgresql://...?sslmode=require" -U ...
sulla stessa macchina riuscito. L'errore restituito con ssl: true
era:
[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
...
Dopo aver esaminato il codice sorgente, ho scoperto che la chiamata non riuscita era in realtà ssl.connect/3
chiamata da il modulo Erlang ssl
:
# 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
Facendo un po' di ficcanaso con Wireshark, sono stato in grado di vederlo quando mi sono connesso con successo con psql
, ho potuto vedere i pacchetti con TLSV1.2
come protocollo, ma quando Postgrex si connetteva con ssl: true
Stavo vedendo pacchetti con SSL
come protocollo prima di non riuscire a connettersi.
Osservando i documenti sulle opzioni Ecto.Adapters.Postgres
, vedrai che c'è un ssl_opts
opzione di configurazione che finisce per essere passata a :ssl.connect/3
in cui puoi impostare versions
per sovrascrivere le versioni TLS utilizzate per la connessione.
Soluzione
Sono stato in grado di connettermi al database aggiungendo quanto segue alla mia configurazione Repo:
ssl_opts: [
versions: [:"tlsv1.2"]
]
La mia configurazione completa ha finito per assomigliare a questa:
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"]
]
Non sono molto sicuro del motivo per cui la versione TLS debba essere impostata in modo esplicito, forse qualcuno con più esperienza in questo settore può far luce su questo.