#1549 closed defect (fixed)

HTTP2 push does not work due to incorrect scheme in proxy_protocol mode

Reported by: roelvanduijnhoven@… Owned by: Ruslan Ermilov <ru@…>
Priority: minor Milestone:
Component: other Version:
Keywords: http2 push Cc:
uname -a: Linux haproxy-machine 3.10.0-693.21.1.el7.x86_64 #1 SMP Wed Mar 7 19:03:37 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
nginx -V: nginx version: nginx/1.14.0 built by gcc 4.8.5 20150623 (Red Hat 4.8.5-16) (GCC) built with OpenSSL 1.0.2k-fips 26 Jan 2017 TLS SNI support enabled configure arguments: --prefix=/etc/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 --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-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_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-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie'

Description

I use the proxy_protocol because I send the tcp traffic via HaProxy? to nginX. However HTTP2 push does not work with this set-up.

When I debug the difference between non-proxy and proxy mode using nghttp I get the following difference:

https://i.stack.imgur.com/OEU3H.png

The resource *is* pushed, but has the wrong scheme.

Sample of configuration used:

    http {
        # This is the one I would like to use
        server {
            listen       8002 http2 proxy_protocol;

            server_name  _;
            root         /usr/share/nginx/html;

            location / {
                http2_push /image.jpg;
            }
        }

        # This one can be accessed directly; and *does* work
        server {
            listen       8004 http2 ssl;

            ssl_certificate certificate.pem;
            ssl_certificate_key private.key;

            server_name  _;
            root         /usr/share/nginx/html;

            location / {
                http2_push /image.jpg;
            }
        }
    }

I could not find a way to overwrite the scheme in nginX in a way that would solve this issue.

I first placed this issue on StackOverflow?. That can be found here: https://stackoverflow.com/questions/50022621/using-http2-push-with-nginx-in-conjunction-with-haproxy-does-not-work

Thanks!

Attachments (2)

patch (1.0 KB) - added by ru 19 months ago.
https.patch (709 bytes) - added by roelvanduijnhoven@… 18 months ago.
Patch that sets https scheme correctly when using proxy protocol

Download all attachments as: .zip

Change History (10)

Changed 19 months ago by ru

comment:1 Changed 19 months ago by ru

Please try the attached patch.

comment:2 Changed 18 months ago by roelvanduijnhoven@…

I can verify that this fixes the problem! Thank you very much :).


On a related note: there is also the problem that the $scheme variable is incorrect when using proxy_protocol. So I quickly verified if this patch also mitigates that situation: that is however not the case.

I tested that by adding:

add_header X-scheme $scheme;

The $scheme variable is http; although the incoming request is definitely https.


Ps: I had some trouble getting a clean Vagrant CentOs?/7 working using https://docs.nginx.com/nginx/admin-guide/installing-nginx/installing-nginx-open-source. Would it be worth creating an issue for this as well (with steps taken to make it work)? But finally got it working :).


Thanks again for your work!

Changed 18 months ago by roelvanduijnhoven@…

Patch that sets https scheme correctly when using proxy protocol

comment:3 follow-up: Changed 18 months ago by roelvanduijnhoven@…

An update.

I did an attempt to update the source code myself. And after compiling found it to work! It now correctly reports the HTTPS scheme only when the actual request has that set as its scheme.

You can find the patch attached!

Note: I am a mere n00b to the nginx code-base. So please review before merging.

comment:4 Changed 18 months ago by ru

See also #711.

comment:5 in reply to: ↑ 3 ; follow-up: Changed 18 months ago by ru

Replying to roelvanduijnhoven@…:

An update.

I did an attempt to update the source code myself. And after compiling found it to work! It now correctly reports the HTTPS scheme only when the actual request has that set as its scheme.

You can find the patch attached!

Note: I am a mere n00b to the nginx code-base. So please review before merging.

While in HTTP/2 the scheme is required, in HTTP/1 it is generally not present (https://tools.ietf.org/html/rfc7230#section-5.3.1) so your patch won't work for HTTP/1.

The original request scheme can be obtained either from the X-Forwarded-Proto header, or derived from the PROXY protocol v2 PP2_TYPE_SSL TLV, but nginx currently lacks support of the latter.

We've also discussed about adding support for XFP and PP2_TYPE_SSL to the realip module with the effect that the $scheme and $https variables will match the original request.

comment:6 Changed 18 months ago by roelvanduijnhoven@…

.. duplicate content

Last edited 18 months ago by roelvanduijnhoven@… (previous) (diff)

comment:7 in reply to: ↑ 5 Changed 18 months ago by roelvanduijnhoven@…

@ru It is hard for me to contribute in this discussion in a meaningful way. But I think the use case I describe is not _that_ special. I'll drop some thoughts in the other issue.
Regarding the original issue: you can fix that issue with the patch you gave earlier. I verified that it worked!

Replying to ru:

Replying to roelvanduijnhoven@…:

An update.

I did an attempt to update the source code myself. And after compiling found it to work! It now correctly reports the HTTPS scheme only when the actual request has that set as its scheme.

You can find the patch attached!

Note: I am a mere n00b to the nginx code-base. So please review before merging.

While in HTTP/2 the scheme is required, in HTTP/1 it is generally not present (https://tools.ietf.org/html/rfc7230#section-5.3.1) so your patch won't work for HTTP/1.

The original request scheme can be obtained either from the X-Forwarded-Proto header, or derived from the PROXY protocol v2 PP2_TYPE_SSL TLV, but nginx currently lacks support of the latter.

We've also discussed about adding support for XFP and PP2_TYPE_SSL to the realip module with the effect that the $scheme and $https variables will match the original request.

comment:8 Changed 18 months ago by Ruslan Ermilov <ru@…>

  • Owner set to Ruslan Ermilov <ru@…>
  • Resolution set to fixed
  • Status changed from new to closed

In 7296:8e6bb4e6045f/nginx:

HTTP/2: use scheme from original request for pushes (closes #1549).

Instead of the connection scheme, use scheme from the original request.
This fixes pushes when SSL is terminated by a proxy server in front of
nginx.

Note: See TracTickets for help on using tickets.