A repository of bitesize articles, tips & tricks
(in both English and French) curated by Mirego’s team.

Test upcoming DNS changes with “curl --resolve”

Recently, we had to move one of our backend entrypoint from Azure CDN to AWS CloudFront.

Everything was in place and the only thing left to do was for us to change the DNS record for api.example.com from:

$ dog "api.example.com"
# CNAME api.example.com.   5m00s   "example-api-prod.azureedge.net."

to:

$ dog "api.example.com"
# CNAME api.example.com.   5m00s   "d1234567890000.cloudfront.net"

(You should be using dog instead of dig to lookup DNS records, it’s awesome.)

We wanted to make sure that everything was configured properly in the CloudFront distribution (namely its alternate domain name and matching SSL certificate) so that when the actual DNS change would be in effect, everything would keep running smoothly.

Historically, I used to modify my local /etc/hosts file to test this kind of stuff by adding this:

# Make api.example.com resolve to one of CloudFront IP addresses
13.225.190.116 api.example.com

So now requests to api.example.com would resolve to a CloudFront IP address.

$ curl --verbose -XGET "https://api.example.com/health"
# *   Trying 13.225.190.116...
# * TCP_NODELAY set
# * Connected to api.example.com (13.225.190.116) port 443 (#0)

One downside is that until we remove the added line from /etc/hosts, the hostname will always resolve to the IP address. It’s pretty easy to forget about it after our tests and it may lead to unexpected behavior when we actually want it to resolve to the “real” IP address.

But there’s a simpler way to do this without having to deal with /etc/hosts and its downside!

Using curl’s --resolve option, we can force it to resolve to a specific IP address — just for this request!

$ curl --verbose --resolve api.example.com:443:13.225.190.116 -XGET "https://api.example.com/health"
# * Added api.example.com:443:13.225.190.116 to DNS cache
# * Hostname api.example.com was found in DNS cache
# *   Trying 13.225.190.116...
# * TCP_NODELAY set
# * Connected to api.example.com (13.225.190.116) port 443 (#0)

Using --resolve is much more powerful than modifying /etc/hosts since you can specify multiple IP addresses, wildcards, etc.