Latar Belakang
Saya mengalami masalah yang sama saat menghubungkan Phoenix/Ecto/Postgrex ke Azure Database untuk server PostgreSQL. Bahkan setelah menyetel ssl: true
dalam konfigurasi Repo saya, saya masih tidak dapat terhubung ke database dengan Postgrex meskipun terhubung menggunakan psql "postgresql://...?sslmode=require" -U ...
pada mesin yang sama berhasil. Kesalahan dikembalikan dengan ssl: true
adalah:
[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
...
Setelah menggali melalui kode sumber, saya menemukan bahwa panggilan yang gagal sebenarnya adalah ssl.connect/3
panggilan dari modul 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
Melakukan beberapa pengintaian dengan Wireshark, saya dapat melihatnya ketika berhasil terhubung dengan psql
, saya bisa melihat paket dengan TLSV1.2
sebagai protokol, tetapi ketika postgrex terhubung dengan ssl: true
Saya melihat paket dengan SSL
sebagai protokol sebelum gagal terhubung.
Melihat dokumen opsi Ecto.Adapters.Postgres
, Anda akan melihat ada ssl_opts
opsi konfigurasi yang akhirnya diteruskan ke :ssl.connect/3
di mana Anda dapat mengatur versions
untuk mengganti versi TLS yang digunakan untuk menghubungkan.
Solusi
Saya dapat terhubung ke database dengan menambahkan yang berikut ini ke konfigurasi Repo saya:
ssl_opts: [
versions: [:"tlsv1.2"]
]
Konfigurasi lengkap saya akhirnya terlihat seperti ini:
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"]
]
Saya tidak begitu yakin mengapa versi TLS perlu disetel secara eksplisit, mungkin seseorang yang lebih ahli di bidang ini dapat menjelaskannya.