When Nginx performs DNS resolution for upstream servers in proxy_pass configurations, it may receive both IPv4 and IPv6 addresses from the DNS resolver. Even when your server doesn't have IPv6 connectivity, Nginx might still attempt to use IPv6 addresses first due to the default address selection policy.
You'll typically see errors like this in your Nginx error logs:
connect() to [AAAA:BBBB:C:DDD:E:F:GGG:HHH]:443 failed (101: Network is unreachable)
while connecting to upstream, client: AA.BB.CC.DD, server: example.com
Method 1: Explicit IPv4 Resolution in Upstream
The most reliable solution is to explicitly specify the IP version in your upstream definition:
upstream download {
server download.example.com:443 ipv4=on;
keepalive 8;
}
Method 2: DNS Configuration
Configure your resolver to only return IPv4 addresses:
resolver 8.8.8.8 ipv6=off;
Method 3: System-wide IPv6 Disable
For Linux systems, you can disable IPv6 entirely:
echo 1 > /proc/sys/net/ipv6/conf/all/disable_ipv6
echo 1 > /proc/sys/net/ipv6/conf/default/disable_ipv6
For more control, you can use Nginx's proxy_next_upstream
directive to handle failed IPv6 attempts:
location /download {
proxy_pass https://download;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_next_upstream_tries 2;
}
When dealing with multiple upstream servers, the DNS resolution behavior becomes more complex. The ipv4=on
parameter ensures consistent IPv4 behavior across all upstream servers.
Here's the complete recommended configuration:
upstream download {
server download.example.com:443 ipv4=on;
keepalive 8;
}
location /download {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Connection "";
proxy_http_version 1.1;
resolver 8.8.8.8 ipv6=off;
proxy_pass https://download;
}
When your Nginx server attempts to proxy requests to upstream servers that advertise both IPv4 and IPv6 addresses, you might encounter connectivity issues if your infrastructure isn't properly configured for IPv6. This manifests in error logs showing failed IPv6 connection attempts:
connect() to [AAAA:BBBB:C:DDD:E:F:GGG:HHH]:443 failed (101: Network is unreachable)
The issue occurs because:
- DNS resolution returns both A (IPv4) and AAAA (IPv6) records
- Nginx's default behavior is to try IPv6 first when available
- Your server lacks proper IPv6 routing configuration
Here are three effective approaches to force IPv4:
Method 1: Explicit IP Binding in Upstream
upstream download {
server 192.0.2.1:443; # Replace with actual IPv4
keepalive 8;
}
Method 2: DNS Resolution Control
resolver 8.8.8.8 ipv6=off; # Disable IPv6 DNS queries
resolver_timeout 5s;
location /download {
proxy_pass https://download.example.com;
}
Method 3: Kernel-level IPv6 Disable (System-wide)
# Add to /etc/sysctl.conf
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
# Then apply:
sysctl -p
If you're using multiple upstream servers, ensure consistent behavior:
upstream backend {
server backend1.example.com:443 resolve ipv6=off;
server backend2.example.com:443 resolve ipv6=off;
keepalive 16;
}
After implementing changes:
- Reload Nginx:
nginx -s reload
- Check connections:
ss -tulnp | grep nginx
- Test with:
curl -v http://yourdomain.com/download/test