"Contradictory scheme headers" when passing both X-Forwarded-Proto and X-Forwarded-Protocol
daliborfilus opened this issue · 6 comments
When using this nginx configuration:
location / {
proxy_http_version 1.1;
proxy_pass_request_headers on;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
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;
proxy_set_header X-Forwarded-Protocol $scheme;
#proxy_set_header X-Forwarded-Ssl on;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Scheme $scheme;
proxy_pass http://127.0.0.1:8080/;
proxy_buffering off;
}
Seafile throws Bad request "Contradictory scheme headers".
I removed every single header one by one and the error disappears when you either remove X-Forwarded-Proto OR X-Forwarded-Protocol. If you have only one of them, it works. If both, it doesn't.
I know it isn't necessary to use all these headers, but they are surely not contradictory.
(I use all of them just because each app uses different one and I use this as a template for every app.)
Seafile version: Docker seafileltd/seafile-mc:latest, tag: e0edf79c2d14,
I am able to reproduce this.
My vhost config:
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name test.*;
ssl_certificate /etc/acme.sh/certs/test.example.com.cert.pem;
ssl_certificate_key /etc/acme.sh/certs/test.example.com.key.pem;
include includes/security_tls.conf;
include includes/security.conf;
include includes/error_pages_default.conf;
client_max_body_size 0;
location / {
include includes/proxy.conf;
resolver 127.0.0.11 valid=30s;
set $upstream_app 127.0.0.1;
set $upstream_port 12080;
set $upstream_proto http;
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
}
}
proxy.conf:
# Timeout if the real server is dead
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
# Proxy Connection Settings
proxy_buffers 32 4k;
proxy_connect_timeout 240;
proxy_headers_hash_bucket_size 128;
proxy_headers_hash_max_size 1024;
proxy_http_version 1.1;
proxy_read_timeout 240;
proxy_redirect http:// $scheme://;
proxy_send_timeout 240;
# Proxy Cache and Cookie Settings
proxy_cache_bypass $cookie_session;
#proxy_cookie_path / "/; Secure"; # enable at your own risk, may break certain apps
proxy_no_cache $cookie_session;
# Proxy Header Settings
proxy_set_header Connection $connection_upgrade;
proxy_set_header Early-Data $ssl_early_data;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Ssl on;
proxy_set_header X-Real-IP $remote_addr;
Result when I request the Seafile login form:
Bad Request
Contradictory scheme headers
However, when I change X-Forwarded-Ssl
from on
to off
(thus making it indeed contradictory to X-Forwarded-Proto
) or when I omit X-Forwarded-Ssl
the error interestingly disappears.
For those sick and tired of being sick and tired:
If you use linuxservers SWAG or older letsencrypt server, the issue is slightly more nuanced. The challenge is that proxy_set_header X-Forwarded-Ssl "";
or proxy_hide_header X-Forwarded-Ssl;
doesn't work. Apparently, you cannot allow SWAG's /config/nginx/proxy.conf
to set the header and hide it in your new .conf file. You have to essentially comment out include /config/nginx/proxy.conf;
and copy the contents minus the X-Forwarded-Ssl
header.
Here is my working example:
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name seafile.*;
include /config/nginx/ssl.conf;
client_max_body_size 0;
location / {
# Timeout if the real server is dead
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
# Proxy Connection Settings
proxy_buffers 32 4k;
proxy_connect_timeout 240;
proxy_headers_hash_bucket_size 128;
proxy_headers_hash_max_size 1024;
proxy_http_version 1.1;
proxy_read_timeout 240;
proxy_redirect http:// $scheme://;
proxy_send_timeout 240;
# Proxy Cache and Cookie Settings
proxy_cache_bypass $cookie_session;
#proxy_cookie_path / "/; Secure"; # enable at your own risk, may break certain apps
proxy_no_cache $cookie_session;
# Proxy Header Settings
proxy_set_header Connection $connection_upgrade;
proxy_set_header Early-Data $ssl_early_data;
proxy_set_header Host $host;
proxy_set_header Proxy "";
proxy_set_header Upgrade $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto https;
# DON'T ENABLE
# proxy_set_header X-Forwarded-Ssl on;
proxy_set_header X-Real-IP $remote_addr;
# Only way to remove the X-Forwarded-Ssl header is to not set it in the first place.
# include /config/nginx/proxy.conf;
include /config/nginx/resolver.conf;
set $upstream_app seafile;
set $upstream_port 80;
set $upstream_proto http;
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
}
}