filipecarneiro / ELabel

Open-source solution for electronic labels on wine bottles.
https://filipecarneiro.github.io/ELabel/
MIT License
17 stars 3 forks source link

Public label link (QR code) doesn't start with https:// when used behind a HTTPS proxy #13

Closed susedv closed 9 months ago

susedv commented 9 months ago

Describe the bug When using a HTTPS proxy (NGINX in my case) the public label link is determined correcly, with one exception: the scheme of the public label link is http:// and not https://.

Probably this issue is caused by this code in \Extensions\UrlHelper.cs which I believe ignores the "X-Forwarded-Proto" header:

        public static string GetBaseUrl(HttpRequest request)
        {
            // TODO: Use Microsoft.AspNetCore.Mvc.Routing.UrlHelper?

            return $"{request.Scheme}://{request.Host}{request.PathBase}";
        }

It seems to be not the best solution, but if may work if you check for "X-Forwarded-Proto" in request.Headers instead of using request.Scheme.

EDIT: Or probably this is the reason, see here for more details:

Invoke the UseForwardedHeaders method before calling other middleware. Configure the middleware to forward the X-Forwarded-For and X-Forwarded-Proto headers
filipecarneiro commented 9 months ago

Hi @susedv,

Thank you for your feedback! Please keep me posted.

You’ll have the configure the IP address of your reverse proxy. You can do that with an environment variable named KnownProxy. This way, the middlware will properly interpret the X-Forwarded-For and X-Forwarded-Proto headers.

If you are using docker compose, you can do that like this:

environment:
      VIRTUAL_HOST: qr.doutorpc.net
      VIRTUAL_PORT: 8080
      LETSENCRYPT_HOST: qr.doutorpc.net
      KnownProxy: '172.18.0.2'

Then, confirm that everything is OK, visiting the page: /Home/Info

Let me know if this solves your problem.

filipecarneiro commented 9 months ago

I’ll try to find some time to write proper installation instructions…

susedv commented 9 months ago

Hi @filipecarneiro,

thank you for your reply.

Yes, I'm using your docker-compose file. Now I have added 2 more lines:

    environment:
      ...
      VIRTUAL_HOST: e-label.***.net
      KnownProxy: '192.168.122.251'

...and re-created the app-container, but the public label link still starts with http://. I also tried it without the VIRTUAL_HOST variable.

I'm using NGINX Proxy Manager that listens on port 80 and 443 and redirects to http://192.168.122.251:8080 if the host matches e-label.***.net (*** masked for privacy), it also redirects form http:// to https://.

NGINX Proxy Mananger sets the headers properly by itself, but anyway I overwrite them in Advanced Config as follows:

proxy_set_header X-Forwarded-Scheme https;
proxy_set_header X-Forwarded-Proto https;

Everything works - except the public label link, that starts with http://.

filipecarneiro commented 9 months ago

OK. So ELabel is running on the local IP 192.168.122.251, right? Your proxy is in a different machine? If so, you need to configure KnownProxy with that proxy local IP (not 192.168.122.251), so the server will trust that proxy.

Note: Proxies running on loopback addresses (127.0.0.0/8, [::1]), including the standard localhost address (127.0.0.1), are trusted by default.

More info here: https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-8.0

Also, have a look on your page at address /Home/Info for valuable information about your server.

I'm available to help with your configuration. If you want, send me an email to: elabel at doutorpc.net

filipecarneiro commented 9 months ago

Note: In my sample, VIRTUAL_HOST is used for jwilder/nginx-proxy. You don't need it if not using this image. LETSENCRYPT_HOST is for jrcs/letsencrypt-nginx-proxy-companion image: https://github.com/jwilder/docker-letsencrypt-nginx-proxy-companion

susedv commented 9 months ago

Ok, I think I misunderstood which IP address should be set in KnownProxy, now I have changed it to 172.18.0.3 (nginx container). ´192.168.122.251´ is the IP address of the Docker VM, where all containers are running. But also with ´KnownProxy: '172.18.0.3'´ and without VIRTUAL_HOST the label public link starts with http://.

You wrote "...so the server will trust that proxy.", but the proxy works with https:// with no issues. I'm speaking about the absolute link shown in Product->Details->QR Code->Label public link and the link inside the QR Code. All other links are relative and start automatically with https://.

Thank you.

Containers

grafik

NGINX Proxy Manager

grafik

grafik

grafik

filipecarneiro commented 9 months ago

:( Have a look on the /Home/Info page (https://e-label.***.net/Home/Info).

In there, you'll find "Remote IP Address". If the proxy IP is right, it will show the real client IP address. If not, it will show the proxy IP (and then you can adjust the value of KnownProxy).

Also, check the Headers property on that page.

In mine I have: X-Forwarded-Ssl=on X-Forwarded-Port=443

Try to add X-Forwarded-Ssl on yours.

susedv commented 9 months ago

Sorry, I forgot to add /Home/Info, I believe it looks good:

grafik

The NGINX config is now as follows:

proxy_set_header X-Forwarded-Scheme https;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Ssl on;
proxy_set_header X-Forwarded-Port 443;

But it still doesn't work. Probably these last 2 headers are not applied by the proxy as you see in /Home/Info.

filipecarneiro commented 9 months ago

OK. You have to put 172.19.0.1 on KnownProxy. Not 172.18.0.3

susedv commented 9 months ago

Your last post is the right solution - now it works with KnownProxy: '172.19.0.1'. It seems to be the bridge IP address / gateway of the ELabel stack and I expected it to be the IP address of the reverse proxy container or the docker VM it is running on.

Also, when using NGINX Proxy Manager, the following lines do not hurt, but they are not necessary, just because NGINX Proxy Manager puts automatically all requered headers:

proxy_set_header X-Forwarded-Scheme https;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Ssl on;
proxy_set_header X-Forwarded-Port 443;

Thank you!

filipecarneiro commented 9 months ago

You are welcome! Please star the project ;)