Strange remote access behaviour

Just confirming I’m seeing the same behavior here. The key seems to lie in being able to get the Remote Access function to work - I can’t seem to get it to understand that I might have a different IP (or rather, hostname) and a valid SSL cert for that hostname. Clients that honor the custom URL directive do work, so the reverse proxy does seem to work just fine when clients call in through it.

My intended traffic flow is CloudFlare -> nginx -> Plex.

Just commenting to say I am also experiencing this.

Okay I appear to have this working now.

I used this to assist with my config:

I have remote access turned off, I have my https://plex.domain.com published as a custom server access URL and I am able to access remotely without relay on android and iOS devices.

@J-Holmes said:
Okay I appear to have this working now.

I used this to assist with my config:

GitHub - toomuchio/plex-nginx-reverseproxy: Configuration to serve Plex Media Center https://plex.tv using Nginx https://nginx.com

I have remote access turned off, I have my https://plex.domain.com published as a custom server access URL and I am able to access remotely without relay on android and iOS devices.

Does that mean you have manually entered your custom URL into the Android and IOS apps? (I don’t see how it would work otherwise).

My problem with that model is I have other friends with PLEX servers that I would like to use, and running a manual config disables account discovery as far as I understand.

I have not.

I have noticed I am commenting in a Windows Forum, however I was experiencing exactly what you was experiencing so assumed it wasn’t platform specific. Maybe it is?

OS X Nginx - I have 5 apps running on the host that are behind my reverse proxy and all work fine.
Plex is on the plex.domain.com subdomain
All other apps are on an admin.domain.com subdomain

Plex

  • Remote Access turned off (However i do have manual port specified as 443 as I believe this is used in the Custom Server Access URL
  • Secure Connections - Required
  • Custom server access URLs - https://plex.domain.com

On the 2 Android devices I have to test when on 4G the Server appears as Remote (not indirect) same with the 1 iOS device I have to test. I sign into the android app with my Plex Pass and it auto detects my Plex Server

@J-Holmes said:
I have not.

I have noticed I am commenting in a Windows Forum, however I was experiencing exactly what you was experiencing so assumed it wasn’t platform specific. Maybe it is?

OS X Nginx - I have 5 apps running on the host that are behind my reverse proxy and all work fine.
Plex is on the plex.domain.com subdomain
All other apps are on an admin.domain.com subdomain

Plex

  • Remote Access turned off (However i do have manual port specified as 443 as I believe this is used in the Custom Server Access URL
  • Secure Connections - Required
  • Custom server access URLs - https://plex.domain.com

On the 2 Android devices I have to test when on 4G the Server appears as Remote (not indirect) same with the 1 iOS device I have to test. I sign into the android app with my Plex Pass and it auto detects my Plex Server

This is really strange… Have you installed your own certificate on the PLEX server, or just added the custom server access URL?
That must mean apps will use the internal URL from discovery if you have disabled remote access (even when being remote). But if you are running split DNS and can use the same URL internally and externally that might just do the trick.
I’m guessing internal clients are also using the 443 connection through NGINX right?

My problem is my URL will not be the same as I want t use 32400 internally and 443 externally.

@J-Holmes said:
Plex

  • Remote Access turned off (However i do have manual port specified as 443 as I believe this is used in the Custom Server Access URL

?? How is that possible. Isn’t that greyed out and useless if remote access is disabled?

@DerKeyser said:
This is really strange… Have you installed your own certificate on the PLEX server, or just added the custom server access URL?
That must mean apps will use the internal URL from discovery if you have disabled remote access (even when being remote). But if you are running split DNS and can use the same URL internally and externally that might just do the trick.
I’m guessing internal clients are also using the 443 connection through NGINX right?

My problem is my URL will not be the same as I want t use 32400 internally and 443 externally.

I have not installed the certificate on the Plex server, just added the custom URL.

I guess if I fire up Wireshark I should be able to see if internal clients are also using the 443 connection? I can take a look. I notice in Plex Media Server logs that i can see multiple reference to port 32400 (when connecting from phone on LAN) and no mention of 443.

@DerKeyser said:

@J-Holmes said:
Plex

  • Remote Access turned off (However i do have manual port specified as 443 as I believe this is used in the Custom Server Access URL

?? How is that possible. Isn’t that greyed out and useless if remote access is disabled?

Like i said this might not even be in effect. I filled in the port 443 before disabling.

Well your plex server will always be accessed on 32400 even if the clients use the 443 connection. That’s how reverse proxies work. See if you can identify which port your client connects to. If you have a client (not web) on windows, fire it up, and then run the netstat command (shows active connections)

Waiting for Windows ISO to download so I can test on WIndows.

I opened PMP and ran netstat from another Mac on my network and:

tcp4 0 0 x.x.x.x.65208 x.x.x.x.32400 ESTABLISHED
tcp4 0 0 x.x.x.x.65207 x.x.x.x.32400 ESTABLISHED
tcp4 0 0 x.x.x.x.65206 x.x.x.x.32400 ESTABLISHED
tcp4 0 0 x.x.x.x.65205 x.x.x.x.32400 ESTABLISHED
tcp4 0 0 x.x.x.x.65204 x.x.x.x.32400 ESTABLISHED

I believe I finally have the reverse proxy working like it should. After following J-Holmes advice in disabling Remote Access in plex. I did have to do a little bit more troubleshooting after the fact though.

Detailed Description

After disabling Remote Access in Plex, my device listing at PMS Resources looked like the following…

<Device <device attributes> >

<Connection protocol="http" address="192.168.20.68" port="32400" uri="http://192.168.20.68:32400" local="1"/>
<Connection protocol="https" address="plex.mydomain.com" port="443" uri="https://plex.mydomain.com" local="1"/>

</Device>

This told me that Plex only thought there were 2 ways to access my server, which is correct. But it still wasn’t working from outside of my home network. After looking at the github link that J-Holmes posted I saw that there were slight discrepancies between that and my Nginx config. The main one being I was only checking for http_x_plex_device_name being equal to the empty string…

if ($http_x_plex_device_name = '') {
    rewrite ^/$ https://$http_host/web/index.html;
}

What made me think that this might be an issue was that while in Firefox I opened Developer -> Network tool and upon loading plex.mydomain.com I saw a lot of 302 redirects in the web traffic. Inspecting the web traffic led me to find that Plex from a browser was sending X-Plex-Device-Name as an argument in the GET request, aka $arg_X-Plex-Device-Name in Nginx. Looking at the github link from above I saw that exact variable check. I updated my if statement in my Nginx config from $http_x_plex_device_name to $arg_X-Plex-Device-Name and I was able to successfully access plex.mydomain.com over 443 remotely and have my library be accessible.

Next I tried from mobile, which (of course) didn’t work. I inspected the Nginx logs to find that the only argument the Android mobile client was sending was X-Plex-Token and therefore it was getting a 302 redirect similar to what the browser had been receiving. So I again modified my Nginx config from $arg_X-Plex-Device-Name to $arg_X-Plex-Token and my Android Plex app can now connect to plex.mydomain.com without issue. And since the browser sends that same argument they both work.

DerKeyser, to your point about wanted internal clients to use 32400. A browser internal to my home network was indeed still accessing my Plex server over 32400. I blocked that access and it started working through my Proxy. So it looks like it will work both ways depending on what it has access to. I have not tried it from any mobile device from internal to my home network. I plan on checking that tonight.

Summary

Plex Server Settings

  • Server Settings->Remote Access = Disabled
  • Server Settings->Network->Custom Cert Location= <path to my pkcs12 file for plex.mydomain.com>
  • Server Settings->Network->Custom Cert Domain= plex.mydomain.com
  • Server Settings->Network->Custom Server Access URL= https://plex.mydomain.com

Nginx Config

My Nginx config file for plex.mydomain.com is exactly like this config, thanks J-Holmes, with one exception. I replaced the following…

		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 ^/$ https://$http_host/web/index.html;
}

with…

		if ($arg_X-Plex-Token = '') {
			rewrite ^/$ https://$http_host/web/index.html;
		}

Next Steps

I plan on verifying these tonight.

  • Verify connectivity with Android (internal)
  • Verify connectivity with iOS device (internal and external)
  • Verify connectivity with Chromecast (internal)

@baileytj
That is very cool work you have done there. So basically it can be brought to a working state with all features available. I trust your mobile clients still discovers the server from your account as opposed to a manual config?
But one question arises: Will setting this up allow my friends to see my PLEX server (discover it) as it’s not registered for “remote access”?

@DerKeyser Yup, my mobile client picked up my library without needing to configure anything additional. A coworker of mine, who I share my plex library with, was still able to see my server just like he normally would.

@baileytj said:
@DerKeyser Yup, my mobile client picked up my library without needing to configure anything additional. A coworker of mine, who I share my plex library with, was still able to see my server just like he normally would.

Very cool work! I’ll try and see if I can mimick that config on my HAproxy :slight_smile:

Hmmm, I don’t seem to quite get what your proxy actually does with the

    if ($arg_X-Plex-Token = '') {
        rewrite ^/$ https://$http_host/web/index.html;
    }

statement in it’s config. I’m a bit of a noob when it comes to http proxy’ing.
Are clients referencing a URL outside of the https://yourdomain/web URL (Not in /web) that you need to catch and rewrite to access the standard URL?

You are looking for an empty X-Plex-Token argument and then you rewrite the URL to access the default index page. I fail to see why that makes it work unless it’s because your proxy removes that argument by default.

@DerKeyser said:
Hmmm, I don’t seem to quite get what your proxy actually does with the

    if ($arg_X-Plex-Token = '') {
        rewrite ^/$ https://$http_host/web/index.html;
    }

statement in it’s config. I’m a bit of a noob when it comes to http proxy’ing.

I know that without that conditional rewrite my plex server becomes “Unavailable”.

From my understanding, when you open a browser and navigate to https://plex.mydomain.com your browser issues a GET request for the path / to the appropriate server. In this request the X-Plex-Token argument does not exist, so you would get redirected to /web/index.html which your browser would then issue another request for, again without the X-Plex-Token argument. This time you won’t get redirected even though the X-Plex-Token argument does not exist becuase the rewrite explicitly matched ^/$. In regex ^ means beginning of line, and $ means end of line. Since this new request contains /web/index.html and not just / the rewrite does not execute. Within the index.html there are a lot of <script> tags that reference javascript files. Your browser goes and gets them as well, still without X-Plex-Token. Once the javascript is loaded from your server the writers of Plex can make the URL requests look like whatever they want. So when the login page appears and you login with your credentials, you get back a valid Plex login token from plex.tv which the javascript then inserts into all of the URL requests as an argument/parameter so that your Plex server knows you already logged in and doesn’t present you with the login screen again (I think).

The first request that my browser makes to my plex server after logging in is

https://plex.mydomain.com/?X-Plex-Product=Plex Web&X-Plex-Version=2.12.5&X-Plex-Client-Identifier=<client id>&X-Plex-Platform=Firefox&X-Plex-Platform-Version=50.0&X-Plex-Device=Windows&X-Plex-Device-Name=Plex Web (Firefox)&X-Plex-Device-Screen-Resolution=1293x210,1920x1080&X-Plex-Token=<token>.

This request does not fall under /web, but the plex server does respond with an XML file.

If the above request was made and the condition in the Nginx config was not present, it would get redirected to /web/index.html which would not return the expected XML file. This appears to be the only request, that is made from loading the homepage, that would match the rewrite rule (as explained above) but evidently it is enough to make the plex server you are connecting to “Unavailable”.

Are clients referencing a URL outside of the https://yourdomain/web URL (Not in /web) that you need to catch and rewrite to access the standard URL?

Other paths outside of /web that I can see Plex access just from loading the homepage of my plex server are:

/
/status
/clients
/updater
/library
/activities
/hubs
/photo

It appears that the only problematic path is /.

You are looking for an empty X-Plex-Token argument and then you rewrite the URL to access the default index page. I fail to see why that makes it work unless it’s because your proxy removes that argument by default.

My proxy does not remove the argument, it is never sent by the browser on the initial request for plex.mydomain.com.

Sorry if this response is a little long, or you already knew some of what I mentioned, I was trying to document what I was seeing/thought so that in a month when I forget how I came up with the Nginx config I have I can look back here. And hopefully this will help someone else that runs across this thread.

1 Like

Thanks for elaborating. I don’t get why the / requests are working when accessing plex directly, but not through the proxy. That means the proxy must do something differently with those requests.by default.

@baileytj your changes got it much closer, thank you. The one bug I encountered after lighting this up was with remote Roku clients.

- - [03/Feb/2017:09:51:13 -0800] “GET / HTTP/1.1” 302 161 “-” “Roku/DVP-7.50 (247.xxxxxxxxxxx)”

Because the client is doing “GET /” nginx redirects as instructed, however seemingly the Roku Plex app has no idea what to do with this:

- - [03/Feb/2017:09:51:13 -0800] “GET /web/index.html HTTP/1.1” 200 938 “Roku/DVP-7.50 (247.xxxxxxxxx)”

Instead, the answer it expects seems to be HTTP 401, and surprise, it then comes back with a token. Now, I am only proxying PMS through this nginx instance, so I opted just to send everything to PMS and let it respond. On the other hand, Android clients for example will also try to GET /, but so far seem to always have a token specified in the URL.

So, a few ways I suppose that you could try to identify the client and respond correctly…one idea maybe is to create a list of user-agents that are definitely Plex devices, and respond with 401 if they do GET / unauthenticated.

This is half-baked, but something along these lines:

/etc/nginx/plexclient.rules

map $http_user_agent $plexclient {
        default         0;
        ~SmartTV    1;
        ~Roku*    1;
(more clients)...
}

back in nginx.conf:

http {
...
include /etc/nginx/plexclient.rules
}
location / {
if ($plexclient) {
return 401;
}
if ($arg_X-Plex-Token = '') {
        rewrite ^/$ https://$http_host/web/index.html;
    }
...
}

@DerKeyser Sorry for not following up for a while. I’ve been trying to get around to testing all of my devices and I ran into a similar issue as @doogie with Roku devices. Since running into the Roku issue I have reverted my config to be almost exactly the config that @J-Holmes posted from github. That is until I have more time on my hands to troubleshoot. @doogie 's solution looks promising but I have not tried it.

@DerKeyser (or any other Plex Pass members) I remember you saying that you were Plex Pass, I unfortunately am not at the moment. Have you tried the latest Plex Media Server 1.4.1? In the release notes there was (Network) Incorrect Remote Access status reported in some cases. (#5834) (#6105). I didn’t know if that could be related to the issues that we were encountering.

Yeah, it made no difference in my installation. Plex is just not reverse proxy friendly due to the less than stellar URL access strategy used by devices.
Unfortunately that probably also means it will never be fixed (as it requires changes to all the clients and how they access the server…