36

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, 2013 at 7:53
  • Flup, net.ipv6.bindv6only=0 doesn't help
    – Anton
    Aug 1, 2013 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? Aug 1, 2013 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, 2013 at 19:40
  • Is there are anyway to solve that specifically with nginx config, without changing global system settings? Aug 15, 2016 at 15:20

6 Answers 6

29

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
8

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;
}
3
  • 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, 2020 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, 2021 at 16:54
  • 1
    @phiresky $request_uri is automatically added when there is no /uri/ present in proxy_pass url. See here nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass
    – piotrekkr
    May 14, 2021 at 11:21
3

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.
4
  • Solved my problem proxying flickr.
    – GaryBishop
    Jan 3, 2020 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, 2020 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, 2020 at 18:52
  • This completely disables ipv6 on the OS. Which can be done if you don't want any ipv6 traffic in our out, but might overshoot on not-resolving ipv6 to your proxy-pass.
    – Bennet G.
    Dec 29, 2021 at 11:03
2

I had the same issue with fastcgi_pass to localhost. In this special case (i.e., if you are only forwarding to localhost), you can fix this by using

fastcgi_pass 127.0.0.1:9000;

instead of

fastcgi_pass localhost:9000;
1
  • This solved my issue! Thank you!
    – a1300
    Aug 13, 2022 at 6:30
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

0

Comment out the following line in /etc/nginx/sites-enabled/default:

listen [::]:80 default_server;

Then restart Nginx (sudo systemctl restart nginx.service)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .