twingly / twingly-http

Robust HTTP client
https://rubygems.org/gems/twingly-http
MIT License
0 stars 1 forks source link

SSLError: SSL_read: unexpected eof while reading #28

Closed Pontus4 closed 11 months ago

Pontus4 commented 12 months ago

Happened to notice that the gem returns an SSL related error when trying to send a GET request to https://www.fokis.se (haven't seen this error for any other sites).

[2] pry(main)> require "twingly/http"
=> true
[3] pry(main)> client = Twingly::HTTP::Client.new(logger: Logger.new(IO::NULL), base_user_agent: "")
=> #<Twingly::HTTP::Client:0x00000001059c9b58>
[4] pry(main)> client.get("https://www.fokis.se")
Twingly::HTTP::ConnectionError: Twingly::HTTP::ConnectionError
from /Users/X/.gem/ruby/3.2.2/gems/twingly-http-0.4.0/lib/twingly/http.rb:102:in `rescue in http_response_for'
Caused by Faraday::SSLError: SSL_read: unexpected eof while reading
from /Users/X/.rubies/ruby-3.2.2/lib/ruby/3.2.0/openssl/buffering.rb:214:in `sysread_nonblock'
Caused by OpenSSL::SSL::SSLError: SSL_read: unexpected eof while reading
from /Users/X/.rubies/ruby-3.2.2/lib/ruby/3.2.0/openssl/buffering.rb:214:in `sysread_nonblock'

While troubleshooting, I noticed that the request works when this line is removed:

https://github.com/twingly/twingly-http/blob/5aec5c0379bfb99f37adff3857644e2a9fcde7e9/lib/twingly/http.rb#L203

I'm not sure why the user agent would cause the error, but it will hopefully get clearer after some further investigation.

dentarg commented 12 months ago

Same problem when using curl with the default user-agent

$ curl -s -o /dev/null -v --http1.1 --user-agent "(Release/unknown_heroku_release_version; Commit/unknown_heroku_slug_commit)" https://www.fokis.se
*   Trying 35.214.35.110:443...
* Connected to www.fokis.se (35.214.35.110) port 443
* ALPN: curl offers http/1.1
} [5 bytes data]
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
} [512 bytes data]
* TLSv1.3 (IN), TLS handshake, Server hello (2):
{ [88 bytes data]
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
} [1 bytes data]
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
} [512 bytes data]
* TLSv1.3 (IN), TLS handshake, Server hello (2):
{ [187 bytes data]
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
{ [25 bytes data]
* TLSv1.3 (IN), TLS handshake, Certificate (11):
{ [3971 bytes data]
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
{ [264 bytes data]
* TLSv1.3 (IN), TLS handshake, Finished (20):
{ [52 bytes data]
* TLSv1.3 (OUT), TLS handshake, Finished (20):
} [52 bytes data]
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN: server accepted http/1.1
* Server certificate:
*  subject: CN=fokis.se
*  start date: Oct 16 00:47:36 2023 GMT
*  expire date: Jan 14 00:47:35 2024 GMT
*  subjectAltName: host "www.fokis.se" matched cert's "www.fokis.se"
*  issuer: C=US; O=Let's Encrypt; CN=R3
*  SSL certificate verify ok.
* using HTTP/1.1
} [5 bytes data]
> GET / HTTP/1.1
> Host: www.fokis.se
> User-Agent: (Release/unknown_heroku_release_version; Commit/unknown_heroku_slug_commit)
> Accept: */*
>
{ [5 bytes data]
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
{ [281 bytes data]
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
{ [281 bytes data]
* old SSL session ID is stale, removing
* Empty reply from server
* Closing connection
} [5 bytes data]
* TLSv1.3 (OUT), TLS alert, close notify (256):
} [2 bytes data]

curl -s -o /dev/null -v --http1.1 --user-agent "foo" https://www.fokis.se works for example

Pontus4 commented 12 months ago

Interesting! Just removing the opening parenthesis from the default user agent works too.

curl -s -o /dev/null -v --http1.1 --user-agent "Release/unknown_heroku_release_version; Commit/unknown_heroku_slug_commit)" https://www.fokis.se

Maybe the site has some special user agent blocking rules set... 🤔

Pontus4 commented 11 months ago

I've tried to request the site with ( as user agent with NET::HTTP and httparty too, and they both return OpenSSL::SSL::SSLError: SSL_read: unexpected eof while reading. I've also tried the SSL versions TLSv1, TLSv1.1 and TLSv1.2 with the same outcome.

The TLS handshake looks complete in Wireshark, too:

image

Since the behaviour is the same for all the tested HTTP clients, I don't think we need to take action here. This case is hopefully pretty uncommon.