zkessin

zkessin

HTTPS handshake error: Fatal - Handshake Failure

I am trying to hit an HTTPS endpoint and when I call it HTTPoison returns this error

 {:error, %HTTPoison.Error{id: nil, reason: {:tls_alert, {:handshake_failure, 'TLS client: In state hello received SERVER ALERT: Fatal - Handshake Failure\n'}}}}

I am passing these options to the get command

   http_options = [ssl: [versions: [:"tlsv1.2"], verify: :verify_none]]
    {:ok, results} = get(url, [], http_options)

I have been banging my head on this for a few days now and my google-fu has failed me, any suggestions on how to fix this?

Most Liked

rjk

rjk

just to add as a helper to debug these calls: :hackney_trace.enable(:max, :io) logs your requests to STDOUT on the REPL/console (it shows the enabled cipers for example).

voltone

voltone

Ah, of course, I had forgotten all about the removal of RSA key exchange already. One would expect a site such as this to support (EC)DHE: I mean, it is 2021…

Anyway, keep in mind that :ssl.cipher_suites/1,2 is deprecated. The ‘official’ way to select custom ciphers would be something like:

defaults = :ssl.cipher_suites(:default, :"tlsv1.2")
rsa_kx =
  :ssl.cipher_suites(:all, :"tlsv1.2")
  |> :ssl.filter_cipher_suites(
    key_exchange: &(&1 == :rsa),
    cipher: &(&1 in [:aes_128_cbc, :aes_128_gcm, :aes_256_cbc, :aes_256_gcm]),
  )
HTTPoison.get!("https://api.etrade.com", [], ssl: [ciphers: defaults ++ rsa_kx])

Also, and more importantly, as @Exadra37 pointed out, passing custom ssl options to Hackney/HTTPoison will override its secure defaults, including verify: :verify_peer and the CA trust store. So actually, for a secure connection you’d have to call:

HTTPoison.get!("https://api.etrade.com", [], ssl: [
  ciphers: defaults ++ rsa_kx,
  verify: :verify_peer,
  cacertfile: :certifi.cacertfile(),
  depth: 3,
  customize_hostname_check: [
    match_fun: :public_key.pkix_verify_hostname_match_fun(:https)
  ]
])
voltone

voltone

The server aborts the handshake, so it looks like it doesn’t like something the client sends. Unfortunately the server does not (cannot) indicate exactly what it didn’t like through the TLS alert mechanism. It might record more details in its local log, but I’m guessing you don’t have access to that log.

I would trace a successful handshake (using curl or openssl) and an unsuccessful one with Wireshark, and compare. You can also trace the handshake by adding log_level: :debug to the ssl options in the client, but that might be hard to compare with the output of other clients.

rjk

rjk

HTTPoison.get!("https://api.etrade.com", [], [ssl: [ciphers: :ssl.cipher_suites() ++ [{:rsa, :aes_256_cbc, :sha256}]], log_level: :debug])

seems to work here! See if that works for you.

rjk

rjk

It seems they’ve documented it here: Erlang -- ssl

  • For security reasons RSA key exchange cipher suites are no longer supported by default, but can be configured. (OTP 21)

Glad to see your code is working again!

Where Next?

Popular in Questions Top

sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
_russellb
I want to try my hand at web scraping. What tools/libraries do I need to use. I’m hoping to turn this into something professional so don’...
New
Werner
Hi, I’m using Ubuntu 18.04 and after updating to OTP-24.0 yesterday i have this warning when I run “mix local.hex”: 14:57:30.512 [warn] ...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
qwerescape
Is there a way to get the call stack or stack trace at any point in the code? Not from exceptions, but an expression that returns how the...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? https://hexdocs.pm/ecto/Ecto.Repo.h...
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
beno
I will often find my self writing things similar to: case some_value do nil -> something() "" -> something() _ -> someth...
New
Codball
Mix format works fine if run from the cmd. I’ve followed this to facilitate the implementation into VSC which involves downloading an ext...
New
Mooodi
Given a string, how can I get access to its character by index? Enum.at("my_string", 2) doesn't work. Or rather, not char, but a substr...
New

Other popular topics Top

JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1140 51847 244
New
sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
yawaramin
In the Dialyzer docs ( http://erlang.org/doc/man/dialyzer.html#requesting-or-suppressing-warnings-in-source-files ), there is a way to tu...
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
Jim
As a follow up to my earlier question: I have the code compiling and running but not getting a successful login from the rest server. ...
New
polypush135
As many of you may have realized by now (sorry for all the posts here) I’ve been working on a db problem where I’m trying to aggregate a ...
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New

We're in Beta

About us Mission Statement