curl: how to specify target hostname for https request

后端 未结 2 1505
野的像风
野的像风 2020-12-31 12:43

I have a x.example which serves traffic for both a.example and b.example. x.example has certificates for both a.exa

相关标签:
2条回答
  • 2020-12-31 13:07

    Indeed SNI in TLS does not work like that. SNI, as everything related to TLS, happens before any kind of HTTP traffic, hence the Host header is not taken into account at that step (but will be useful later on for the webserver to know which host you are connecting too).

    So to enable SNI you need a specific switch in your HTTP client to tell it to send the appropriate TLS extension during the handshake with the hostname value you need.

    In case of curl, you need at least version 7.18.1 (based on https://curl.haxx.se/changes.html) and then it seems to automatically use the value provided in the Host header. It alo depends on which OpenSSL (or equivalent library on your platform) version it is linked to.

    See point 1.10 of https://curl.haxx.se/docs/knownbugs.html that speaks about a bug but explains what happens:

    When given a URL with a trailing dot for the host name part: "https://example.com./", libcurl will strip off the dot and use the name without a dot internally and send it dot-less in HTTP Host: headers and in the TLS SNI field.

    The --connect-to option could also be useful in your case. Or --resolve as a substitute to /etc/hosts, see https://curl.haxx.se/mail/archive-2015-01/0042.html for am example, or https://makandracards.com/makandra/1613-make-an-http-request-to-a-machine-but-fake-the-hostname You can add --verbose in all cases to see in more details what is happening. See this example: https://www.claudiokuenzler.com/blog/693/curious-case-of-curl-ssl-tls-sni-http-host-header ; you will also see there how to test directly with openssl.

    If you have a.example in your /etc/hosts you should just run curl with https://a.example/ and it should take care of the Host header and hence SNI (or use --resolve instead)

    0 讨论(0)
  • 2020-12-31 13:08

    The selected answer helped me find the answer, even though it does not contain the answer. The answer in the mail/archive link Patrick Mevzek provided has the wrong port number. So even following that answer will cause it to continue to fail.

    I used this container to run a debugging server to inspect the requests. I highly suggest anyone debugging this kind of issue do the same.

    Here is how to address the OP's question.

    # Instead of this:
    # curl --header 'Host: a.example'        https://x.example
    
    # Do:
      host=a.example
      target=x.example
    
      ip=$(dig +short $target | head -n1)
      curl -sv   --resolve $host:443:$ip https://$host
    
    

    If you want to ignore bad certificates matches, use -svk instead of -sv

    curl -svk --resolve $host:443:$ip https://$host
    

    Note: Since you are using https, you must use 443 in the --resolve argument instead of 80 as was stated on the mail/archive

    0 讨论(0)
提交回复
热议问题