Opened 6 months ago

Last modified 6 months ago

#2509 new enhancement

Support IPv6 interface identifiers outside of URLs

Reported by: hardfalcon@… Owned by:
Priority: minor Milestone:
Component: nginx-core Version:
Keywords: Cc:
uname -a: Linux somehost 6.3.6-0-hardened #1 SMP PREEMPT_DYNAMIC Wed, 07 Jun 2023 22:33:46 +0000 x86_64 GNU/Linux
nginx -V: nginx version: nginx/1.25.0
built with OpenSSL 3.1.1 30 May 2023
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --conf-path=/etc/nginx/nginx.conf --sbin-path=/usr/bin/nginx --pid-path=/run/ --lock-path=/run/lock/nginx.lock --user=http --group=http --http-log-path=/var/log/nginx/access.log --error-log-path=stderr --http-client-body-temp-path=/var/lib/nginx/client-body --http-proxy-temp-path=/var/lib/nginx/proxy --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-cc-opt='-march=x86-64 -mtune=generic -O2 -pipe -fno-plt -fexceptions -Wp,-D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -fstack-clash-protection -fcf-protection -g -ffile-prefix-map=/build/nginx-mainline/src=/usr/src/debug/nginx-mainline -flto=auto' --with-ld-opt='-Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now -flto=auto' --with-compat --with-debug --with-file-aio --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_degradation_module --with-http_flv_module --with-http_geoip_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-http_v3_module --with-mail --with-mail_ssl_module --with-pcre-jit --with-stream --with-stream_geoip_module --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-threads


As of version 1.25.0, nginx doesn't seem to support IPv6 interface identifiers at all, even outside of URLs. For example, when trying to use it with the "listen" directive in the "http server" context, I'm getting the following error:

2023/06/11 11:01:54 [emerg] 4542#4542: invalid IPv6 address in "[fe80::123%wg0]:443" of the "listen" directive in /etc/nginx/sites-enabled/test.conf

Even though there might be issues with supporting such address literals within URLs (as stated in #623 and #1422), these addresses would also be useful for other things that don't use URLs, for example for using IPv6 link-local addresses with the "listen" and "set_real_ip_from" directives in the "http server" and "stream server" contexts, or when using such addresses with the "server" directive in the "stream upstream" context.

Side note: It seems that trac doesn't allow setting the 1.24.x or 1.25.x versions when creating a new ticket.

Change History (1)

comment:1 by Maxim Dounin, 6 months ago

As outlined in #623, IPv6 addresses with zone identifiers are not directly supported by nginx, though can be used by providing a name which maps to an appropriate limited-scope IPv6 address.

This approach is expected to work correctly in places where resulting sockaddr structure is directly used, such as in proxy_pass, fastcgi_pass, and server directives in the upstream blocks.

It is not going to work in places where addresses are matched by nginx though. In particular:

  • IPv6 address matching won't try to take scope identifier into account in set_real_ip_from. In set_real_ip_from, scoped IPv6 addresses are actually recognized out of the box: nginx simply uses getaddrinfo() for anything which isn't a valid IP address, and hence scoped IPv6 addresses are properly resolved. Only the IP addresses are used for subsequent matching though.
  • For listen addresses in the http module, listening sockets with identical IPv6 addresses but with different zone identifiers will be considered by nginx as equivalent, as it doesn't try to compare sin6_scope_id. If addresses with different zone identifiers are used, bind should be explicitly requested for each socket.

Better support is more or less requires #1422, since more or less any address parsing in nginx (including listen and server in upstream blocks) uses the same URI parsing code.

Additionally, comparison issues needs to be specifically addressed. I doubt we should try to do it for set_real_ip_from, but might consider checking sin6_scope_id for listening sockets in http.

Note: See TracTickets for help on using tickets.