New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unknown SSL protocol error in connection to any site through HTTPS #2299

Closed
Qclanton opened this Issue Feb 9, 2018 · 21 comments

Comments

Projects
None yet
5 participants
@Qclanton

Qclanton commented Feb 9, 2018

I did this

curl -v https://packagist.org
curl -v --insecure https://packagist.org

I also tried wget -q -S -O - https://packagist.org and it works perfectly without any errors.

I expected the following

Response from server.

I received the following

* Rebuilt URL to: https://packagist.org/
*   Trying 144.217.203.53...
* TCP_NODELAY set
* Connected to packagist.org (144.217.203.53) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* Unknown SSL protocol error in connection to packagist.org:443
* Curl_http_done: called premature == 1
* stopped the pause stream!
* Closing connection 0
curl: (35) Unknown SSL protocol error in connection to packagist.org:443

curl/libcurl version

curl 7.52.1 (x86_64-pc-linux-gnu) libcurl/7.52.1 OpenSSL/1.0.2l zlib/1.2.8 libidn2/0.16 libpsl/0.17.0 (+libidn2/0.16) libssh2/1.7.0 nghttp2/1.18.1 librtmp/2.3
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp scp sftp smb smbs smtp smtps telnet tftp
Features: AsynchDNS IDN IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz TLS-SRP HTTP2 UnixSockets HTTPS-proxy PSL

operating system

Distributor ID: Debian
Description:    Debian GNU/Linux 9.3 (stretch)
Release:        9.3
Codename:       stretch

@jay jay added the SSL/TLS label Feb 10, 2018

@jay

This comment has been minimized.

Member

jay commented Feb 10, 2018

I can't reproduce that here in Ubuntu. I also tried in Windows using libcurl and each of mbedTLS, OpenSSL, WinSSL and wolfSSL. Is it possible something is intercepting the connection? Can you still reproduce? Do other https requests work?

curl 7.52.1 (x86_64-pc-linux-gnu) libcurl/7.52.1 OpenSSL/1.0.2j zlib/1.2.8 nghttp2/1.18.1 librtmp/2.3
curl 7.54.0 (x86_64-pc-linux-gnu) libcurl/7.54.0 OpenSSL/1.0.2l zlib/1.2.8 nghttp2/1.23.1 librtmp/2.3
curl 7.58.0 (x86_64-pc-linux-gnu) libcurl/7.58.0 OpenSSL/1.0.2n zlib/1.2.8 nghttp2/1.30.0 librtmp/2.3

@Qclanton

This comment has been minimized.

Qclanton commented Feb 10, 2018

Is it possible something is intercepting the connection?

I don't know how to check it. If you have any suggestions, please share it. This machine connected directly to provider coaxial modem and problem is still there. Actually problem is not new, I was witnessing it at least few months but I've decided to do something with it :)
I also have a couple of other machines (with Windows 10) it the same network and I cannot reproduce problem from these machines.

Results of fresh tests:
Debian 9 machine (with problems):

curl https://google.com -v --cacert /home/qcl/curl-ca-bundle.crt
* Rebuilt URL to: https://google.com/
*   Trying 172.217.2.174...
* TCP_NODELAY set
* Connected to google.com (172.217.2.174) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /home/qcl/curl-ca-bundle.crt
  CApath: /etc/ssl/certs
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* Unknown SSL protocol error in connection to google.com:443
* Curl_http_done: called premature == 1
* stopped the pause stream!
* Closing connection 0
curl: (35) Unknown SSL protocol error in connection to google.com:443

Windows 10 machine (no problems):

curl https://google.com -v --cacert C:\curl\curl-ca-bundle.crt
* Rebuilt URL to: https://google.com/
*   Trying 2607:f8b0:400b:808::200e...
* TCP_NODELAY set
* Connected to google.com (2607:f8b0:400b:808::200e) port 443 (#0)
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: C:\curl\curl-ca-bundle.crt
  CApath: none
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-ECDSA-AES128-GCM-SHA256
* ALPN, server accepted to use http/1.1
* Server certificate:
*  subject: C=US; ST=California; L=Mountain View; O=Google Inc; CN=*.google.com
*  start date: Jan 23 13:36:00 2018 GMT
*  expire date: Apr 17 13:36:00 2018 GMT
*  subjectAltName: host "google.com" matched cert's "google.com"
*  issuer: C=US; O=Google Inc; CN=Google Internet Authority G2
*  SSL certificate verify ok.
> GET / HTTP/1.1
> Host: google.com
> User-Agent: curl/7.58.0
> Accept: */*
>
< HTTP/1.1 302 Found
< Cache-Control: private
< Content-Type: text/html; charset=UTF-8
< Referrer-Policy: no-referrer
< Location: https://www.google.ca/?gfe_rd=cr&dcr=0&ei=T7N-WrKGF4aR8QeJ7oioDA
< Content-Length: 269
< Date: Sat, 10 Feb 2018 08:54:39 GMT
< Alt-Svc: hq=":443"; ma=2592000; quic=51303431; quic=51303339; quic=51303338; quic=51303337; quic=51303335,quic=":443"; ma=2592000; v="41,39,38,37,35"
<
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>302 Moved</TITLE></HEAD><BODY>
<H1>302 Moved</H1>
The document has moved
<A HREF="https://www.google.ca/?gfe_rd=cr&amp;dcr=0&amp;ei=T7N-WrKGF4aR8QeJ7oioDA">here</A>.
</BODY></HTML>
* Connection #0 to host google.com left intact

Do other https requests work?

No. No one HTTPS request works.
If you need any additional information, please tell me. I don't know which information may be helpful in this case.

@jay

This comment has been minimized.

Member

jay commented Feb 10, 2018

#1681 is another report with the same curl on stretch, but that only affected a select host.

On the affected computer use wireshark and set capture filter host test.com and then run curl https://test.com. Check to make sure the capture only contains the attempt to connect to test.com. Stop the capture, save it, .zip it [1] and then upload it here.

[1]: GitHub only allows certain file types like zip. Also, before zipping it you may want to remove possibly sensitive information from the packet capture such as IP/MAC by using TraceWrangler, but disable remove unknown layers.

@mrsmallyi

This comment has been minimized.

mrsmallyi commented Feb 11, 2018

@Qclanton

This comment has been minimized.

Qclanton commented Feb 11, 2018

@mrsmallyi, thank you for suggestion but this solution does not help in my case, errors are the same.

@jay, I was wrong when I said "No one HTTPS request work". Requests to https://test.com suddenly work. However requests to https://google.com and https://packagist.org still lead to error.
I've captured three dumps: one of them contains successful request to test.com, another one contains failed request to packagist.org and third one contains successful request to packagist.org using wget.

Dumps: dump-curl-test-20180211.zip

Logs of requests:
Failed request (https://packagist.org using curl):

curl https://packagist.org -v
* Rebuilt URL to: https://packagist.org/
*   Trying 144.217.203.53...
* TCP_NODELAY set
* Connected to packagist.org (144.217.203.53) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* Unknown SSL protocol error in connection to packagist.org:443
* Curl_http_done: called premature == 1
* stopped the pause stream!
* Closing connection 0
curl: (35) Unknown SSL protocol error in connection to packagist.org:443

Successful request (https://packagist.org using wget):

wget -S -O - https://packagist.org
--2018-02-11 05:05:01--  https://packagist.org/
Resolving packagist.org (packagist.org)... 144.217.203.53, 2607:5300:60:7113::3
Connecting to packagist.org (packagist.org)|144.217.203.53|:443... connected.
HTTP request sent, awaiting response...
  HTTP/1.1 200 OK
  Server: nginx
  Date: Sun, 11 Feb 2018 10:05:01 GMT
  Content-Type: text/html; charset=UTF-8
  Transfer-Encoding: chunked
  Connection: keep-alive
  Vary: Accept-Encoding
  Vary: Accept-Encoding
  Set-Cookie: packagist=08pqb21q7i8ev1q6c1ks6auvv3; expires=Sun, 11-Feb-2018 11:05:01 GMT; Max-Age=3600; path=/; secure; HttpOnly
  Cache-Control: private, must-revalidate
  Strict-Transport-Security: max-age=31104000
  pragma: no-cache
  expires: -1
  X-Frame-Options: DENY
  Content-Security-Policy: default-src 'self'; block-all-mixed-content; connect-src 'self' *.algolia.net *.algolianet.com; font-src 'self' https://fonts.gstatic.com/; img-src 'self' https://www.gravatar.com/ https://camo.githubusercontent.com/ https://ssl.google-analytics.com/ http://www.google-analytics.com/; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.jsdelivr.net/ https://ssl.google-analytics.com/; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net/ https://fonts.googleapis.com/
  X-Content-Security-Policy: default-src 'self'; block-all-mixed-content; connect-src 'self' *.algolia.net *.algolianet.com; font-src 'self' https://fonts.gstatic.com/; img-src 'self' https://www.gravatar.com/ https://camo.githubusercontent.com/ https://ssl.google-analytics.com/ http://www.google-analytics.com/; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.jsdelivr.net/ https://ssl.google-analytics.com/; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net/ https://fonts.googleapis.com/
  X-Xss-Protection: 1; mode=block
  Referrer-Policy: strict-origin-when-cross-origin
  X-Content-Type-Options: nosniff
Length: unspecified [text/html]
Saving to: ‘STDOUT’

-                                                      [<=>                                                                                                             ]       0  --.-KB/s               <!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />

        <title>Packagist</title>
        <meta name="description" content="The PHP Package Repository" />
        <meta name="author" content="Jordi Boggiano" />
 ...

Successful request (https://test.com using curl)

curl https://test.com -v
* Rebuilt URL to: https://test.com/
*   Trying 69.172.200.235...
* TCP_NODELAY set
* Connected to test.com (69.172.200.235) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server accepted to use http/1.1
* Server certificate:
*  subject: OU=Domain Control Validated; OU=nsProtect Secure Xpress; CN=www.test.com
*  start date: Jan 15 00:00:00 2017 GMT
*  expire date: Jan 24 23:59:59 2020 GMT
*  subjectAltName: host "test.com" matched cert's "test.com"
*  issuer: C=US; ST=VA; L=Herndon; O=Network Solutions L.L.C.; CN=Network Solutions DV Server CA 2
*  SSL certificate verify ok.
> GET / HTTP/1.1
> Host: test.com
> User-Agent: curl/7.52.1
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Server: nginx/1.13.4
< Date: Sun, 11 Feb 2018 09:30:04 GMT
< Content-Type: text/html
< Content-Length: 185
< Connection: keep-alive
< Keep-Alive: timeout=20
< Location: https://www.test.com/
< X-DIS-Request-ID: bdf804ffc0cd5ff24958ca932b1457ae
<
<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.13.4</center>
</body>
</html>
* Curl_http_done: called premature == 0
* Connection #0 to host test.com left intact
@jay

This comment has been minimized.

Member

jay commented Feb 11, 2018

The ClientHello is essentially the same for both the good and the bad connection. For bad conn to packagist.com there is no reply received to the ClientHello, despite several retransmissions over the next minute. Exactly 1 minute after the ClientHello the server initiates a close FIN which is what packagist would do without receiving one. Also if you look at the TSecr (timestamp echo reply) the number is from before the ClientHello was sent, meaning it has not received the ClientHello or the retransmissions, since if it did it could send any one of those as the echoreply.

I don't know why it's happening but I doubt it has to do with curl. It's possible something curl does may contribute, for example the ClientHello may be seen as too big and rejected by some middleman? Are you in China and maybe some of these hosts are blocked? That doesn't explain why wget isn't doing that or its ClientHello is otherwise different and can pass through. Try making the ClientHello smaller by only sending a single cipher, for example here is a cipher that connected you to test.com and also works for me for packagist.com:

curl -v --cipher ECDHE-RSA-AES256-GCM-SHA384 https://packagist.com

Also I'm curious what ClientHello wget is sending that works.

@Qclanton

This comment has been minimized.

Qclanton commented Feb 12, 2018

Are you in China and maybe some of these hosts are blocked?

No, I'm in Toronto and in this case it would affect the other devices in the network too. And wget also works...

Try making the ClientHello smaller by only sending a single cipher, for example here is a cipher that connected you to test.com and also works for me for packagist.com

Yes. it works. But regular request without 'cipher' option still does not work. I'm not sure I totally understand what cipher is and what did I change using this option. I would you very appreciate if you explain it :) Also, do you have any idea, what further actions can I do to solve my problem?

Dump: curl-test-packagist-org-cipher-20180212.zip
Log:

 curl -v --cipher ECDHE-RSA-AES256-GCM-SHA384 https://packagist.org
* Rebuilt URL to: https://packagist.org/
*   Trying 144.217.203.53...
* TCP_NODELAY set
* Connected to packagist.org (144.217.203.53) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ECDHE-RSA-AES256-GCM-SHA384
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server accepted to use http/1.1
* Server certificate:
*  subject: C=DE; L=Berlin; O=Packagist Conductors UG (haftungsbeschr▒nkt); CN=packagist.org
*  start date: Jul 12 00:00:00 2017 GMT
*  expire date: Aug 25 12:00:00 2020 GMT
*  subjectAltName: host "packagist.org" matched cert's "packagist.org"
*  issuer: C=US; O=DigiCert Inc; CN=DigiCert SHA2 Secure Server CA
*  SSL certificate verify ok.
> GET / HTTP/1.1
> Host: packagist.org
> User-Agent: curl/7.52.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: nginx
< Date: Mon, 12 Feb 2018 23:54:45 GMT
< Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< Vary: Accept-Encoding
< Vary: Accept-Encoding
< Set-Cookie: packagist=ffdshrd5v45qkjhl28o3un0u93; expires=Tue, 13-Feb-2018 00:54:45 GMT; Max-Age=3600; path=/; secure; HttpOnly
< Cache-Control: private, must-revalidate
< Strict-Transport-Security: max-age=31104000
< pragma: no-cache
< expires: -1
< X-Frame-Options: DENY
< Content-Security-Policy: default-src 'self'; block-all-mixed-content; connect-src 'self' *.algolia.net *.algolianet.com; font-src 'self' https://fonts.gstatic.com/; img-src 'self' https://www.gravatar.com/ https://camo.githubusercontent.com/ https://ssl.google-analytics.com/ http://www.google-analytics.com/; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.jsdelivr.net/ https://ssl.google-analytics.com/; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net/ https://fonts.googleapis.com/
< X-Content-Security-Policy: default-src 'self'; block-all-mixed-content; connect-src 'self' *.algolia.net *.algolianet.com; font-src 'self' https://fonts.gstatic.com/; img-src 'self' https://www.gravatar.com/ https://camo.githubusercontent.com/ https://ssl.google-analytics.com/ http://www.google-analytics.com/; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.jsdelivr.net/ https://ssl.google-analytics.com/; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net/ https://fonts.googleapis.com/
< X-Xss-Protection: 1; mode=block
< Referrer-Policy: strict-origin-when-cross-origin
< X-Content-Type-Options: nosniff
<
<!DOCTYPE html>
@jay

This comment has been minimized.

Member

jay commented Feb 13, 2018

Please try packagist.com not packagist.org. Sometimes you are referring to one and sometimes the other and I examined packagist.com which is in your first trace. Monitor host 54.72.156.240 and try both of:

curl -v --resolve packagist.com:443:54.72.156.240 https://packagist.com
curl -v --cipher ECDHE-RSA-AES256-GCM-SHA384 --resolve packagist.com:443:54.72.156.240 https://packagist.com
@Qclanton

This comment has been minimized.

Qclanton commented Feb 13, 2018

Please try packagist.com not packagist.org. Sometimes you are referring to one and sometimes the other

I did this mistake once and then I noticed that and remade tests and edited my comment. If you take a look to all my comments you'll see only packagist.org in them. Anyway, there is no difference in results between any of hosts of both packagist.org and packagist.com.

Monitor host 54.72.156.240 and try both

I did it.
Dumps: curl-test-packagist.com-2018-02-13.zip
Logs:
Unsuccessful regular request to https://packagist.com using curl:

curl -v --resolve packagist.com:443:54.72.156.240 https://packagist.com
url -v --resolve packagist.com:443:54.72.156.240 https://packagist.com
* Added packagist.com:443:54.72.156.240 to DNS cache
* Rebuilt URL to: https://packagist.com/
* Hostname packagist.com was found in DNS cache
*   Trying 54.72.156.240...
* TCP_NODELAY set
* Connected to packagist.com (54.72.156.240) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* Unknown SSL protocol error in connection to packagist.com:443
* Curl_http_done: called premature == 1
* stopped the pause stream!
* Closing connection 0
curl: (35) Unknown SSL protocol error in connection to packagist.com:443

Successful request to https://packagist.com using curl with one cipher:

curl -v --cipher ECDHE-RSA-AES256-GCM-SHA384 --resolve packagist.com:443:54.72.156.240 https://packagist.com
* Added packagist.com:443:54.72.156.240 to DNS cache
* Rebuilt URL to: https://packagist.com/
* Hostname packagist.com was found in DNS cache
*   Trying 54.72.156.240...
* TCP_NODELAY set
* Connected to packagist.com (54.72.156.240) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ECDHE-RSA-AES256-GCM-SHA384
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=packagist.com
*  start date: Sep 15 00:00:00 2017 GMT
*  expire date: Oct 15 12:00:00 2018 GMT
*  subjectAltName: host "packagist.com" matched cert's "packagist.com"
*  issuer: C=US; O=Amazon; OU=Server CA 1B; CN=Amazon
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x55ff3708cc00)
> GET / HTTP/1.1
> Host: packagist.com
> User-Agent: curl/7.52.1
> Accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
< HTTP/2 200
< date: Tue, 13 Feb 2018 13:00:11 GMT
< content-type: text/html; charset=UTF-8
< server: nginx
< vary: Accept-Encoding
< set-cookie: PHPSESSID=48692f734925c98ba6c1c011a5d92014; path=/; secure; HttpOnly
< cache-control: no-cache, private
< x-content-type-options: nosniff
< strict-transport-security: max-age=31104000
< x-frame-options: DENY
< content-security-policy: default-src 'self'; block-all-mixed-content; connect-src 'self' https://api.intercom.io https://api-iam.intercom.io https://api-ping.intercom.io https://nexus-websocket-a.intercom.io https://nexus-websocket-b.intercom.io https://nexus-long-poller-a.intercom.io https://nexus-long-poller-b.intercom.io wss://nexus-websocket-a.intercom.io wss://nexus-websocket-b.intercom.io https://uploads.intercomcdn.com https://uploadsintercomusercontent.coms-websocket-b.intercom.io; font-src 'self' fonts.gstatic.com https://js.intercomcdn.com; frame-src api.recurly.com; img-src data: *; media-src https://js.intercomcdn.com; script-src 'self' www.google-analytics.com js.recurly.com https://app.intercom.io https://widget.intercom.io https://js.intercomcdn.com 'unsafe-inline' 'sha256-UCscuFdInH+Tb2zoqU/yYIJdpqP4aF+6hny3ClW5DfU=' 'sha256-1gcjkQmF3vDBHqTK/GCaJKMg/UjNNomsjObGfUSd8GU=' 'sha256-DcokebrOSmWciSX1qQC5mQVZVTuYP7rxG1GdCn4I4Ls='; style-src 'self' fonts.googleapis.com 'unsafe-inline'
< x-content-security-policy: default-src 'self'; block-all-mixed-content; connect-src 'self' https://api.intercom.io https://api-iam.intercom.io https://api-ping.intercom.io https://nexus-websocket-a.intercom.io https://nexus-websocket-b.intercom.io https://nexus-long-poller-a.intercom.io https://nexus-long-poller-b.intercom.io wss://nexus-websocket-a.intercom.io wss://nexus-websocket-b.intercom.io https://uploads.intercomcdn.com https://uploadsintercomusercontent.coms-websocket-b.intercom.io; font-src 'self' fonts.gstatic.com https://js.intercomcdn.com; frame-src api.recurly.com; img-src data: *; media-src https://js.intercomcdn.com; script-src 'self' www.google-analytics.com js.recurly.com https://app.intercom.io https://widget.intercom.io https://js.intercomcdn.com 'unsafe-inline' 'sha256-UCscuFdInH+Tb2zoqU/yYIJdpqP4aF+6hny3ClW5DfU=' 'sha256-1gcjkQmF3vDBHqTK/GCaJKMg/UjNNomsjObGfUSd8GU=' 'sha256-DcokebrOSmWciSX1qQC5mQVZVTuYP7rxG1GdCn4I4Ls='; style-src 'self' fonts.googleapis.com 'unsafe-inline'
< x-xss-protection: 1; mode=block
<
<!DOCTYPE html>
...

Successful request to https://packagist.com using wget:

wget -S -O - https://packagist.com
--2018-02-13 08:09:55--  https://packagist.com/
Resolving packagist.com (packagist.com)... 54.72.156.240, 54.76.37.177, 54.246.163.107
Connecting to packagist.com (packagist.com)|54.72.156.240|:443... connected.
HTTP request sent, awaiting response...
  HTTP/1.1 200 OK
  Date: Tue, 13 Feb 2018 13:09:56 GMT
  Content-Type: text/html; charset=UTF-8
  Transfer-Encoding: chunked
  Connection: keep-alive
  Server: nginx
  Vary: Accept-Encoding
  Set-Cookie: PHPSESSID=4aa182b3aab87262ad0eb05d15070048; path=/; secure; HttpOnly
  Cache-Control: no-cache, private
  X-Content-Type-Options: nosniff
  Strict-Transport-Security: max-age=31104000
  X-Frame-Options: DENY
  Content-Security-Policy: default-src 'self'; block-all-mixed-content; connect-src 'self' https://api.intercom.io https://api-iam.intercom.io https://api-ping.intercom.io https://nexus-websocket-a.intercom.io https://nexus-websocket-b.intercom.io https://nexus-long-poller-a.intercom.io https://nexus-long-poller-b.intercom.io wss://nexus-websocket-a.intercom.io wss://nexus-websocket-b.intercom.io https://uploads.intercomcdn.com https://uploadsintercomusercontent.coms-websocket-b.intercom.io; font-src 'self' fonts.gstatic.com https://js.intercomcdn.com; frame-src api.recurly.com; img-src data: *; media-src https://js.intercomcdn.com; script-src 'self' www.google-analytics.com js.recurly.com https://app.intercom.io https://widget.intercom.io https://js.intercomcdn.com 'unsafe-inline' 'sha256-UCscuFdInH+Tb2zoqU/yYIJdpqP4aF+6hny3ClW5DfU=' 'sha256-1gcjkQmF3vDBHqTK/GCaJKMg/UjNNomsjObGfUSd8GU=' 'sha256-DcokebrOSmWciSX1qQC5mQVZVTuYP7rxG1GdCn4I4Ls='; style-src 'self' fonts.googleapis.com 'unsafe-inline'
  X-Content-Security-Policy: default-src 'self'; block-all-mixed-content; connect-src 'self' https://api.intercom.io https://api-iam.intercom.io https://api-ping.intercom.io https://nexus-websocket-a.intercom.io https://nexus-websocket-b.intercom.io https://nexus-long-poller-a.intercom.io https://nexus-long-poller-b.intercom.io wss://nexus-websocket-a.intercom.io wss://nexus-websocket-b.intercom.io https://uploads.intercomcdn.com https://uploadsintercomusercontent.coms-websocket-b.intercom.io; font-src 'self' fonts.gstatic.com https://js.intercomcdn.com; frame-src api.recurly.com; img-src data: *; media-src https://js.intercomcdn.com; script-src 'self' www.google-analytics.com js.recurly.com https://app.intercom.io https://widget.intercom.io https://js.intercomcdn.com 'unsafe-inline' 'sha256-UCscuFdInH+Tb2zoqU/yYIJdpqP4aF+6hny3ClW5DfU=' 'sha256-1gcjkQmF3vDBHqTK/GCaJKMg/UjNNomsjObGfUSd8GU=' 'sha256-DcokebrOSmWciSX1qQC5mQVZVTuYP7rxG1GdCn4I4Ls='; style-src 'self' fonts.googleapis.com 'unsafe-inline'
  X-XSS-Protection: 1; mode=block
Length: unspecified [text/html]
Saving to: ‘STDOUT’

-                                                      [<=>                                                                                                             ]       0  --.-KB/s               <!DOCTYPE html>
...
@Qclanton

This comment has been minimized.

Qclanton commented Feb 14, 2018

Can I use only one cipher as a temporary solution? Is it possible to set this option in config permanently?

@jay

This comment has been minimized.

Member

jay commented Feb 14, 2018

Unsuccessful regular request to https://packagist.com using curl:

Thanks I downloaded the capture and was unable to reproduce. I extracted the raw ClientHello and sent it like this:

nc -q90 54.72.156.240 443 < curl-test-packagist-com_ClientHello.raw

I received a ServerHello in reply. Since I am now sending the exact same ClientHello and receiving a reply I believe there is something on your end interfering with the traffic that prevents the ClientHello from being received by the server. My guess is it has something to do with the size of the ClientHello.

Attached are the files I used to reproduce and also several files where I modified the raw data in the ClientHello for making the length of data in the padding extension 1, 0, and also removing the padding extension. In all cases I received a ServerHello in reply. You can try sending the raw data in netcat and monitor in Wireshark to see if you receive a server reply to any of them. (Note nc option -q90 is wait 90 seconds after sending, probably unnecessary and this server should terminate after 1 min if no ServerHello.)

ClientHello_sent_via_nc__anon.zip

It is possible to stop libcurl from requesting the ClientHello be padded by removing flag SSL_OP_TLSEXT_PADDING from SSL_OP_ALL:

diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
index 2a6b3cf..94092d0 100644
--- a/lib/vtls/openssl.c
+++ b/lib/vtls/openssl.c
@@ -2181,6 +2181,9 @@ static CURLcode ossl_connect_step1(struct connectdata *con

   ctx_options = SSL_OP_ALL;

+  /* disable padding test */
+  ctx_options &= ~SSL_OP_TLSEXT_PADDING;
+
 #ifdef SSL_OP_NO_TICKET
   ctx_options |= SSL_OP_NO_TICKET;
 #endif

Can I use only one cipher as a temporary solution? Is it possible to set this option in config permanently?

I think that would cause more problems than it would solve if you put it in the curlrc. There's no guarantee an arbitrary server that you connect to will accept that cipher. For that server specifically even it could stop accepting that cipher.

@bagder

This comment has been minimized.

Member

bagder commented Feb 15, 2018

Impressive research @jay!

This clienthello extension extension is even documented in RFC 7685 and the RFC says:

As an example, consider a client that wishes to avoid sending a
ClientHello with a TLSCiphertext.length between 256 and 511 bytes
(inclusive). This case is considered because at least one TLS
implementation is known to hang the connection when such a
ClientHello record is received.

So, while this is clearly not a curl bug we can of course discuss whether to add support for this padding option.

@Qclanton

This comment has been minimized.

Qclanton commented Feb 20, 2018

@jay, I successfully receive response for raw ClientHello packet. However, I still cannot receive response for ClientHello sent by curl.
Dumps: curl-raw-ClientHello.zip

It is possible to stop libcurl from requesting the ClientHello be padded by removing flag

Is it possible for me to apply this patch somehow?

@bagder

This comment has been minimized.

Member

bagder commented Mar 5, 2018

Yes, @jay's comment holds a patch you can apply.

@Qclanton

This comment has been minimized.

Qclanton commented Mar 5, 2018

@bagder, I would very appreciate if you describe, how I can do that. I installed curl by command apt-get install curl. If I understand right, I have to do next steps:

  1. Download sources.
  2. Apply patch (https://www.thegeekstuff.com/2014/12/patch-command-examples).
  3. Compile library (how?).
  4. Replace installed library with compiled library.

Is that correct sequence? If is so, what should I do on the step 3?

@jay

This comment has been minimized.

Member

jay commented Mar 18, 2018

Compile library (how?).

./configure && make

That installs it in /usr/local and you can use that version as a workaround. If you want to repackage curl/libcurl see https://wiki.debian.org/BuildingAPackage#Edit_the_source_code

@qiangli

This comment has been minimized.

qiangli commented Apr 16, 2018

Experiencing same in latest Jenkins LTS docker image behind a corporate firewall. wget works while curl fails:

jenkins@501c9ac248ea:/tmp$ curl  -v --insecure https://google.com
* Rebuilt URL to: https://google.com/
*   Trying x.x.x.x...
* TCP_NODELAY set
* Connected to (nil) (x.x.x.x) port 8080 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: none
  CApath: /etc/ssl/certs
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* Unknown SSL protocol error in connection to x.x.x.x:8080
* Curl_http_done: called premature == 0
* Closing connection 0
curl: (35) Unknown SSL protocol error in connection to x.x.x.x:8080

jenkins@501c9ac248ea:/tmp$ wget -v --no-check-certificate https://google.com
--2018-04-16 19:09:59--  https://google.com/
Connecting to x.x.x.x:8080... connected.
WARNING: The certificate of ‘google.com’ is not trusted.
WARNING: The certificate of ‘google.com’ hasn't got a known issuer.
Proxy request sent, awaiting response... 301 Moved Permanently
Location: https://www.google.com/ [following]
--2018-04-16 19:09:59--  https://www.google.com/
Connecting to x.x.x.x:8080... connected.
WARNING: The certificate of ‘www.google.com’ is not trusted.
WARNING: The certificate of ‘www.google.com’ hasn't got a known issuer.
Proxy request sent, awaiting response... 200 OK
Length: unspecified [text/html]
Saving to: ‘index.html’

index.html                                                 [ <=>                                                                                                                         ]  10.42K  --.-KB/s    in 0.07s

2018-04-16 19:10:00 (151 KB/s) - ‘index.html’ saved [10672]
@qiangli

This comment has been minimized.

qiangli commented Apr 16, 2018

curl --version
curl 7.52.1 (x86_64-pc-linux-gnu) libcurl/7.52.1 OpenSSL/1.0.2l zlib/1.2.8 libidn2/0.16 libpsl/0.17.0 (+libidn2/0.16) libssh2/1.7.0 nghttp2/1.18.1 librtmp/2.3
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp scp sftp smb smbs smtp smtps telnet tftp
Features: AsynchDNS IDN IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz TLS-SRP HTTP2 UnixSockets HTTPS-proxy PSL

@jay

This comment has been minimized.

Member

jay commented Apr 17, 2018

We have no reason to believe this is a curl problem. If you have more information that makes you think what you are reporting is different then please open a new issue.

@bagder

This comment has been minimized.

Member

bagder commented Apr 29, 2018

I'm going to add an item to the TODO about this extension and then move to close this issue.

@bagder bagder closed this in e085ea9 Apr 29, 2018

@jay

This comment has been minimized.

Member

jay commented Apr 30, 2018

The padding AFAIK is added by default by the ssl backend when necessary but the patch here disables that for openssl. Too little is known about why the padding would be causing the issue so I don't think it's appropriate to add even as an option.

@lock lock bot locked as resolved and limited conversation to collaborators Jul 29, 2018

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.