2

First of all, this question is not about how to fix this, but rather about why it happens.

Exact same curl (exact same version curl/7.65.1) with exact same request produces different results.

  • Why the certificate chain is different?
  • How server response depends on ssl connection flow? (Alpine get response body "Invalid host header", host OS downloads file w/o any issues)?
  • Why http version is different? How do the server and client agree on protocol version? Running the same command with --http curl flag fixes the issue.

docker run -i -t alpine /bin/sh:

apk add curl
curl -kfSL https://nginx.org/download/nginx-1.15.3.tar.gz -o nginx.tar.gz -vvv

Output:

*   Trying 95.211.80.227:443...
* TCP_NODELAY set
* Connected to nginx.org (95.211.80.227) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (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, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=localhost
*  start date: Jul  8 19:13:11 2019 GMT
*  expire date: Aug  7 19:13:11 2019 GMT
*  issuer: CN=localhost
*  SSL certificate verify result: self signed certificate (18), continuing anyway.
* 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 0x55e3e4a37540)
> GET /download/nginx-1.15.3.tar.gz HTTP/2
> Host: nginx.org
> User-Agent: curl/7.65.1
> Accept: */*
> 
* Connection state changed (MAX_CONCURRENT_STREAMS == 4294967295)!
< HTTP/2 200 
< x-powered-by: Express
< content-type: text/html; charset=utf-8
< content-length: 19
< etag: W/"13-OxsTL6IB85fkJxv9HO8uum0slCI"
< 
* Connection #0 to host nginx.org left intact
Invalid Host header

Same curl command works completely fine from my host machine (Archlinux bleeding edge) even without insecure (-k)option.

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0*   Trying 95.211.80.227:443...
* TCP_NODELAY set
* Connected to nginx.org (95.211.80.227) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: none
} [5 bytes data]
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
} [512 bytes data]
* TLSv1.3 (IN), TLS handshake, Server hello (2):
{ [108 bytes data]
* TLSv1.2 (IN), TLS handshake, Certificate (11):
{ [2621 bytes data]
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
{ [333 bytes data]
* TLSv1.2 (IN), TLS handshake, Server finished (14):
{ [4 bytes data]
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
} [70 bytes data]
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
} [1 bytes data]
* TLSv1.2 (OUT), TLS handshake, Finished (20):
} [16 bytes data]
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0* TLSv1.2 (IN), TLS handshake, Finished (20):
{ [16 bytes data]
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server accepted to use http/1.1
* Server certificate:
*  subject: CN=nginx.org
*  start date: May 14 19:45:30 2019 GMT
*  expire date: Aug 12 19:45:30 2019 GMT
*  subjectAltName: host "nginx.org" matched cert's "nginx.org"
*  issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3
*  SSL certificate verify ok.
} [5 bytes data]
> GET /download/nginx-1.15.3.tar.gz HTTP/1.1
> Host: nginx.org
> User-Agent: curl/7.65.1
> Accept: */*
> 
{ [5 bytes data]
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.15.7
< Date: Wed, 10 Jul 2019 13:03:16 GMT
< Content-Type: application/octet-stream
< Content-Length: 1022881
< Last-Modified: Tue, 28 Aug 2018 15:40:55 GMT
< Connection: keep-alive
< Keep-Alive: timeout=15
< ETag: "5b856d07-f9ba1"
< Accept-Ranges: bytes

P.S. I'm aware of this response

deathangel908
  • 8,601
  • 8
  • 47
  • 81
  • 2
    It looks like on the host where the download is failing, something is getting in between curl and nginx.org. It is offering a certificate for "localhost" instead of nginx.org, appears to support http/2 (which nginx.org does not right now), and sends a header `x-powered-by: Express`. Your container is probably configured in such a way where the nginx download is being redirected to some other local server. – drew010 Jul 10 '19 at 20:53

0 Answers0