Tło
Miałem ten sam problem z połączeniem Phoenix/Ecto/Postgrex z serwerem Azure Database for PostgreSQL. Nawet po ustawieniu ssl: true
w mojej konfiguracji Repo nadal nie byłem w stanie połączyć się z bazą danych za pomocą Postgrex, mimo że łączyłem się za pomocą psql "postgresql://...?sslmode=require" -U ...
na tej samej maszynie się udało. Błąd zwrócony z ssl: true
było:
[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
...
Po przekopaniu się przez kod źródłowy odkryłem, że nieudane wywołanie było w rzeczywistości ssl.connect/3
wywołanie z modułu 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
Trochę podsłuchując z Wireshark, mogłem to zobaczyć po pomyślnym połączeniu z psql
, widziałem pakiety z TLSV1.2
jako protokół, ale gdy postgrex łączył się z ssl: true
Widziałem pakiety z SSL
jako protokół przed niepowodzeniem połączenia.
Patrząc na dokumentację dotyczącą opcji Ecto.Adapters.Postgres
, zobaczysz, że istnieje ssl_opts
opcja konfiguracji, która kończy się przekazaniem do :ssl.connect/3
w którym możesz ustawić versions
aby zastąpić wersje TLS używane do połączenia.
Rozwiązanie
Udało mi się połączyć z bazą danych, dodając następujące elementy do mojej konfiguracji repozytorium:
ssl_opts: [
versions: [:"tlsv1.2"]
]
Moja pełna konfiguracja wyglądała tak:
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"]
]
Nie jestem do końca pewien, dlaczego wersja TLS musi być wyraźnie ustawiona, być może ktoś z większą wiedzą w tej dziedzinie może rzucić na to trochę światła.