#1330 closed defect (fixed)
OCSP stapling non-functional on IPv6-only host
Reported by: | Owned by: | ||
---|---|---|---|
Priority: | major | Milestone: | |
Component: | nginx-core | Version: | 1.10.x |
Keywords: | Cc: | ||
uname -a: | Linux front.flathub.org 3.10.0-514.26.2.el7.x86_64 #1 SMP Tue Jul 4 15:04:05 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux | ||
nginx -V: |
ginx version: nginx/1.10.2
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-4) (GCC) built with OpenSSL 1.0.1e-fips 11 Feb 2013 TLS SNI support enabled configure arguments: --prefix=/usr/share/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/tmp/client_body --http-proxy-temp-path=/var/lib/nginx/tmp/proxy --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi --http-scgi-temp-path=/var/lib/nginx/tmp/scgi --pid-path=/run/nginx.pid --lock-path=/run/lock/subsys/nginx --user=nginx --group=nginx --with-file-aio --with-ipv6 --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_addition_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_geoip_module=dynamic --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_degradation_module --with-http_slice_module --with-http_stub_status_module --with-http_perl_module=dynamic --with-mail=dynamic --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream=dynamic --with-stream_ssl_module --with-google_perftools_module --with-debug --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -m64 -mtune=generic' --with-ld-opt='-Wl,-z,relro -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -Wl,-E' |
Description
I have an IPv6-only host running CentOS 7. I have a Lets Encrypt certificate on the host and I've enabled OCSP stapling per the Mozilla preferred SSL stuff. My provider has NAT64 set-up so I've configured their NAT64 resolvers in the resolve entry in nginx.conf.
# OCSP Stapling --- # fetch OCSP records from URL in ssl_certificate and cache them ssl_stapling on; ssl_stapling_verify on; # verify chain of trust of OCSP response using Root CA and Intermediate certs ssl_trusted_certificate /etc/dehydrated/certs/flathub.org/chain.pem; resolver [2a00:1098:0:80:1000:3b:0:1] [2a00:1098:0:82:1000:3b:0:1];
I see this error:
2017/07/24 14:02:23 [error] 16637#0: connect() to 88.221.134.147:80 failed (101: Network is unreachable) while requesting certificate status, responder: ocsp.int-x3.letsencrypt.org
I believe that it's because this host returns two A and two AAAA results:
[root@front nginx]# host ocsp.int-x3.letsencrypt.org ocsp.int-x3.letsencrypt.org is an alias for ocsp.int-x3.letsencrypt.org.edgesuite.net. ocsp.int-x3.letsencrypt.org.edgesuite.net is an alias for a771.dscq.akamai.net. a771.dscq.akamai.net has address 88.221.134.114 a771.dscq.akamai.net has address 88.221.134.147 a771.dscq.akamai.net has IPv6 address 2a02:26f0:e8::6856:6fb0 a771.dscq.akamai.net has IPv6 address 2a02:26f0:e8::6856:6f88
However the SSL stapling code only attempts to connect the first one: https://github.com/nginx/nginx/blob/9197a3c8741a8832e6f6ed24a72dc5b078d840fd/src/event/ngx_event_openssl_stapling.c#L1028
I've tried to work around with /etc/hosts but that seems unused, and OCSP stapling seems to disable itself if I have no resolver configuration entry. I can't seem to place an IPv6 address in the ssl_stapling_responder either.
Change History (8)
follow-up: 4 comment:1 by , 7 years ago
Status: | new → accepted |
---|
comment:3 by , 7 years ago
I wanted to add another workaround: Use a DNS A record filter proxy ( https://tools.ietf.org/html/draft-hazeyama-sunset4-dns-a-filter-00 ).
Sadly I couldn't find any implementation for this, so I used the howto at https://peteris.rocks/blog/dns-proxy-server-in-node-js-with-ui/ and changed the codes a bit. Here's the result: https://pastebin.com/W49EGiMV
So far this seems to have no drawbacks when used on a IPv6 only server but fixes quirks in other software, too.
EDIT: New codes: https://pastebin.com/2NTfJu84
follow-up: 5 comment:4 by , 7 years ago
Replying to mdounin:
The following workarounds should work out of the box though:
- Configure
ssl_stapling_responder
with an reachable address. Note though, that just using an IPv6 address of a real responder likely won't work, as the resulting request will contain an invalidHost
header and likely will be rejected. It can be easily worked around using nginx itself though, with something like this:server { ... ssl_stapling on; ssl_stapling_responder http://[::1]:8082; ... } server { listen [::1]:8082; location / { proxy_pass http://ocsp.int-x3.letsencrypt.org; } }
This workaround worked, with one tweak - as I mentioned in the original ticket the ssl_stapling_responder seemed unwilling to accept a bare IPv6 address in []s, so I put http://localhost in there instead.
comment:5 by , 7 years ago
Replying to ramcq@…:
This workaround worked, with one tweak - as I mentioned in the original ticket the ssl_stapling_responder seemed unwilling to accept a bare IPv6 address in []s, so I put http://localhost in there instead.
You have to use URL, not just an IP address. The configuration as written (with ssl_stapling_responder http://[::1]:8082;
) works fine here.
comment:6 by , 4 years ago
In 7652:7cffd81015e7/nginx:
OCSP stapling: iterate over all responder addresses.
Previously only the first responder address was used per each stapling update.
Now, in case of a network or parsing error, next address is used.
This also fixes the issue with unsupported responder address families
(ticket #1330).
comment:7 by , 4 years ago
Resolution: | → fixed |
---|---|
Status: | accepted → closed |
comment:8 by , 4 years ago
For the record.
It looks like my initial analysis in comment:1 was wrong, and OCSP stapling should be working fine as long as the resolver
directive was used in the configuration, since resolver actually rotates all IP addresses, not preferring neither IPv4 nor IPv6. While the error itself is expected to appear, subsequent OCSP stapling requests are likely to use other addresses and succeed.
The error might be fatal when not using the resolver
directive though, since only the first IP address was used then (obtained during configuration parsing). Before nginx 1.15.10 (8be88b22fe81) it resulted in stapling not working on IPv6-only hosts unless the system resolver was configured to return only IPv6 addresses. Starting with 1.15.10 it might result in fatal errors if IPv4 address was returned first by the system resolver on an IPv6-only host, or IPv6 address was returned first on an IPv4-only host.
With the patch committed all IP addresses will be tried in any case, eliminating the problem. Note though that errors might still appear in logs as long as some addresses tried are not reachable.
The problem is as follows:
As a result, as long as a name resolves to both IPv4 and IPv6 addresses, an IPv4 address is always tried first. It is not reachable though, hence OCSP request fails.
The following workarounds should work out of the box though:
resolver
directive from the configuration, and configure system resolver to only IPv6 addresses (e.g., via/etc/hosts
). This way nginx will complain about... [warn] ... no resolver defined to resolve ...
on each request to the OCSP responder, though should work fine using addresses obtained from system resolver during configuration parsing.ssl_stapling_responder
with an reachable address. Note though, that just using an IPv6 address of a real responder likely won't work, as the resulting request will contain an invalidHost
header and likely will be rejected. It can be easily worked around using nginx itself though, with something like this: Proxy is smart enough to re-try requests if a connection fails, so it should work without additional filtering of addresses.Proper fix would be to introduce fallback to different addresses in OCSP and/or something like
resolver ... ipv4=off
(similar toresolver ... ipv6=off
we have now).