72

Let's say a website is load-balanced between several servers. I want to run a command to test whether it's working, such as curl DOMAIN.TLD. So, to isolate each IP address, I specify the IP manually. But many websites may be hosted on the server, so I still provide a host header, like this: curl IP_ADDRESS -H 'Host: DOMAIN.TLD'. In my understanding, these two commands create the exact same HTTP request. The only difference is that in the latter one I take out the DNS lookup part from cURL and do this manually (please correct me if I'm wrong).

All well so far. But now I want to do the same for an HTTPS url. Again, I could test it like this curl https://DOMAIN.TLD. But I want to specify the IP manually, so I run curl https://IP_ADDRESS -H 'Host: DOMAIN.TLD'. Now I get a cURL error:

curl: (51) SSL: certificate subject name 'DOMAIN.TLD' does not match target host name 'IP_ADDRESS'.

I can of course get around this by telling cURL not to care about the certificate (the "-k" option) but it's not ideal.

Is there a way to isolate the IP address being connected to from the host being certified by SSL?

  • Is your load balancer the SSL termination point, or is it the individual instances? – rikola Jul 18 '17 at 11:28
  • Can someone explain why the Host header doesn't select the correct VHost and certificate on the back-end for HTTPS, but this alone for HTTP works OK. Does client pass information to the back-end (using HTTPS protocol) whether IP was used or domain? – NeverEndingQueue Apr 30 at 11:34
105

Think I found a solution going through the cURL manual:

curl https://DOMAIN.EXAMPLE --resolve 'DOMAIN.EXAMPLE:443:192.0.2.17'

Added in [curl] 7.21.3. Removal support added in 7.42.0.

from CURLOPT_RESOLVE explained

  • 1
    --resolve doe not exist in curl... – JustAGuy Sep 10 '14 at 13:07
  • 7
    The curl on my machine (7.27.0) has --resolve. – Theron Luhn Jan 16 '15 at 17:41
  • You can see it work using curl -v and you can see that curl adds the resolve option to the DNS cache temporariy, and adds uses the IP address you specified. – CMCDragonkai Oct 19 '15 at 5:13
  • CentOS 6.8 curl: option --resolve: is unknown curl: try 'curl --help' or 'curl --manual' for more information root@server3 [~]# curl -V curl 7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2 Protocols: tftp ftp telnet dict ldap ldaps http file https ftps scp sftp Features: GSS-Negotiate IDN IPv6 Largefile NTLM SSL libz – Jose Nobile Nov 18 '16 at 5:23
  • Note that if you use a hostname for IP_ADDRESS, it will silently ignore the option. – Xiong Chiamiov Jan 30 '18 at 19:12
11

You can change in /etc/hosts to make the server think that the domain is located at a certain IP.

This is the syntax:

192.168.10.20 www.domain.tld

This will make cURL use the IP-address you want without the SSL-certificate to break.

  • 4
    That works, but I'm looking at some method which doesn't require modifying the OS as a whole – Martin Oct 31 '12 at 9:35
  • I honestly don't think there's another way. You must get cURL to access the correct domain-name for the certificate to work, and the way to map a certain domain to an IP is either by DNS or by the hosts-file. – miono Oct 31 '12 at 10:19
5

Here is the man entry for the currently most upvoted answer since they only included a link to the programmatic component:

--resolve <host:port:address>

    Provide  a  custom  address  for  a specific host and port pair. Using
    this, you can make the curl requests(s) use a specified address and 
    prevent the otherwise normally resolved address to be used. Consider 
    it a sort of /etc/hosts alternative provided on the command line. 
    The port number should be the number used for the specific protocol 
    the host will be used for. It means you need several entries if you 
    want to provide address for the same host but different ports.

    The provided address set by this option will be used even if -4, 
    --ipv4 or -6, --ipv6 is set to make curl use another IP version.

    This option can be used many times to add many host names to resolve.

    Added in 7.21.3.

But due to the limitation given ("It means you need several entries if you want to provide address for the same host but different ports."), I would consider another, newer option that can translate both at the same time:

--connect-to <HOST1:PORT1:HOST2:PORT2>

    For  a request to the given HOST:PORT pair, connect to 
    CONNECT-TO-HOST:CONNECT-TO-PORT instead. This option is suitable 
    to direct requests at a specific server, e.g. at a specific cluster 
    node in a cluster of servers. This option is only used to establish 
    the network connection. It does NOT affect the hostname/port that 
    is used for TLS/SSL (e.g. SNI, certificate verification) or for 
    the application protocols. "host" and "port" may be the empty string, 
    meaning "any host/port". "connect-to-host" and "connect-to-port" 
    may also be the empty string, meaning "use the request's original host/port".

    This option can be used many times to add many connect rules.

    See also --resolve and -H, --header. 
    Added in 7.49.0.
4

If you're running curl in Windows, use double quotes

curl https://DOMAIN.TLD --resolve "DOMAIN.TLD:443:IP_ADDRESS"

curl DOMAIN.TLD --resolve "DOMAIN.TLD:80:IP_ADDRESS"

You can skip the scheme/protocol up front, but you can't skip the port number in the --resolve string.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.