*google searches 'wiki plex'*
Plex is a client-server media player system and software suite comprising two main components. The Plex Media Server (PMS) desktop application runs on Windows, macOS and Linux-compatibles including some types of NAS devices.
It's a pretty common media server, with its primary client application being a web browser which connects to their servers:
$ curl -vsL https://app.plex.tv/desktop > /dev/null
* Trying 23.22.246.0...
* TCP_NODELAY set
* Connected to app.plex.tv (23.22.246.0) port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
* Server certificate: *.plex.tv
* Server certificate: DigiCert SHA2 Secure Server CA
* Server certificate: DigiCert Global Root CA
> GET /desktop HTTP/1.1
> Host: app.plex.tv
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Fri, 03 Nov 2017 04:44:51 GMT
< Content-Type: text/html; charset=utf-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< Server: nginx/1.13.0
< X-Frame-Options: ALLOW-FROM http://app.plex.tv
< X-XSS-Protection: 1; mode=block
< X-Content-Type-Options: nosniff
< Content-Security-Policy: frame-ancestors 'self' http://app.plex.tv
< ETag: W/"11cffa0d5e7691c70e21385567c89d97"
< Cache-Control: max-age=0, private, must-revalidate
< X-Request-Id: 181266ee-6aec-4d17-b52a-2f54abce9984
< X-Runtime: 0.007836
<
{ [6689 bytes data]
* Connection #0 to host app.plex.tv left intact
This resolves to a web server at
23.22.246.0
, with an HTTPS certificate presented as*.plex.tv
.
However...
The web server informs the client (your browser) of some new hostnames to which follow-up requests are sent. I'll have to find a nice way to present this proof, but for the time being go ahead and open your browser's dev tools and watch all the subsequent requests after https://app.plex.tv/desktop
loads.
A slightly-redacted sample of abbreviated requests consists of the following:
https://plex.tv:443/
wss://pubsub.plex.tv:443/
- (Need to confirm port)
https://192-168-1-14.d0bdefd745cb45789a30d377f4162afd.plex.direct:32400/
https://plex.lolnope.us:443/
https://67-186-228-45.62988ef8f7084969939e9dd428e7c246.plex.direct:32400/
https://192-168-10-51.62988ef8f7084969939e9dd428e7c246.plex.direct:32400/
plex.tv
has us load pubsub.plex.tv
which instructs your browser to make multiple follow-up requests for server discovery. Any PMS server can be reached on its LAN address, and can also be enabled for remote (WAN) access. If remote access is configured, there are two potential ways to connect. Also, if you share access to other PMS's, they will need to be discovered.
In the list I showed above, lines 3 through 6 show this discovery process for my PMS as well as a shared PMS. Each domain resolves to a proper IP context:
$ host 67-186-228-45.62988ef8f7084969939e9dd428e7c246.plex.direct 8.8.8.8
Using domain server:
Name: 8.8.8.8
Address: 8.8.8.8#53
Aliases:
67-186-228-45.62988ef8f7084969939e9dd428e7c246.plex.direct has address 67.186.228.45
$ host 192-168-10-51.62988ef8f7084969939e9dd428e7c246.plex.direct 8.8.8.8
Using domain server:
Name: 8.8.8.8
Address: 8.8.8.8#53
Aliases:
192-168-10-51.62988ef8f7084969939e9dd428e7c246.plex.direct has address 192.168.10.51
This means if you're on your internal LAN, you'll connect to 192.168.10.51
, whereas if you're out on the WAN, you'll connect to 67.186.228.45
.
(You may have to disable DNS rebinding attack prevention).
HTTPS for all!
These domains may resolve to IPs all fine and dandy, but you may notice that each is being access via https
. In particular, how can Plex (the company) issue a publicly valid certificate for a machine on your network?!
Well, check it:
$ openssl s_client -connect 67-186-228-45.62988ef8f7084969939e9dd428e7c246.plex.direct:32400 < /dev/null
CONNECTED(00000003)
---
Certificate chain
0 s:/C=US/ST=CA/L=Los Gatos/O=Plex, Inc./CN=*.62988ef8f7084969939e9dd428e7c246.plex.direct
i:/C=US/O=Plex, Inc./CN=Plex Devices High Assurance CA2
1 s:/C=US/O=Plex, Inc./CN=Plex Devices High Assurance CA2
i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIE3jCCA8agAwIBAgIQDAa1VnGuiJqKTq8+6ncfQTANBgkqhkiG9w0BAQsFADBM
MQswCQYDVQQGEwJVUzETMBEGA1UEChMKUGxleCwgSW5jLjEoMCYGA1UEAxMfUGxl
eCBEZXZpY2VzIEhpZ2ggQXNzdXJhbmNlIENBMjAeFw0xNjEyMjUwMDAwMDBaFw0x
NzEyMjUxMjAwMDBaMHwxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTESMBAGA1UE
BxMJTG9zIEdhdG9zMRMwEQYDVQQKEwpQbGV4LCBJbmMuMTcwNQYDVQQDDC4qLjYy
OTg4ZWY4ZjcwODQ5Njk5MzllOWRkNDI4ZTdjMjQ2LnBsZXguZGlyZWN0MIIBIjAN
BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqrQidEr1NhJl+36mwhpVGJIGdVze
1szlypN8htt5GlPfSqoxJkagX5lLNK4graWXT+Xlg/Z+oMmJ4TAuZ7tQAIXOGgiD
Y1klDAFkuwpE9aJGMEbNVEgCab2cA7Ve5CkkyrnOrtwM/JjJa/CXtJffXgRJMbZx
lWhc30zZz6X2FYo6eawAbgBF/IIOMyp34O7o0z+s8fhg2vneDzxVEVbWjDOUL8mj
+Xb2BJ1xLNYzdKQuBAcdRj7yiAZnFbGcxn+pqd0slG09wSzZOgYa2fN0UrvaRLzZ
WeF0V8Ocl1qFXRTlvwBIDY4yPAo8CTdupDE+qd3j8o58CUrQYln5qKqKTwIDAQAB
o4IBijCCAYYwHwYDVR0jBBgwFoAUlIuJ90hyifJRStmIe+Vhtaqc1QEwHQYDVR0O
BBYEFP7KCZF0qapJGFgVZpKZh8E7NXvHMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUE
FjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwTAYDVR0gBEUwQzA3BglghkgBhv1sAQEw
KjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAIBgZn
gQwBAgIwfgYIKwYBBQUHAQEEcjBwMCUGCCsGAQUFBzABhhlodHRwOi8vb2NzcHgu
ZGlnaWNlcnQuY29tMEcGCCsGAQUFBzAChjtodHRwOi8vY2FjZXJ0cy5kaWdpY2Vy
dC5jb20vUGxleERldmljZXNIaWdoQXNzdXJhbmNlQ0EyLmNydDAMBgNVHRMBAf8E
AjAAMDkGA1UdEQQyMDCCLiouNjI5ODhlZjhmNzA4NDk2OTkzOWU5ZGQ0MjhlN2My
NDYucGxleC5kaXJlY3QwDQYJKoZIhvcNAQELBQADggEBAHIjf/vMdbdBwi44J0zT
1vN5CLVMsMQ1ceLJ4g8IwE5hD5cRxNUrL/WIsg6f42y9hvihvATEhzPfGM5sJkyg
SVk/E1iYPXaNaWSXoLzbNcWRYQIGgQrpS1Tc21pE2mUHkwQcqthHCppDAr6BMGtx
lPGA5hojVfeEmxbQvrPZuYh7fijV18A5059JJm4qNtYIsTpEWLUV3R9ra9ZemWh1
5g2ydY/lEM1f833GXq0qNyvXkfV4p8hm8lXKqKRTGbh1hYOSodosY24+TTzbGBg6
0W4n1RIsfFJzyHXx0d2wegAA7usYh3cfPKJHlkEmG4e993ChLrOFifCf99jEhis+
W2E=
-----END CERTIFICATE-----
subject=/C=US/ST=CA/L=Los Gatos/O=Plex, Inc./CN=*.62988ef8f7084969939e9dd428e7c246.plex.direct
issuer=/C=US/O=Plex, Inc./CN=Plex Devices High Assurance CA2
---
No client certificate CA names sent
---
SSL handshake has read 3421 bytes and written 456 bytes
---
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES128-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : DHE-RSA-AES128-SHA
Session-ID: 396EC8610AFB13EFE30A1472821AC7EB2A7822AD9FC28552BAA94326CF2A3EE7
Session-ID-ctx:
Master-Key: E429EDCB9170E007207EE3BDA01E2C0768B563DB405EB439954F73312AA02021E3196AFCBB12718EFCBED98C0EB15FCE
Key-Arg : None
Start Time: 1509687469
Timeout : 300 (sec)
Verify return code: 0 (ok)
---
Plex (the company) generates *.62988ef8f7084969939e9dd428e7c246.plex.direct
wildcard certificates for each PMS/user out there, and the certificates must be synced down to PMS at some point so the PMS web server can present valid HTTPS certificates.
(The internal domain would have presented the same cert, but I cannot reach
192.168.10.51
from WAN. You'll have to trust me.)
Mkay, what now
I wanted to have my own domain, https://plex.lolnope.us
, to reach instead of going to https://app.plex.tv
. This implies I must have a valid HTTPS certificate if I didn't want browsers getting all upset. 😤
Let's Encrypt is an easy way to do this. Luckily, they have a pfSense package to help with this.
After having a proper HTTPS certificate, I needed to route HTTPS requests via SNI so I can run multiple HTTPS sites on a single IP. HAproxy has a pfSense package that can do this. PMS has a setting known as Custom server access URLs which will publish back to plex.tv
the domain names by which your server is accessible.
Now that I can route Plex HTTPS traffic, I can expose TCP port 443
as an HAproxy frontend, and route traffic to TCP port 32400
on the backend. To instruct plex.tv
to send requests to TCP port 443
, PMS has a setting known as Remote Access Public Port which I manually specified as 443
.
Damn mobile app
The last hurdle was that the (iOS) mobile app seems to be hardcoded to use TCP port 32400
when accessing my WAN IP. So I still needed to add an HAproxy frontend on TCP 32400
and decrypt with the same plex.lolnope.us
certificate I'm using for TCP port 443
.
Result
I can now browse to plex.lolnope.us
and access my content on a web browser or mobile app, on my LAN or on WAN. 👍