toomuchio / plex-nginx-reverseproxy

Configuration to serve Plex Media Center https://plex.tv using Nginx https://nginx.com
663 stars 94 forks source link

Location / not redirecting to /web, causing a 401 error. #19

Closed DenzoNL closed 7 years ago

DenzoNL commented 7 years ago

The current nginx.conf (as of commit 8d238de) does not properly redirect/rewrite from https://plex.domain.xyz/ to https://plex.domain.xyz/web/index.html when using Chrome 57. I'm server a 401 Unauthorized error instead. When manually appending /web or /web/index.html, it all works just fine.

I'm using the config as is with my own SSL certificates, OCSP and HSTS enabled without includeSubdomains.

My full config:

ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;

#Upstream to Plex
upstream plex_backend {
    server 127.0.0.1:32400;
    keepalive 32;
}

server {
    listen 80;
    listen 443 ssl http2; #http2 can provide a substantial improvement for streaming: https://blog.cloudflare.com/introducing-http2/
    server_name plex.domain.xyz;

    #Faster resolving, improves stapling time. Timeout and nameservers may need to be adjusted for your location Google's have been used here.
    resolver 8.8.4.4 8.8.8.8 valid=300s;
    resolver_timeout 10s;

    #Use letsencrypt.org to get a free and trusted ssl certificate
    ssl_certificate /etc/letsencrypt/live/plex.domain.xyz/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/plex.domain.xyz/privkey.pem;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    #Intentionally not hardened for security for player support and encryption video streams has a lot of overhead with something like AES-256-GCM-SHA384.
    ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';

    #Why this is important: https://blog.cloudflare.com/ocsp-stapling-how-cloudflare-just-made-ssl-30/
    ssl_stapling on;
    ssl_stapling_verify on;
    #For letsencrypt.org you can get your chain like this: https://esham.io/2016/01/ocsp-stapling
    ssl_trusted_certificate /etc/letsencrypt/ssl/chain.pem;

    #Reuse ssl sessions, avoids unnecessary handshakes
    #Turning this on will increase performance, but at the cost of security. Read below before making a choice.
    #https://github.com/mozilla/server-side-tls/issues/135
    #https://wiki.mozilla.org/Security/Server_Side_TLS#TLS_tickets_.28RFC_5077.29
    #ssl_session_tickets on;
    ssl_session_tickets off;

    #Use: openssl dhparam -out dhparam.pem 2048 - 4096 is better but for overhead reasons 2048 is enough for Plex.
    ssl_dhparam /etc/nginx/ssl/dhparam.pem;
    ssl_ecdh_curve secp384r1;

    #Will ensure https is always used by supported browsers which prevents any server-side http > https redirects, as the browser will internally correct any request to https.
    #Recommended to submit to your domain to https://hstspreload.org as well.
    #!WARNING! Only enable this if you intend to only serve Plex over https, until this rule expires in your browser it WONT BE POSSIBLE to access Plex via http, remove 'includeSubDomains;' if you only want it to effect your Plex (sub-)domain.
    #This is disabled by default as it could cause issues with some playback devices it's advisable to test it with a small max-age and only enable if you don't encounter issues. (Haven't encountered any yet)
    add_header Strict-Transport-Security "max-age=63072000; preload" always;

    #Plex has A LOT of javascript, xml and html. This helps a lot, but if it causes playback issues with devices turn it off. (Haven't encountered any yet)
    gzip on;
    gzip_vary on;
    gzip_min_length 1000;
    gzip_proxied any;
    gzip_types text/plain text/css text/xml application/xml text/javascript application/x-javascript image/svg+xml;
    gzip_disable "MSIE [1-6]\.";

    #Forward real ip and host to Plex
    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;

    #Websockets
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";

    #Buffering off send to the client as soon as the data is received from Plex.
    proxy_redirect off;
    proxy_buffering off;

    location / {
        if ($request_method != OPTIONS) {
            set $test A;
        }
        if ($http_x_plex_device_name = '') {
            set $test "${test}B";
        }
        if ($arg_X-Plex-Device-Name = '') {
            set $test "${test}C";
        }
        if ($http_user_agent !~ (SmartTV)) {
            set $test "${test}D";
        }

        #If the client isn't an app like a SmartTV and such, forward them to the web interface.
        if ($test = ABCD) {
            rewrite ^/$ $scheme://$http_host/web/index.html;
        }

        proxy_pass http://plex_backend;
    }
}
toomuchio commented 7 years ago

I'm unable to recreate this, curl -i https://plex.domain.xyz and paste the reply if you can, substituting your own domain. Nginx could be out of date or something else clashing with it? Unsure.... Incognito tab unable to recreate it.

DenzoNL commented 7 years ago
HTTP/1.1 302 Moved Temporarily
Server: nginx/1.12.0
Date: Wed, 26 Apr 2017 17:22:01 GMT
Content-Type: text/html
Content-Length: 161
Connection: keep-alive
Location: https://plex.domain.xyz/web/index.html
Strict-Transport-Security: max-age=63072000; preload

<html>
<head><title>302 Found</title></head>
<body bgcolor="white">
<center><h1>302 Found</h1></center>
<hr><center>nginx/1.12.0</center>
</body>
</html>

It seems that when using cURL the location is being set correctly. In incognito mode the URL is indeed set correctly. After clearing all of my browsing data, the issue seems to be resolved as well. Thanks!