25

My server doesn't have IPv6 adresses.

However, when I use Nginx proxy_pass to upstream with IPv4 and IPv6, sometimes it tries to send outgoing requests using IPv6:

2013/07/30 00:25:06 [error] 1930#0: *1482670 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, request: "GET /download/file HTTP/1.0", upstream: "https://[AAAA:BBBB:C:DDD:E:F:GGG:HHH]:443/download/file", host: "example.com"

How can I disable IPv6 for outgoing requests in proxy_pass?

nginx.conf:

upstream download {
  server download.example.com:443;
  keepalive 8;
}

location /download {
  proxy_set_header      X-Forwarded-For  $proxy_add_x_forwarded_for;
  proxy_set_header      Connection "";
  proxy_ignore_headers  X-Accel-Redirect;
  proxy_http_version    1.1;
  resolver              8.8.8.8;
  resolver_timeout      5s;
  proxy_pass            https://download;
}

nginx -V:

nginx version: nginx/1.4.2
built by gcc 4.7.2 (Debian 4.7.2-5)
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-mail --with-mail_ssl_module --with-file-aio --with-http_spdy_module --with-cc-opt='-g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2' --with-ld-opt=-Wl,-z,relro --with-ipv6

OS: Debian Wheezy

Linux 3.2.0-4-amd64 #1 SMP Debian 3.2.46-1 x86_64 GNU/Linux

ip a

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 6c:62:6d:7a:ea:af brd ff:ff:ff:ff:ff:ff
    inet XXX.XXX.XXX.XXX/27 brd XXX.XXX.XXX.XXX scope global eth0
7
  • Does this happen after you do sudo sysctl -w net.ipv6.bindv6only=0? – Flup Jul 31 '13 at 7:53
  • Flup, net.ipv6.bindv6only=0 doesn't help – Anton Aug 1 '13 at 8:23
  • That definitely looks wrong. You should have at least IPv6 link-local addresses. What changes have you or your provider made to this server's configuration? – Michael Hampton Aug 1 '13 at 11:11
  • We've added only net.ipv6.conf.all.disable_ipv6=1. Our provider doesn't assign IPv6 using DHCP, so it must be configured manually. – Anton Aug 2 '13 at 19:40
  • Is there are anyway to solve that specifically with nginx config, without changing global system settings? – Dmitry Polushkin Aug 15 '16 at 15:20
21

Looks like there are a solution since nginx >= 1.5.8:

 resolver 8.8.8.8 ipv6=off;

You can find more here: http://nginx.org/en/docs/http/ngx_http_core_module.html

2
4

Nginx is doing DNS resolution at startup by default.

Include (an empty) variable in the hostname to force Nginx to do resolution at runtime with the specified resolver directive.

location / {
    resolver 1.1.1.1 ipv6=off valid=30s;
    set $empty "";
    proxy_pass https://example.com$empty;
}
2
  • this works but you also need to add $request_uri because it is only added by default when there is no other variable present – phiresky Jun 22 '20 at 12:04
  • It won't allow me to set the variable empty. I read elsewhere that custom variables aren't allowed. What are you doing to allow the set $empty ""? – GaryBishop Feb 9 at 16:54
1

Using the resolver did not work for me when using proxy_pass to a https url. I had to modify the sysctl.

  1. Add the following lines in /etc/sysctl.conf.
    net.ipv6.conf.all.disable_ipv6 = 1 net.ipv6.conf.default.disable_ipv6 = 1 net.ipv6.conf.lo.disable_ipv6 = 1 net.ipv6.conf.eth0.disable_ipv6 = 1 net.ipv6.conf.eth1.disable_ipv6 = 1 net.ipv6.conf.eth2.disable_ipv6 = 1 net.ipv6.conf.eth3.disable_ipv6 = 1
  2. Reboot system with sysctl -p.
  3. Reboot nginx with sudo nginx -s reload.
3
  • Solved my problem proxying flickr. – GaryBishop Jan 3 '20 at 20:38
  • It fixed my problem but now the error log is showing complaints (99: Cannot assign requested address) even though the request apparently succeeds. I'd just like to figure out how to prevent it from trying the ipv6 address. – GaryBishop Jan 3 '20 at 23:46
  • Adding the ipv6=off to the resolver in nginx along with this fixes it and eliminates the error messages. – GaryBishop Jan 4 '20 at 18:52
0

Neither of the solutions above worked for me, it seems that resolver definitions are used in some special case by Nginx, and it usually resolves the IP using system resolver.

My final solution was to define a single IPv4 for my proxy host in /etc/hosts and restart Nginx

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.