Resolve hostname to IPv6 address in listen directive

Matthias-Christian Ott ott at mirix.org
Wed Aug 25 21:39:00 MSD 2010


On Wed, Aug 25, 2010 at 03:04:44PM +0400, Maxim Dounin wrote:
> Hello!

Hello,

> On Wed, Aug 25, 2010 at 09:27:43AM +0200, Matthias-Christian Ott wrote:
> 
> > At the moment nignx does not allow IPv6 addresses to specified by
> > hostname in a listen directive, that is the following will not work:
> > 
> >   listen ipv6.example.com;
> >   listen [ipv6.example.com];
> >   listen ipv6.example.com ipv6only=on;
> >   listen [ipv6.example.com] ipv6only=on;
> > 
> > Though I see a potential security problem with hostnames here (this
> > also applies to IPv4), because DNS replies can be manipulated if
> > DNSSEC is not used, I think that this feature would be helpful and
> > simplifies administration.
> 
> Note well: listen with hostname always uses *one* address returned 
> by hostname lookup, the first one returned by gethostbyname().  It 
> doesn't make sense to attempt to use it with hostname which 
> resolves to multiple addresses.

Of course you would have to use getaddrinfo() (gethostbyname() is
removed in POSIX.1-2008 and is deprecated by RFC 3493). Multiple
addresses for one hostname are necessary for IPv4/IPv6 dual stack.
So I see no reason why nginx should only associate one IP address
with a hostname.

> > Given that example.com resolves to an IPv4 and IPv6 address, simply
> > binding to both addresses with the following directive would break
> > backwards compatibility: listen example.com;
> > 
> > For backwards compatibility I propose the following to resolve the
> > IPv6 addresses of a hostname and listen on them:
> > 
> > a) listen example.com ipv6only=on;
> > 
> > b) listen [example.com];
> > 
> > Solution b) has the disadvantage that it doesn't conform to RFC 3986.
> 
> Both are bad.  Attribute ipv6only serves completely different 
> purpose: it disables implicit mapping of ipv6 listen sockets to 
> ipv4 (for OSes where such mapping is on by default), i.e. 
> instructs nginx to do setsockopt(IPV6_V6ONLY) on listen socket.  
> See http://tools.ietf.org/html/rfc3493#section-5.3 for details.

I know what the option means and I'm aware of the fact that my
proposed solution introduces a semantic corner case for [::] since we
“overload” the semantics of ipv6only. But I though for backwards
compatibility this would be a good idea. If you prefer a new syntax
simply suggest “ipv4” and “ipv6” as in:
  
  listen example.com ipv4;
  listen example.com ipv6;

This would be the cleanest solution I can come up with.

Moreover, IPv4-compatible IPv6 address are deprecated by RFC 4291 and
I think IPV6_V6ONLY should be the default option, so ipv6only could
at least in 0.8 if not in 0.7 be removed or reused.
 
> I believe correct solution would be to make
> 
>     listen example.com;
> 
> to use ipv6 address if no ipv4 addresses were found.

No definitely not. This would make IPv4/IPv6 dual stack impossible. It
should rather bind to all addresses returned by getaddrinfo() as any
other server does. ipv4only/ipv6only or ipv4/ipv6 (depending on the
final choice) could be used to listen only to IPv4 or IPv6 addresses
of the hostname. This is pretty much the standard behaviour of every
server that support IPv6 correctly.

> Maxim Dounin

Regards,
Matthias-Christian



More information about the nginx-devel mailing list