should support passtrough of unmodified plex endpoints

This commit is contained in:
Mathieu Broillet 2025-08-25 15:22:20 +02:00
parent ee52567c46
commit 6d904fe7a5
Signed by: mathieub
GPG Key ID: 4428608CDA3A98D3
4 changed files with 50 additions and 16 deletions

1
.gitignore vendored
View File

@ -8,3 +8,4 @@ tmp/
.idea/ .idea/
certs/ certs/
extracted_apks/ extracted_apks/
plexamp_headless/

View File

@ -26,7 +26,7 @@ Due to the nature of this hack, you'll have to :
# Generate a root CA # Generate a root CA
openssl genrsa -out plexhackCA.key 4096 openssl genrsa -out plexhackCA.key 4096
# Create a self-signed root CA certificate # Create a self-signed root CA certificate
openssl req -x509 -new -nodes -key plexhackCA.key -sha256 -days 3650 -out plexhackCA.crt -subj "/C=US/ST=Unknown/L=Unknown/O=Unknown/CN=PlexHackCA" openssl req -x509 -new -nodes -key plexhackCA.key -sha256 -days 3650 -out plexhackCA.pem -subj "/C=US/ST=SomeState/L=SomeCity/O=PlexHack/OU=PlexHack/CN=PlexHackCA"
# Generate private key for proxy # Generate private key for proxy
openssl genrsa -out plexhackproxy.key 2048 openssl genrsa -out plexhackproxy.key 2048
@ -35,29 +35,31 @@ openssl genrsa -out plexhackproxy.key 2048
cat > plexhacksan.cnf <<EOL cat > plexhacksan.cnf <<EOL
[req] [req]
distinguished_name = req_distinguished_name distinguished_name = req_distinguished_name
req_extensions = req_ext req_extensions = v3_req
prompt = no prompt = no
[req_distinguished_name] [req_distinguished_name]
C = US C = US
ST = Unknown ST = SomeState
L = Unknown L = SomeCity
O = Unknown O = PlexHack
OU = PlexHack
CN = plex.tv CN = plex.tv
[req_ext] [v3_req]
subjectAltName = @alt_names subjectAltName = @alt_names
[alt_names] [alt_names]
DNS.1 = plex.tv DNS.1 = plex.tv
DNS.2 = clients.plex.tv DNS.2 = clients.plex.tv
DNS.3 = app.plex.tv
EOL EOL
# Create a certificate signing request (CSR) using the SAN config # Create a certificate signing request (CSR) using the SAN config
openssl req -new -key plexhackproxy.key -out plexhackproxy.csr -config plexhacksan.cnf openssl req -new -key plexhackproxy.key -out plexhackproxy.csr -config plexhacksan.cnf
# Sign the CSR with your root CA to create the proxy certificate # Sign the CSR with your root CA to create the proxy certificate
openssl x509 -req -in plexhackproxy.csr -CA plexhackCA.crt -CAkey plexhackCA.key -CAcreateserial -out plexhackproxy.crt -days 825 -sha256 -extfile plexhacksan.cnf -extensions req_ext openssl x509 -req -in plexhackproxy.csr -CA plexhackCA.pem -CAkey plexhackCA.key -CAcreateserial -out plexhackproxy.crt -days 365 -sha256 -extfile plexhacksan.cnf -extensions v3_req
``` ```
Now you should have two files `plexhackproxy.crt` and `plexhackproxy.key` that you will use in your reverse proxy. Now you should have two files `plexhackproxy.crt` and `plexhackproxy.key` that you will use in your reverse proxy.
@ -173,7 +175,7 @@ Now if you try to go to `https://clients.plex.tv/api/hack` you should see a JSON
If you see the Plex "Oops, 404" page then something is wrong with your redirection or proxy. If you see the Plex "Oops, 404" page then something is wrong with your redirection or proxy.
## Patch PlexAmp ## Patch Plexamp
>[!IMPORTANT] >[!IMPORTANT]
> You'll need to have the official PlexAmp app installed on your device for this to work. > You'll need to have the official PlexAmp app installed on your device for this to work.
@ -206,13 +208,16 @@ _This might sound harder than it is, just follow these steps_:
```bash ```bash
# 1. Extract the existing cacert.pem from base.apk # 1. Extract the existing cacert.pem from base.apk
unzip base.apk assets/cacert.pem -d tmp/ unzip base.apk assets/cacert.pem -d ./
# 2. Append your custom CA cert # 2. Append your custom CA cert
cat ../certs/plexhackCA.crt >> tmp/assets/cacert.pem echo -e "\nPlexHack" >> assets/cacert.pem
echo -e "==================================" >> assets/cacert.pem
cat ../certs/plexhackCA.pem >> assets/cacert.pem
# 3. Replace the file inside base.apk (no compression) # 3. Remove old cacert.pem and add the new one (with no compression)
zip -r -0 base.apk tmp/assets/cacert.pem zip -d base.apk assets/cacert.pem
zip -X0 base.apk assets/cacert.pem
# 4. Remove existing signatures from ALL APKs (base + splits) # 4. Remove existing signatures from ALL APKs (base + splits)
for f in base.apk split_config.*.apk; do for f in base.apk split_config.*.apk; do
@ -236,3 +241,28 @@ You can now install the modified APK on your Android device.
# Make sure to uninstall the official PlexAmp app first # Make sure to uninstall the official PlexAmp app first
adb install-multiple base.apk split_config.*.apk adb install-multiple base.apk split_config.*.apk
``` ```
## Patch Plexamp Headless
```bash
# Execute this from the root of the cloned repo
mkdir plexamp_headless && cd plexamp_headless
# Download and extract Plexamp Headless
wget https://plexamp.plex.tv/headless/Plexamp-Linux-headless-v4.12.4.tar.bz2 -O plexamp-headless.tar.bz2 -k
tar -xvf plexamp-headless.tar.bz2 && rm plexamp-headless.tar.bz2
mv plexamp/* ./ && rmdir plexamp
# Add the custom CA cert to the cacert.pem file
echo -e "\nPlexHack" >> cacert.pem
echo -e "==================================" >> cacert.pem
cat ../certs/plexhackCA.pem >> cacert.pem
# Now you can run Plexamp Headless with the custom CA cert
node js/index.js
# (optional) You can also setup the systemd service included
mv plexamp.service /etc/systemd/system/
systemctl daemon-reload
systemctl enable --now plexamp # to start at boot and start now
```

View File

@ -6,7 +6,7 @@ from fastapi.responses import Response
from starlette.responses import JSONResponse from starlette.responses import JSONResponse
from client import AsyncCustomHost, NameSolver from client import AsyncCustomHost, NameSolver
from const import OFFICIAL_API, FEATURES_DICT, ENTITLEMENTS, CURRENT_DATE_MINUS_ONE_DAY, FEATURES, \ from const import FEATURES_DICT, ENTITLEMENTS, CURRENT_DATE_MINUS_ONE_DAY, FEATURES, \
CURRENT_DATE_MINUS_ONE_DAY_Z, NEXT_MONTH_DATE_Z, PLEXAMP_FEATURES, TIMESTAMP_CURRENT_PLUS_30DAYS, \ CURRENT_DATE_MINUS_ONE_DAY_Z, NEXT_MONTH_DATE_Z, PLEXAMP_FEATURES, TIMESTAMP_CURRENT_PLUS_30DAYS, \
TIMESTAMP_CURRENT_MINUS_30MIN, PLEXAMP_SUBSCRIPTION_XML TIMESTAMP_CURRENT_MINUS_30MIN, PLEXAMP_SUBSCRIPTION_XML
@ -49,12 +49,12 @@ async def call_official(request: Request, path: str) -> httpx.Response:
} }
# Rewrite Host header to match upstream # Rewrite Host header to match upstream
req_headers["host"] = httpx.URL(OFFICIAL_API).host req_headers["host"] = request.url.hostname
# Forward request upstream # Forward request upstream
upstream_response = await official_client.request( upstream_response = await official_client.request(
method=request.method, method=request.method,
url=f"{OFFICIAL_API}/{path}", url=f"{str(request.base_url).rstrip('/')}/{path}", # f"{OFFICIAL_API}/{path}",
headers=req_headers, headers=req_headers,
content=body, content=body,
params=request.query_params, params=request.query_params,

3
requirements.txt Normal file
View File

@ -0,0 +1,3 @@
httpx
uvicorn
fastapi