Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Snipe-IT behind reverse proxy loads resources using HTTP instead of HTTPS #9179

Closed
2 tasks done
Zocker1999NET opened this issue Feb 22, 2021 · 21 comments
Closed
2 tasks done
Assignees

Comments

@Zocker1999NET
Copy link

Please confirm you have done the following before posting your bug report:

Describe the bug
Firefox does not load external resources like JavaScript or CSS files because of CSP because the original HTML page is loaded using HTTPS but Snipe-IT wants to load these resources using HTTP.

If I enable debug mode, Snipe-IT wants to load these using HTTPS. Because of that, I cannot append any stacktrace for now.

I use a Docker setup. Every run I tried after any configuration change included deleting all files and databases so no cache hopefully might have broken anything.

To Reproduce

Steps to reproduce the behavior (domain changed to snipeit.example):

  1. Launch Snipe-IT in Docker as recommended, but add --port 127.0.0.1:12345:80 and especially configuring following environment variables:
APP_DEBUG= "false" # or "true" if tested in debug mode
APP_ENV= production
APP_TRUSTED_PROXIES= "*" # used wildcard because our nginx is executed outside Docker and IPs while using Docker seem not static, but due to limiting Docker port forwarding to localhost, Snipe-IT itself is not exposed
APP_URL= "https://snipeit.example"
  1. Configure nginx virtual host using following configuration:
upstream localhost12345 {
  keepalive 32;
  server localhost:12345;
}
server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;

  server_name snipeit.example;

  ssl_certificate /var/lib/dehydrated/certs/snipeit.example/fullchain.pem;                                                                             
  ssl_certificate_key /var/lib/dehydrated/certs/snipeit.example/privkey.pem;                                                                           
  ssl_stapling_file /var/lib/dehydrated/certs/snipeit.example/ocsp.der;

  ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
  ssl_ciphers 'ECDHE+AESGCM+AES256:DHE+AESGCM+AES256:ECDHE+AESGCM+AES128:DHE+AESGCM+AES128:ECDHE+AES256+SHA384:DHE+AES256+SHA256:ECDHE+AES256+SHA:DHE+AES256+SHA:ECDHE+AES128+SHA256:DHE+AES128+SHA256:ECDHE+AES128+SHA:DHE+AES128+SHA:DES-CBC3-SHA';
  ssl_prefer_server_ciphers on;
  ssl_session_cache shared:SSL:1m;
  ssl_session_timeout 1440m;
  ssl_session_tickets off;
  ssl_dhparam /etc/dhparams;
  ssl_stapling on;
  ssl_stapling_verify on;
  add_header Strict-Transport-Security 'max-age=63115200';
  add_header 'Referrer-Policy' 'strict-origin' always;

  add_header X-Content-Type-Options "nosniff" always;
  add_header X-Frame-Options "SAMEORIGIN" always;
  add_header X-XSS-Protection "1; mode=block" always;

  location / {
    proxy_pass http://localhost12345;
    proxy_read_timeout 300;
    proxy_connect_timeout 300;
    proxy_http_version 1.1;
    proxy_set_header Connection $connection_upgrade;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;
  }
}
  1. Visit https://snipeit.example and see error while debug mode is disabled

Expected behavior

  • no errors while loading resources
  • load external resources using HTTPS if everything is configured to be HTTPS

Screenshots
Error loading resources because of CSP (Domain is blurred):
Screenshot_20210222_135056
No error loading resources while debug mode is enabled:
Screenshot_20210222_135609

Server (please complete the following information):

  • Snipe-IT Version: 5.1.1
  • OS: Ubuntu (from your Docker container)
  • Web Server: probably Apache (from your Docker container)
  • PHP Version: 7.2.24-0ubuntu0.18.04.7 (from your Docker container)

Desktop (please complete the following information):

  • OS: Debian 11
  • Browser: Mozilla Firefox
  • Version: 85.0.1 (64-bit)

Error Messages

  • WITH DEBUG TURNED ON, if you're getting an error in your browser, include that error

  • If a stacktrace is provided in the error, include that too.

  • Any errors that appear in your browser's error console.

  • Confirm whether the error is reproducible on the demo: https://snipeitapp.com/demo.

  • Include any additional information you can find in storage/logs and your webserver's logs.

  • Include the output from php -m (this should display what modules you have enabled.)

  • For error logs see browser screenshots

Additional context

  • Is this a fresh install or an upgrade? yes, fresh everytime I tried so far
  • What OS and web server you're running Snipe-IT on: Docker on Debian 10
  • What method you used to install Snipe-IT (install.sh, manual installation, docker, etc): docker
  • Include what you've done so far in the installation, and if you got any error messages along the way.
  • Indicate whether or not you've manually edited any data directly in the database

Add any other context about the problem here.

Please do not post an issue without answering the related questions above. If you have opened a different issue and already answered these questions, answer them again, once for every ticket. It will be next to impossible for us to help you.

@welcome
Copy link

welcome bot commented Feb 22, 2021

👋 Thanks for opening your first issue here! If you're reporting a 🐞 bug, please make sure you include steps to reproduce it. We get a lot of issues on this repo, so please be patient and we will get back to you as soon as we can.

@novastream
Copy link

novastream commented Mar 10, 2021

I'm using the following with Cloudflare:

# Listen on port 443
  listen 443 ssl http2;
  listen [::]:443 ssl http2;

  # Listen on port 80
  listen 80;
  listen [::]:80;

  # Redirect http requests to https
  if ($http_x_forwarded_proto = "http") { return 301
      https://$server_name$request_uri;
  }

Maybe you could try something similar or do a http redirect like this:

server {
    listen [::]:80;
    server_name domain.com www.domain.com;
    return 301 https://domain.com$request_uri;
}

@uberbrady
Copy link
Collaborator

Generally, if your APP_URL has https in it, Snipe-IT should generate URL's with https in it. Are you setting that in your Docker.env file, or are you actually editing the container?

Also our docker container does support terminating SSL itself, might be worth giving that a shot if you have access to your certs (but if your SSL is being set up by Cloudflare, you wouldn't)

@Zocker1999NET
Copy link
Author

Maybe you could try something similar or do a http redirect like this:

server {
    listen [::]:80;
    server_name domain.com www.domain.com;
    return 301 https://domain.com$request_uri;
}

I have configured my server to do this (but globally for all domains, that's why it is not shown here) but this does not work because Firefox did not tried to contact server, it blocked the request locally due to CSP.

Generally, if your APP_URL has https in it, Snipe-IT should generate URL's with https in it. Are you setting that in your Docker.env file, or are you actually editing the container?

My APP_URL has https:// at the beginning and I'm configuring it inside the docker-compose.yml, so similar to Docker.env.

Also our docker container does support terminating SSL itself, might be worth giving that a shot if you have access to your certs (but if your SSL is being set up by Cloudflare, you wouldn't)

I saw that but I would not like to use that because I need an external nginx to serve multiple sites using one IP. I have access to the certificates as I obtain them myself using Let's Encrypt so it would be possible in theory.

What I can say further is that after continuing the installation process in debug mode, this did not happen again. After the installation process I disabled debug mode without having any CSP issues again, so only the installer seems to have this issue, so it might be a minor one.

So this issue only happens if debug mode is disabled while Snipe-IT is not fully installed/configured as I currently see it.

@kajes
Copy link
Contributor

kajes commented Mar 16, 2021

It's not only the installer having this issue. I've ran into this trying to deploy to a kubernetes cluster as well, routing through an ingress controller reverse proxy. The app is absolutely determined to fetch css/js assets through regular http. Not even APP_DEBUG=true seem to help either.

@snipe
Copy link
Owner

snipe commented Mar 16, 2021

I've ran into this trying to deploy to a kubernetes cluster as well

I will never understand why this is a use case that exists, but I try not to judge.

The app is absolutely determined to fetch css/js assets through regular http

So, IIRC, that's a Symfony thing, not a Laravel (or even Snipe-IT thing). We specifically had to create some docs on proxies/reverse proxies because of the way Symfony handles requests.

Not saying that makes it suck any less, it's just not something we have a lot of direct control over. If you're using the TRUSTED_PROXIES environmental variable, you should be okay.

@uberbrady v6 of Laravel has some extra bullshit - I think our middleware/env handling already deals with this, but an extra set of eyes would be great: https://laravel.com/docs/6.x/requests#configuring-trusted-proxies

@kajes
Copy link
Contributor

kajes commented Mar 17, 2021

If you're using the TRUSTED_PROXIES environmental variable, you should be okay.

Yes, I realize it's probably not an issue on your end, but the TRUSTED_PROXIES env variable doesn't seem to work either. That may be something you can look into, but I'll if there's something I can do about it in the ingress controller for future reference. It's an edge case running it like this, but it's probably going to be more common in the future.

Edit:
I found that pretty much the only thing that would make this work properly is to add the $url->forceScheme('https') to the AppServiceProvider boot function. Would this be a possible fix with a check? Something like this:

<?php
namespace App\Providers;

[...]
use Illuminate\Routing\UrlGenerator;

class AppServiceProvider extends ServiceProvider
{
    public function boot(UrlGenerator $url)
    {
	  if ( strpos(env('APP_URL'), 'https://') === 0 ) {
	      $url->forceScheme('https');
	  }
    }

    public function register()
    {
        [...]
    }
}

Not the prettiest of solutions, but modern browsers will block non-TLS calls from a website that is accessed through TLS anyway, so I don't know if it would hurt either.

@Ajedi32
Copy link

Ajedi32 commented Jul 1, 2021

Just ran into this issue as well (I'm not using Kubernetes, just Traefik with docker-compose). I'm not entirely clear on what the purpose of the APP_TRUSTED_PROXIES config is, but even setting it to ** didn't fix the problem in my case.

As a work-around, setting APP_FORCE_TLS=true does seem to resolve the problem, likely due to the change @kajes made in #9179:

if (env('APP_FORCE_TLS')) {
if (strpos(env('APP_URL'), 'https') === 0) {
$url->forceScheme('https');
} else {
\Log::warning("'APP_FORCE_TLS' is set to true, but 'APP_URL' does not start with 'https://'. Will not force TLS on connections.");
}
}

To fix this permanently, best practice would be for the HTML generated by Snipe-IT to not use absolute paths to subresources in cases where a relative URL would do. It sounds from the above comments like this is a problem with a dependency rather than with Snipe-IT itself. Is this something that needs to be reported upstream?

I know pretty much nothing about Laravel or Symfony so forgive me if I'm totally off-base here, but a quick search suggests that Symfony does generate relative URLs when you use the asset component: https://symfony.com/doc/current/components/asset.html#asset-packages Snipe-IT doesn't seem to use that component though, instead generating URLs to subresources by calling url(mix('path/to/subresource')):

<link rel="stylesheet" href="{{ url(mix('css/dist/all.css')) }}">
Would switching to the asset component be a viable solution to this problem?

The Asset Component: The Asset component manages URL generation and versioning of web assets such as CSS stylesheets, JavaScript files and image files. In the past, it was common for web applications...

@tmijieux
Copy link

tmijieux commented Aug 16, 2021

We had exactly the same symptoms at first and we were missing the the X-Forwarded-Proto header.

We added a X-Forwarded-Proto header with a value of "https" before sending the snipe-it backend and that solved the problem in our use-case (all generated urls in raw source use the https protocol)
example configuration for those using nginx,
(in our use case nginx is a ssl-terminating reverse-proxy)
with the proxy_set_header X-Forwaded-Proto $scheme nginx command.

location / {
    proxy_http_version 1.1;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;   # <----- thanks to this the backend knows it is behind https and generate the correct url
    proxy_pass http://10.22.22.7:8000/;  # backend ip for our snipe-it instance
}

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto
for those not using nginx, if you have a way of adding this http header before sending to the backend it should do the work as this is not a nginx specific quirk, just a regular http header.

The X-Forwarded-Proto (XFP) header is a de-facto standard header for identifying the protocol (HTTP or HTTPS) that a client used to connect to your proxy or load balancer. Your server access logs contain the protocol used between the server and the load balancer, but not the protocol used between the client and the load balancer. To determine the protocol used between the client and the load balancer, the X-Forwarded-Proto request header can be used.

edit: i do not know about traefik but there is a mention of this header in their documentation so there must be a way to get this working
https://doc.traefik.io/traefik/middlewares/http/headers/#sslproxyheaders

@jeremylowery
Copy link

jeremylowery commented Oct 21, 2021

I had the exact same problem with a proxy behind apache. Adding the following to the apache virtualhost fixed the issue:

RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
RequestHeader set "X-Forwarded-SSL" expr=%{HTTPS}

@gahoo
Copy link

gahoo commented Jan 18, 2022

In my case, X-Forwarded-Proto does not work for me. By adding this header to nginx, the browser was able to render correctly.

add_header 'Content-Security-Policy' 'upgrade-insecure-requests';

@arnovdk
Copy link

arnovdk commented Feb 7, 2022

TL;DR: Thanks to @Ajedi32 for mentioning APP_FORCE_TLS above; the provided hint works for me.

Elaboration:
For reference to others whom it might concern, I am also experiencing the problem as described in the topic start. I too use Traefik as a proxy in tandem my other Docker containers, among which is Snipe-It. I use Docker Compose for setting everything up and Traefik is configured to redirect all incoming requests from HTTP to HTTPS. As far as I can tell, Snipe-It still runs on port 80, within its own container.

During setup of Snipe-It, some stylesheets (among which is all.css) are blocked by my browser due to the Mixed Content error. In my docker-compose.yml file I specify the proper URL for APP_URL; this URL starts with https://.

Adding the environment variable APP_FORCE_TLS and setting it to true fixes the problem on my end: URLs are (only) now served by Snipe-It via HTTPS, in stead of HTTP.

@RockFoundries
Copy link

What's the current consensus on this? The official docs say to use the trusted proxies and add a header in the reverse proxy server, but this is not doing anything for me, and APP_FORCE_TLS also doesn't seem to do a huge amount either

@nelsonov
Copy link

nelsonov commented Jan 8, 2023

@gahoo You're solution works:

In my case, X-Forwarded-Proto does not work for me. By adding this header to nginx, the browser was able to render correctly.

add_header 'Content-Security-Policy' 'upgrade-insecure-requests';

But for the Snipe-IT folks, this seems to be a kluge that requires browser support. This does not solve the problem of Snipe-IT returning HTTP URL's when it should be returning HTTPS URL's. Like many other people here and elsewhere, I have followed the directions about proxy_set_header X-Forwarded-Proto $scheme; in nginx and APP_TRUSTED_PROXIES and making sure there is an https in APP_URL=https://snipeit.example.com and we still have the problems. There is something else going on here.

@zeemalik2008
Copy link

@gahoo You're solution works:

In my case, X-Forwarded-Proto does not work for me. By adding this header to nginx, the browser was able to render correctly.

add_header 'Content-Security-Policy' 'upgrade-insecure-requests';

But for the Snipe-IT folks, this seems to be a kluge that requires browser support. This does not solve the problem of Snipe-IT returning HTTP URL's when it should be returning HTTPS URL's. Like many other people here and elsewhere, I have followed the directions about proxy_set_header X-Forwarded-Proto $scheme; in nginx and APP_TRUSTED_PROXIES and making sure there is an https in APP_URL=https://snipeit.example.com and we still have the problems. There is something else going on here.

My urls working fine wuth this setting and snipe-it login properly but my saved data not showing in https . fine in localhost and local ip can you help ?

@erakura
Copy link

erakura commented Apr 12, 2023

This is still an issue, and the official documentation produces a non-working result. I've tried adding APP_FORCE_TLS=true and it doesn't seem to do anything. If I have my APP_URL set to snipeit.domain.com (no port) it will fail the URL check, saying that my real URL is snipeit.domain.com:80. If I change it to APP_URL=snipeit.domain.com:80, Firefox will not load the page, with error SSL_ERROR_RX_RECORD_TOO_LONG.
I'm using a nginx reverse proxy running on the Docker host, and it is set to add X-Forwarded-Proto per the instructions.

@snipe
Copy link
Owner

snipe commented Apr 12, 2023

@erakura without knowing what version you're on, I'm not really sure how to help you. I think what you're looking for is APP_ALLOW_INSECURE_HOSTS:

Screenshot 2023-04-12 at 1 31 25 PM

https://snipe-it.readme.io/docs/configuration#optional-misc

Snipe-IT Documentation
This section is where you edit the Snipe-IT configuration file to reflect your own settings, such as your database credentials, mail server, preferred language, timezone, and so on. Some of the settings are optional, some are required.Don't be intimidated by the length of this page. The configuratio...

@erakura
Copy link

erakura commented Apr 12, 2023

@snipe Apologies for not including that information -- I'm on snipe/snipe-it:latest from Docker Hub, Snipe-IT v6.1.0 build 10161.
I've added APP_ALLOW_INSECURE_HOSTS=true to my Docker env. My need is internal-only. Hoping it works fine!
For the sake of thoroughness, I am on Docker 23.0.3 running on Ubuntu 22.04, with nginx/1.18.0 as the reverse proxy.

@kajes
Copy link
Contributor

kajes commented Apr 17, 2023

This is still an issue, and the official documentation produces a non-working result. I've tried adding APP_FORCE_TLS=true and it doesn't seem to do anything. If I have my APP_URL set to snipeit.domain.com (no port) it will fail the URL check, saying that my real URL is snipeit.domain.com:80. If I change it to APP_URL=snipeit.domain.com:80, Firefox will not load the page, with error SSL_ERROR_RX_RECORD_TOO_LONG. I'm using a nginx reverse proxy running on the Docker host, and it is set to add X-Forwarded-Proto per the instructions.

The APP_FORCE_TLS workaround also checks the APP_URL variable. It needs to start with the https:// prefix, otherwise it will be ignored.

@thanatopsian
Copy link

@gahoo You're solution works:

In my case, X-Forwarded-Proto does not work for me. By adding this header to nginx, the browser was able to render correctly.

add_header 'Content-Security-Policy' 'upgrade-insecure-requests';

But for the Snipe-IT folks, this seems to be a kluge that requires browser support. This does not solve the problem of Snipe-IT returning HTTP URL's when it should be returning HTTPS URL's. Like many other people here and elsewhere, I have followed the directions about proxy_set_header X-Forwarded-Proto $scheme; in nginx and APP_TRUSTED_PROXIES and making sure there is an https in APP_URL=https://snipeit.example.com and we still have the problems. There is something else going on here.

FWIW in my case, add_header 'Content-Security-Policy' 'upgrade-insecure-requests'; worked- but it was only a select few resources that were still being passed over http: livewire.js, favicon.io, and selectlist. Devtools said the initiator of selectlist was all.js, but selectlist's get call is under the livewire tab in the debugger- so i think the root cause may be livewire.js.

@setpill
Copy link
Contributor

setpill commented Aug 23, 2024

@gahoo You're solution works:

In my case, X-Forwarded-Proto does not work for me. By adding this header to nginx, the browser was able to render correctly.

add_header 'Content-Security-Policy' 'upgrade-insecure-requests';

But for the Snipe-IT folks, this seems to be a kluge that requires browser support. This does not solve the problem of Snipe-IT returning HTTP URL's when it should be returning HTTPS URL's. Like many other people here and elsewhere, I have followed the directions about proxy_set_header X-Forwarded-Proto $scheme; in nginx and APP_TRUSTED_PROXIES and making sure there is an https in APP_URL=https://snipeit.example.com and we still have the problems. There is something else going on here.

I also experienced this "something else" and traced it down to the TrustProxies middleware not being loaded. PR to fix this was merged almost instantly, so should be fixed in the next release :)

@snipe snipe closed this as completed Aug 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests