What does the --resolve option do in Curl?
The --resolve
option in curl is a powerful feature that allows you to manually specify hostname-to-IP address mappings, effectively bypassing DNS resolution for specific hosts. This option is invaluable for testing, development, debugging, and scenarios where you need to override DNS settings without modifying system-wide configuration files.
How --resolve Works
The --resolve
option tells curl to resolve a specific hostname to a particular IP address and port combination. Instead of performing a DNS lookup, curl uses your specified mapping directly. This happens before any HTTP request is made, allowing you to control exactly which server curl connects to.
Basic Syntax
curl --resolve "hostname:port:ip_address" https://hostname/path
The format is: hostname:port:ip_address
- hostname: The domain name you want to override
- port: The port number (typically 80 for HTTP, 443 for HTTPS)
- ip_address: The IP address to resolve the hostname to
Practical Examples
Basic DNS Override
# Override example.com to point to 192.168.1.100
curl --resolve "example.com:443:192.168.1.100" https://example.com/api/status
This command tells curl to connect to IP address 192.168.1.100
when accessing https://example.com
, regardless of what DNS would normally return.
Testing Local Development Servers
# Test a local development server using production domain
curl --resolve "api.mycompany.com:443:127.0.0.1" https://api.mycompany.com/health
This is particularly useful when developing locally but want to test with the production domain name to ensure SSL certificates and host headers work correctly.
Load Balancer Testing
# Test specific backend servers behind a load balancer
curl --resolve "app.example.com:80:10.0.1.15" http://app.example.com/status
curl --resolve "app.example.com:80:10.0.1.16" http://app.example.com/status
Multiple Host Overrides
You can use multiple --resolve
options in a single command:
curl --resolve "api.example.com:443:192.168.1.10" \
--resolve "cdn.example.com:443:192.168.1.20" \
https://api.example.com/data
Advanced Use Cases
IPv6 Addresses
The --resolve
option also works with IPv6 addresses:
curl --resolve "example.com:443:2001:db8::1" https://example.com/
Testing SSL/TLS Configurations
When testing SSL certificates on different servers:
# Test SSL certificate on a specific server
curl --resolve "secure.example.com:443:203.0.113.50" \
--verbose \
https://secure.example.com/
The --verbose
flag will show you the SSL handshake details, helping verify certificate validity.
Bypassing DNS Propagation Issues
During DNS changes or migrations:
# Access new server before DNS propagation completes
curl --resolve "www.example.com:443:198.51.100.25" \
https://www.example.com/api/v1/status
Comparison with Other Methods
vs /etc/hosts Modification
While you could modify /etc/hosts
to achieve similar results, --resolve
offers several advantages:
- Temporary: Changes only affect the current curl command
- No root access: Doesn't require administrator privileges
- Port-specific: Can specify different IPs for different ports
- Scriptable: Easy to use in automated scripts
vs Host Header Manipulation
Unlike using the --header "Host: hostname"
approach, --resolve
maintains proper hostname verification for SSL/TLS certificates:
# This maintains proper SSL validation
curl --resolve "api.example.com:443:192.168.1.100" https://api.example.com/
# This might cause SSL errors due to hostname mismatch
curl --header "Host: api.example.com" https://192.168.1.100/
Integration with Web Scraping
The --resolve
option is particularly useful in web scraping scenarios where you need to:
- Test scraping scripts against staging environments using production URLs
- Bypass CDNs or load balancers to scrape from specific origin servers
- Work around DNS-based restrictions or geographic redirections
Example: Scraping Behind Load Balancers
# Script to scrape data from multiple backend servers
#!/bin/bash
backends=("10.0.1.10" "10.0.1.11" "10.0.1.12")
for ip in "${backends[@]}"; do
curl --resolve "api.example.com:443:$ip" \
--output "data_${ip}.json" \
https://api.example.com/data
done
Troubleshooting Common Issues
Port Specification
Always include the port number, even for standard ports:
# Correct
curl --resolve "example.com:80:192.168.1.100" http://example.com/
# Incorrect - may not work as expected
curl --resolve "example.com:192.168.1.100" http://example.com/
SSL Certificate Validation
When testing with --resolve
, SSL certificates must still match the hostname:
# This will work if the certificate is valid for example.com
curl --resolve "example.com:443:192.168.1.100" https://example.com/
# Use --insecure to bypass certificate validation for testing
curl --resolve "example.com:443:192.168.1.100" \
--insecure \
https://example.com/
Verification
Use the --verbose
flag to verify that your resolve mapping is being used:
curl --resolve "example.com:443:192.168.1.100" \
--verbose \
https://example.com/ 2>&1 | grep "Trying"
This will show you the actual IP address curl is connecting to.
Best Practices
- Always specify the port: Include the port number even for standard HTTP/HTTPS ports
- Use with --verbose for debugging: The verbose output helps confirm your mappings are working
- Combine with other curl options: Works well with options like --retry for robust requests and --max-time for timeout control
- Document your overrides: When using in scripts, comment why specific IP addresses are being used
Script Integration
Shell Script Example
#!/bin/bash
# Test API endpoints on multiple servers
HOSTNAME="api.example.com"
PORT="443"
SERVERS=("192.168.1.10" "192.168.1.11" "192.168.1.12")
for server in "${SERVERS[@]}"; do
echo "Testing $HOSTNAME on $server"
response=$(curl --resolve "$HOSTNAME:$PORT:$server" \
--silent \
--write-out "%{http_code}" \
https://$HOSTNAME/health)
echo "Server $server returned: $response"
done
Python Integration
import subprocess
import json
def test_server_with_resolve(hostname, port, ip_address, endpoint):
"""Test an endpoint using curl with --resolve option"""
cmd = [
'curl',
'--resolve', f'{hostname}:{port}:{ip_address}',
'--silent',
f'https://{hostname}{endpoint}'
]
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode == 0:
return json.loads(result.stdout)
else:
raise Exception(f"Curl failed: {result.stderr}")
# Usage
try:
data = test_server_with_resolve('api.example.com', '443', '192.168.1.100', '/status')
print(f"API Status: {data}")
except Exception as e:
print(f"Error: {e}")
Conclusion
The --resolve
option in curl is an essential tool for developers, system administrators, and anyone working with web services. It provides precise control over hostname resolution without requiring system-wide changes, making it perfect for testing, debugging, and development scenarios. Whether you're testing new deployments, bypassing DNS issues, or scraping data from specific servers, --resolve
offers a clean and effective solution.
By understanding and utilizing this option effectively, you can significantly improve your debugging capabilities and create more robust testing procedures for web applications and APIs.