How to Make curl Request a Site from a Different IP Than in DNS


One issue I've encountered over the years has been when moving a Web site between systems and the site is set up on two different servers simultaneously (this could also happen if using a CDN). Let's say example.com is set up on 1.1.1.1 and 2.2.2.2 but DNS is pointing solely to 1.1.1.1

What do we do if we want to request http://example.com/ but from 2.2.2.2?

A system wide approach would be adding an entry to the /etc/hosts file:

This usually works but can require you to flush your local DNS cache and/or force refresh in your browser. You have to remember to remove the line as well, it's not very configurable, and so on.

What about if we want to use curl? You could use /etc/hosts but for debugging purposes it'd be nice if we could override the IP address on a single request basis as part of the command. This is possible!

The way I used to do it was to override the Host HTTP header (the way a HTTP client tells a server which host it's looking for) and request from the new IP address, like so:

curl -H "Host: example.com" http://2.2.2.2/

Fine in the old days, but in the modern HTTPS world various problems are introduced. Luckily curl has a solution in the form of --resolve!

--resolve <host:port:address[,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.

So if we want to request example.com from 2.2.2.2, we could do this:

curl http://example.com/ --resolve example.com:80:2.2.2.2 curl https://example.com/ --resolve example.com:443:2.2.2.2 

Multiple entries can be added if needed for more complex situations like chains of redirects, say.

It's also possible to use * as a wildcard host so that any host involved in the request goes to the address you specify (and it could also save you a bit of redundancy and typing!):

curl http://example.com/ --resolve *:80:2.2.2.2