Opened 5 years ago

Closed 4 months ago

#623 closed defect (invalid)

IPv6 link-local addresses with zone id not usable in proxy_pass

Reported by: launchpad.net/~lotheac Owned by:
Priority: minor Milestone:
Component: nginx-core Version: 1.6.x
Keywords: Cc:
uname -a: SunOS www 5.11 omnios-8c08411 i86pc i386 i86pc
nginx -V: nginx version: nginx/1.6.1 TLS SNI support enabled configure arguments: --prefix=/opt/nginx --with-ipv6 --with-http_ssl_module --with-ld-opt=-m64 --http-client-body-temp-path=tmp/client_body --http-proxy-temp-path=tmp/proxy --http-fastcgi-temp-path=tmp/fastcgi --http-uwsgi-temp-path=tmp/uwsgi --http-scgi-temp-path=tmp/scgi

Description

nginx doesn't like IPv6 link-local addresses with zone identifiers (addresses like 'fe80::8:20ff:fe6a:64de%www1'; the zone identifier 'www1' here refers to the network interface).

First I tried with a literal address:

proxy_pass http://[fe80::8:20ff:fe6a:64de%www1]:5232/;

but that resulted in

invalid IPv6 address in upstream "[fe80::8:20ff:fe6a:64de%www1]:5232/"

As an aside: I could work around this if it was possible to tell nginx to use getaddrinfo to resolve upstreams. If I put the address in /etc/hosts as 'foo' and use 'http://foo%www1:5232/' both curl and wget resolve the address correctly (because they just pass it to getaddrinfo), but nginx fails with:

no resolver defined to resolve foo%www1

and if I do define a resolver, it will try DNS queries, which is the wrong thing here. Is it not possible to use the system resolver?

Change History (4)

comment:1 follow-up: Changed 5 years ago by mdounin

  • Resolution set to invalid
  • Status changed from new to closed

There is no support for IPv6 literals with zone ids in nginx, though it works fine for names as resolved by the system resolver. Just tested with:

fe80::a00:27ff:fedf:4d9b%em1 foo

in /etc/hosts, and

proxy_pass http://foo;

in nginx config.

Some additional comments:

The "foo%www1" in your example looks wrong to me, as "%www1" is part of the address, not the name. Not sure about Solaris, but FreeBSD's getaddinfo() just fails to lookup such a name.

The fact that nginx complains about "no resolver defined" means that you are trying to use proxy_pass with variables and hence nginx own event-driven DNS resolver have to be used instead of blocking getaddrinfo(). This needs resolver, hence the error (but for obvious reasons, DNS resolution of names won't allow you to use IPv6 addresses zone identifiers).

If you want nginx to resolve names during using getaddrinfo() during configuration parsing while still using variables in proxy_pass, you may force this by explicitly defining upstream{} blocks with appropriate names, like this:

upstream foo {
    server foo;
}

set $backend "foo";
proxy_pass http://$backend;

Alternatively, just avoid using variables in proxy_pass. See http://nginx.org/r/proxy_pass for details.

Note well that RFC 3986 syntax of IPv6 address literals doesn't allow use of zone identifiers. The RFC 6874 tries to extend the syntax by allowing the http://[::1%25zoneid]/ (yes, with %25 instead of %), though this proposed standard was published less than a year ago and seems to have various major problems, see errata list.

comment:2 in reply to: ↑ 1 Changed 5 years ago by launchpad.net/~lotheac

Replying to Maxim Dounin:

fe80::a00:27ff:fedf:4d9b%em1 foo

in /etc/hosts

You may be interested to know that this doesn't work on illumos - getaddrinfo
for foo returns EAI_NONAME if the entry in the hosts file includes the zone id.
But maybe this is a bug in illumos, I don't know.

The "foo%www1" in your example looks wrong to me, as "%www1" is part of the
address, not the name. Not sure about Solaris, but FreeBSD's getaddinfo()
just fails to lookup such a name.

It appears to be the opposite on illumos (and I assume Solaris). If the hosts
file doesn't include the zone id, 'foo%www1' works with getaddrinfo.

The fact that nginx complains about "no resolver defined" means that you are
trying to use proxy_pass with variables and hence nginx own event-driven
DNS resolver have to be used instead of blocking getaddrinfo(). This needs
resolver, hence the error (but for obvious
reasons, DNS resolution of names won't allow you to use IPv6 addresses zone
identifiers).

Ah, thanks, that makes sense - removing variables did the trick. Thanks, and
sorry for the noise.

Last edited 5 years ago by launchpad.net/~lotheac (previous) (diff)

comment:3 Changed 4 months ago by https://stackoverflow.com/users/11113143/birajpaul600

  • Resolution invalid deleted
  • Status changed from closed to reopened
'''
== '''''[
{{{
[[BR]]
[[Image(
----
)]]
}}}
]''''' ==
'''

comment:4 Changed 4 months ago by mdounin

  • Resolution set to invalid
  • Status changed from reopened to closed
Note: See TracTickets for help on using tickets.