ninenines / gun

HTTP/1.1, HTTP/2, Websocket client (and more) for Erlang/OTP.
ISC License
891 stars 232 forks source link

timeout to connect to ws.postman-echo.com:443 #326

Closed gdamjan closed 6 months ago

gdamjan commented 6 months ago
Erlang/OTP 26 [erts-14.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]

Eshell V14.2 (press Ctrl+G to abort, type help(). for help)
1> application:ensure_all_started(gun),
   {ok, ConnPid} = gun:open("ws.postman-echo.com", 443),
   {ok, Protocol} = gun:await_up(ConnPid).
** exception error: no match of right hand side value {error,timeout}

I've tried the patch at #324 but it didn't help

I've assumed they use TLSv1.3 since curl -v says:

curl -v https://ws.postman-echo.com
…
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
essen commented 6 months ago

Your snippet is missing a lot of configuration, you have to provide TLS options and/or certificates, Gun won't do it for you.

gdamjan commented 6 months ago

Your snippet is missing a lot of configuration, you have to provide TLS options and/or certificates, Gun won't do it for you.

ugh sorry, I was going by the guide here: https://ninenines.eu/docs/en/gun/2.0/guide/connect/#_opening_a_new_connection

what options do I need more? I can't find anything about certificates in either the guide or the manual.

ps. I get the same timeout with both example.net:443 and www.google.com:443

essen commented 6 months ago

You're using OTP-26 so the problem is likely that you haven't given the cacerts option. OTP-26 switched to {verify, verify_peer} by default so it expects a list of CA certs to do the verification. OTP-25+ has a new function to take system CA certs that you can use:

1> {ok, ConnPid} = gun:open("google.com", 443, #{tls_opts => [{cacerts, public_key:cacerts_get()}]}).
{ok,<0.130.0>}
2> gun:await_up(ConnPid).
{ok,http2}

Alternatively you can disable peer verification:

1> {ok, ConnPid} = gun:open("google.com", 443, #{tls_opts => [{verify, verify_none}]}).
{ok,<0.130.0>}
2> gun:await_up(ConnPid).
{ok,http2}

Gun does not currently set CA certs automatically so it no longer works by default on OTP-26+. When Gun will stop supporting versions below OTP-25 it will likely be changed to call public_key:cacerts_get/0 automatically if none are provided. Maybe for the next version.

essen commented 6 months ago

To add more context, the TLS configuration information can be found in https://www.erlang.org/doc/man/ssl.html - Gun just passes the configuration to OTP's ssl application.

gdamjan commented 6 months ago

Thanks #{tls_opts => [{cacerts, public_key:cacerts_get()}]}) works indeed. wasn't obvious that there's a strange interaction between OTP-26 and Gun 2.0.

essen commented 6 months ago

Two things can make debugging these issues more obvious (for future reference):

Shell got {'DOWN',#Ref<0.3552409767.4216324106.107274>,process,<0.123.0>,
                  {shutdown,{options,incompatible,
                                     [{verify,verify_peer},
                                      {cacerts,undefined}]}}}
{ok, ConnPid} = gun:open("ws.postman-echo.com", 443, #{trace => true}).

(<0.139.0>) returned from gun:normal_tls_handshake/4 -> {error,
                                                         {options,
                                                          incompatible,
                                                          [{verify,
                                                            verify_peer},
                                                           {cacerts,
                                                            undefined}]},

Cheers.