Jump to content

Force TLS issue with certain Android/Google TV devices


Recommended Posts

Posted (edited)

I'm running the official Emby docker beta image version 4.9.0.28.
I have issued a ZeroSSL certificate with 2048bit RSA key.
This should provide better compatibility compared to Elliptic Curve (ECC) keys.
However when I enforce secure connections, Android /w GoogleTV and certain Android TV television sets refuse to connect.
Other Emby clients, such as LG WebOS and the Android client on my Samsung Galaxy phone work fine though.

I've created my PFX certificate with OpenSSL:

$ openssl pkcs12 -export -inkey "${HOME}/.acme.sh/mycert/mycert.key" -in "${HOME}/.acme.sh/mycert/fullchain.cer" -out "/docker/emby_data/cert.pfx" -password pass:mypassword


Here's the testssl report:

$ testssl https://xx:8920


###########################################################
    testssl       3.2rc3 from https://testssl.sh/dev/

      This program is free software. Distribution and
             modification under GPLv2 permitted.
      USAGE w/o ANY WARRANTY. USE IT AT YOUR OWN RISK!

       Please file bugs @ https://testssl.sh/bugs/

###########################################################

 Using "OpenSSL 3.2.1 30 Jan 2024 (Library: OpenSSL 3.2.1 30 Jan 2024)" [~94 ciphers]
 on razerblade15:/usr/bin/openssl
 (built: "Feb  9 00:00:00 2024", platform: "linux-x86_64")


 Start 2024-07-29 11:34:26                -->> yy:8920 (xx) <<--

 rDNS (yy):   zz
 Service detected:       HTTP


 Testing protocols via sockets except NPN+ALPN 

 SSLv2      not offered (OK)
 SSLv3      not offered (OK)
 TLS 1      not offered
 TLS 1.1    not offered
 TLS 1.2    offered (OK)
 TLS 1.3    offered (OK): final
 NPN/SPDY   not offered
 ALPN/HTTP2 h2, http/1.1 (offered)

 Testing cipher categories 

 NULL ciphers (no encryption)                      not offered (OK)
 Anonymous NULL Ciphers (no authentication)        not offered (OK)
 Export ciphers (w/o ADH+NULL)                     not offered (OK)
 LOW: 64 Bit + DES, RC[2,4], MD5 (w/o export)      not offered (OK)
 Triple DES Ciphers / IDEA                         not offered
 Obsoleted CBC ciphers (AES, ARIA etc.)            offered
 Strong encryption (AEAD ciphers) with no FS       not offered
 Forward Secrecy strong encryption (AEAD ciphers)  offered (OK)


 Testing server's cipher preferences 

Hexcode  Cipher Suite Name (OpenSSL)       KeyExch.   Encryption  Bits     Cipher Suite Name (IANA/RFC)
-----------------------------------------------------------------------------------------------------------------------------
SSLv2
 - 
SSLv3
 - 
TLSv1
 - 
TLSv1.1
 - 
TLSv1.2 (server order)
 xc030   ECDHE-RSA-AES256-GCM-SHA384       ECDH 253   AESGCM      256      TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384              
 xc02f   ECDHE-RSA-AES128-GCM-SHA256       ECDH 253   AESGCM      128      TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256              
 xc028   ECDHE-RSA-AES256-SHA384           ECDH 253   AES         256      TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384              
 xc027   ECDHE-RSA-AES128-SHA256           ECDH 253   AES         128      TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256              
TLSv1.3 (server order)
 x1302   TLS_AES_256_GCM_SHA384            ECDH 253   AESGCM      256      TLS_AES_256_GCM_SHA384                             
 x1303   TLS_CHACHA20_POLY1305_SHA256      ECDH 253   ChaCha20    256      TLS_CHACHA20_POLY1305_SHA256                       
 x1301   TLS_AES_128_GCM_SHA256            ECDH 253   AESGCM      128      TLS_AES_128_GCM_SHA256                             

 Has server cipher order?     yes (OK) -- TLS 1.3 and below


 Testing robust forward secrecy (FS) -- omitting Null Authentication/Encryption, 3DES, RC4 

 FS is offered (OK)           TLS_AES_256_GCM_SHA384 TLS_CHACHA20_POLY1305_SHA256 ECDHE-RSA-AES256-GCM-SHA384 ECDHE-RSA-AES256-SHA384 TLS_AES_128_GCM_SHA256 ECDHE-RSA-AES128-GCM-SHA256
                              ECDHE-RSA-AES128-SHA256 
 Elliptic curves offered:     prime256v1 secp384r1 secp521r1 X25519 X448 
 Finite field group:          ffdhe2048 ffdhe3072 ffdhe4096 ffdhe6144 ffdhe8192
 TLS 1.2 sig_algs offered:    RSA-PSS-RSAE+SHA256 RSA-PSS-RSAE+SHA384 RSA-PSS-RSAE+SHA512 RSA+SHA256 RSA+SHA384 RSA+SHA512 RSA+SHA224 
 TLS 1.3 sig_algs offered:    RSA-PSS-RSAE+SHA256 RSA-PSS-RSAE+SHA384 RSA-PSS-RSAE+SHA512 

 Testing server defaults (Server Hello) 

 TLS extensions (standard)    "renegotiation info/#65281" "EC point formats/#11" "session ticket/#35" "status request/#5" "supported versions/#43" "key share/#51" "max fragment length/#1"
                              "application layer protocol negotiation/#16" "encrypt-then-mac/#22" "extended master secret/#23"
 Session Ticket RFC 5077 hint 7200 seconds, session tickets keys seems to be rotated < daily
 SSL Session ID support       yes
 Session Resumption           Tickets: yes, ID: yes
 TLS clock skew               Random values, no fingerprinting possible 
 Certificate Compression      none
 Client Authentication        none
 Signature Algorithm          SHA384 with RSA
 Server key size              RSA 2048 bits (exponent is 65537)
 Server key usage             Digital Signature, Key Encipherment
 Server extended key usage    TLS Web Server Authentication, TLS Web Client Authentication
 Serial                       B58642E12F232AB5FF4984A58F4746EF (OK: length 16)
 Fingerprints                 SHA1 021D163300156605D0673C8CC258D4034B17F91D
                              SHA256 B74D0EB06A2D25CE22EF53F5D2E4CCA1B3EE0460D77D36F3A10C3C2B946C039D
 Common Name (CN)             xx 
 subjectAltName (SAN)         xx 
 Trust (hostname)             Ok via SAN and CN (same w/o SNI)
 Chain of trust               Ok   
 EV cert (experimental)       no 
 Certificate Validity (UTC)   78 >= 60 days (2024-07-17 00:00 --> 2024-10-15 23:59)
 ETS/"eTLS", visibility info  not present
 Certificate Revocation List  --
 OCSP URI                     http://zerossl.ocsp.sectigo.com
 OCSP stapling                offered, not revoked
 OCSP must staple extension   --
 DNS CAA RR (experimental)    available - please check for match with "Issuer" below: issue=sectigo.com
 Certificate Transparency     yes (certificate extension)
 Certificates provided        2
 Issuer                       ZeroSSL RSA Domain Secure Site CA (ZeroSSL from AT)
 Intermediate cert validity   #1: ok > 40 days (2030-01-29 23:59). ZeroSSL RSA Domain Secure Site CA <-- USERTrust RSA Certification Authority
 Intermediate Bad OCSP (exp.) Ok


 Testing HTTP header response @ "/" 

 HTTP Status Code             302 Found, redirecting to "web/index.html"
 HTTP clock skew              -1 sec from localtime
 Strict Transport Security    not offered
 Public Key Pinning           --
 Server banner                (no "Server" line in header, interesting!)
 Application banner           --
 Cookie(s)                    (none issued at "/") -- maybe better try target URL of 30x
 Security headers             --
 Reverse Proxy banner         --


 Testing vulnerabilities 

 Heartbleed (CVE-2014-0160)                not vulnerable (OK), no heartbeat extension
 CCS (CVE-2014-0224)                       not vulnerable (OK)
 Ticketbleed (CVE-2016-9244), experiment.  not vulnerable (OK)
 ROBOT                                     Server does not support any cipher suites that use RSA key transport
 Secure Renegotiation (RFC 5746)           supported (OK)
 Secure Client-Initiated Renegotiation     not vulnerable (OK)
 CRIME, TLS (CVE-2012-4929)                not vulnerable (OK)
 BREACH (CVE-2013-3587)                    no gzip/deflate/compress/br HTTP compression (OK)  - only supplied "/" tested
 POODLE, SSL (CVE-2014-3566)               not vulnerable (OK), no SSLv3 support
 TLS_FALLBACK_SCSV (RFC 7507)              No fallback possible (OK), no protocol below TLS 1.2 offered
 SWEET32 (CVE-2016-2183, CVE-2016-6329)    not vulnerable (OK)
 FREAK (CVE-2015-0204)                     not vulnerable (OK)
 DROWN (CVE-2016-0800, CVE-2016-0703)      not vulnerable on this host and port (OK)
                                           make sure you don't use this certificate elsewhere with SSLv2 enabled services, see
                                           https://search.censys.io/search?resource=hosts&virtual_hosts=INCLUDE&q=B74D0EB06A2D25CE22EF53F5D2E4CCA1B3EE0460D77D36F3A10C3C2B946C039D
 LOGJAM (CVE-2015-4000), experimental      not vulnerable (OK): no DH EXPORT ciphers, no DH key detected with <= TLS 1.2
 BEAST (CVE-2011-3389)                     not vulnerable (OK), no SSL3 or TLS1
 LUCKY13 (CVE-2013-0169), experimental     potentially VULNERABLE, uses cipher block chaining (CBC) ciphers with TLS. Check patches
 Winshock (CVE-2014-6321), experimental    not vulnerable (OK)
 RC4 (CVE-2013-2566, CVE-2015-2808)        no RC4 ciphers detected (OK)


 Running client simulations (HTTP) via sockets 

 Browser                      Protocol  Cipher Suite Name (OpenSSL)       Forward Secrecy
------------------------------------------------------------------------------------------------
 Android 6.0                  TLSv1.2   ECDHE-RSA-AES128-GCM-SHA256       256 bit ECDH (P-256)
 Android 7.0 (native)         TLSv1.2   ECDHE-RSA-AES256-GCM-SHA384       256 bit ECDH (P-256)
 Android 8.1 (native)         TLSv1.2   ECDHE-RSA-AES256-GCM-SHA384       253 bit ECDH (X25519)
 Android 9.0 (native)         TLSv1.3   TLS_AES_256_GCM_SHA384            253 bit ECDH (X25519)
 Android 10.0 (native)        TLSv1.3   TLS_AES_256_GCM_SHA384            253 bit ECDH (X25519)
 Android 11 (native)          TLSv1.3   TLS_AES_256_GCM_SHA384            253 bit ECDH (X25519)
 Android 12 (native)          TLSv1.3   TLS_AES_256_GCM_SHA384            253 bit ECDH (X25519)
 Chrome 79 (Win 10)           TLSv1.3   TLS_AES_256_GCM_SHA384            253 bit ECDH (X25519)
 Chrome 101 (Win 10)          TLSv1.3   TLS_AES_256_GCM_SHA384            253 bit ECDH (X25519)
 Firefox 66 (Win 8.1/10)      TLSv1.3   TLS_AES_256_GCM_SHA384            253 bit ECDH (X25519)
 Firefox 100 (Win 10)         TLSv1.3   TLS_AES_256_GCM_SHA384            253 bit ECDH (X25519)
 IE 6 XP                      No connection
 IE 8 Win 7                   No connection
 IE 8 XP                      No connection
 IE 11 Win 7                  TLSv1.2   ECDHE-RSA-AES256-SHA384           256 bit ECDH (P-256)
 IE 11 Win 8.1                TLSv1.2   ECDHE-RSA-AES256-SHA384           256 bit ECDH (P-256)
 IE 11 Win Phone 8.1          TLSv1.2   ECDHE-RSA-AES128-SHA256           256 bit ECDH (P-256)
 IE 11 Win 10                 TLSv1.2   ECDHE-RSA-AES256-GCM-SHA384       256 bit ECDH (P-256)
 Edge 15 Win 10               TLSv1.2   ECDHE-RSA-AES256-GCM-SHA384       253 bit ECDH (X25519)
 Edge 101 Win 10 21H2         TLSv1.3   TLS_AES_256_GCM_SHA384            253 bit ECDH (X25519)
 Safari 12.1 (iOS 12.2)       TLSv1.3   TLS_AES_256_GCM_SHA384            253 bit ECDH (X25519)
 Safari 13.0 (macOS 10.14.6)  TLSv1.3   TLS_AES_256_GCM_SHA384            253 bit ECDH (X25519)
 Safari 15.4 (macOS 12.3.1)   TLSv1.3   TLS_AES_256_GCM_SHA384            253 bit ECDH (X25519)
 Java 7u25                    No connection
 Java 8u161                   TLSv1.2   ECDHE-RSA-AES256-GCM-SHA384       256 bit ECDH (P-256)
 Java 11.0.2 (OpenJDK)        TLSv1.3   TLS_AES_256_GCM_SHA384            256 bit ECDH (P-256)
 Java 17.0.3 (OpenJDK)        TLSv1.3   TLS_AES_256_GCM_SHA384            253 bit ECDH (X25519)
 go 1.17.8                    TLSv1.3   TLS_AES_256_GCM_SHA384            253 bit ECDH (X25519)
 LibreSSL 2.8.3 (Apple)       TLSv1.2   ECDHE-RSA-AES256-GCM-SHA384       253 bit ECDH (X25519)
 OpenSSL 1.0.2e               TLSv1.2   ECDHE-RSA-AES256-GCM-SHA384       256 bit ECDH (P-256)
 OpenSSL 1.1.0l (Debian)      TLSv1.2   ECDHE-RSA-AES256-GCM-SHA384       253 bit ECDH (X25519)
 OpenSSL 1.1.1d (Debian)      TLSv1.3   TLS_AES_256_GCM_SHA384            253 bit ECDH (X25519)
 OpenSSL 3.0.3 (git)          TLSv1.3   TLS_AES_256_GCM_SHA384            253 bit ECDH (X25519)
 Apple Mail (16.0)            TLSv1.2   ECDHE-RSA-AES256-GCM-SHA384       256 bit ECDH (P-256)
 Thunderbird (91.9)           TLSv1.3   TLS_AES_256_GCM_SHA384            253 bit ECDH (X25519)


 Rating (experimental) 

 Rating specs (not complete)  SSL Labs's 'SSL Server Rating Guide' (version 2009q from 2020-01-30)
 Specification documentation  https://github.com/ssllabs/research/wiki/SSL-Server-Rating-Guide
 Protocol Support (weighted)  100 (30)
 Key Exchange     (weighted)  90 (27)
 Cipher Strength  (weighted)  90 (36)
 Final Score                  93
 Overall Grade                A
 Grade cap reasons            Grade capped to A. HSTS is not offered

 Done 2024-07-29 11:35:16 [  52s] -->> yy:8920 (xx) <<--

And the output of openssl s_client:

$ openssl s_client -connect xx:8920
Connecting to yy
CONNECTED(00000003)
depth=2 C=US, ST=New Jersey, L=Jersey City, O=The USERTRUST Network, CN=USERTrust RSA Certification Authority
verify return:1
depth=1 C=AT, O=ZeroSSL, CN=ZeroSSL RSA Domain Secure Site CA
verify return:1
depth=0 CN=xx
verify return:1
---
Certificate chain
 0 s:CN=xx
   i:C=AT, O=ZeroSSL, CN=ZeroSSL RSA Domain Secure Site CA
   a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA384
   v:NotBefore: Jul 17 00:00:00 2024 GMT; NotAfter: Oct 15 23:59:59 2024 GMT
 1 s:C=AT, O=ZeroSSL, CN=ZeroSSL RSA Domain Secure Site CA
   i:C=US, ST=New Jersey, L=Jersey City, O=The USERTRUST Network, CN=USERTrust RSA Certification Authority
   a:PKEY: rsaEncryption, 4096 (bit); sigalg: RSA-SHA384
   v:NotBefore: Jan 30 00:00:00 2020 GMT; NotAfter: Jan 29 23:59:59 2030 GMT
---
Server certificate
..

As you can see, it offers the complete chain.

I've also tested every web-browser and they all work fine.
Except for Android/Google TV.

Any ideas?

Edited by MastaG
Posted (edited)

They may not trust the ZeroSSL RSA Domain Secure Site CA or the root USERTrust RSA Certification Authority. You could try to add the CA manually, if there's an option to install a CA from storage, and see if that resolves it, otherwise switch to the ZeroSSL ECC Domain Secure Site CA/USERTrust ECC Certification Authority issued certificates.

EDIT: Your chain is missing the root certificate, that could also be what's missing. There should be your cert at 0, intermediate at 1, and root at 2.

Edited by Lessaj
  • Like 1
Q-Droid
Posted
7 hours ago, MastaG said:

I've also tested every web-browser and they all work fine.
Except for Android/Google TV.

Any ideas?

Are you trying to force TLS on LAN? How are you trying to force it?

 

Posted (edited)

@Q-Droid
I'm using the generated PFX certificate in Emby server and there is an option you can set to enforce TLS encryption and not allow unencrypted clients.
See my attached picture.
I'm not connecting from LAN, only over WAN.

Now this seems to be a bug in Emby Server where it doesn't seem to serve out the complete chain.
If I use the exact same PFX file in Plex Media Server, I do get the full chain like @Lessajwas mentioning.

Plex Media Server:

$ openssl s_client -connect XX:32400
Connecting to XX
CONNECTED(00000003)
depth=2 C=US, ST=New Jersey, L=Jersey City, O=The USERTRUST Network, CN=USERTrust RSA Certification Authority
verify return:1
depth=1 C=AT, O=ZeroSSL, CN=ZeroSSL RSA Domain Secure Site CA
verify return:1
depth=0 CN=XX
verify return:1
---
Certificate chain
 0 s:CN=XX
   i:C=AT, O=ZeroSSL, CN=ZeroSSL RSA Domain Secure Site CA
   a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA384
   v:NotBefore: Jul 29 00:00:00 2024 GMT; NotAfter: Oct 27 23:59:59 2024 GMT
 1 s:C=AT, O=ZeroSSL, CN=ZeroSSL RSA Domain Secure Site CA
   i:C=US, ST=New Jersey, L=Jersey City, O=The USERTRUST Network, CN=USERTrust RSA Certification Authority
   a:PKEY: rsaEncryption, 4096 (bit); sigalg: RSA-SHA384
   v:NotBefore: Jan 30 00:00:00 2020 GMT; NotAfter: Jan 29 23:59:59 2030 GMT
 2 s:C=US, ST=New Jersey, L=Jersey City, O=The USERTRUST Network, CN=USERTrust RSA Certification Authority
   i:C=GB, ST=Greater Manchester, L=Salford, O=Comodo CA Limited, CN=AAA Certificate Services
   a:PKEY: rsaEncryption, 4096 (bit); sigalg: RSA-SHA384
   v:NotBefore: Mar 12 00:00:00 2019 GMT; NotAfter: Dec 31 23:59:59 2028 GMT
---

Emby:

$ openssl s_client -connect XX:8920
Connecting to XX
CONNECTED(00000003)
depth=2 C=US, ST=New Jersey, L=Jersey City, O=The USERTRUST Network, CN=USERTrust RSA Certification Authority
verify return:1
depth=1 C=AT, O=ZeroSSL, CN=ZeroSSL RSA Domain Secure Site CA
verify return:1
depth=0 CN=XX
verify return:1
---
Certificate chain
 0 s:CN=XX
   i:C=AT, O=ZeroSSL, CN=ZeroSSL RSA Domain Secure Site CA
   a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA384
   v:NotBefore: Jul 29 00:00:00 2024 GMT; NotAfter: Oct 27 23:59:59 2024 GMT
 1 s:C=AT, O=ZeroSSL, CN=ZeroSSL RSA Domain Secure Site CA
   i:C=US, ST=New Jersey, L=Jersey City, O=The USERTRUST Network, CN=USERTrust RSA Certification Authority
   a:PKEY: rsaEncryption, 4096 (bit); sigalg: RSA-SHA384
   v:NotBefore: Jan 30 00:00:00 2020 GMT; NotAfter: Jan 29 23:59:59 2030 GMT
---

The ZeroSSL acme.sh client has an option to generate the PFX file with the --to-pkcs12 --password XXX options.
And the same thing happens when using the PFX generated by the acme.sh client.
Only Plex seems to serve the full chain.
So this is definitely a bug in Emby's http server.

Schermafdruk van 2024-07-30 00-51-41.png

Edited by MastaG
Q-Droid
Posted

WAN only then, good.

It doesn't have to present the full chain during the handshake and many web servers and proxies don't. The CA root is expected to be in the client trust store and the client uses that to validate the chain as long as intermediate certs aren't missing. 

Even so it doesn't hurt anything to include the root. 

Do the same devices and same certs work with plex but not Emby? 

Posted
1 minute ago, Q-Droid said:

WAN only then, good.

It doesn't have to present the full chain during the handshake and many web servers and proxies don't. The CA root is expected to be in the client trust store and the client uses that to validate the chain as long as intermediate certs aren't missing. 

Even so it doesn't hurt anything to include the root. 

Do the same devices and same certs work with plex but not Emby? 

Yes, using Plex on the same Android TV works. And my Plex server is also configured to only allow secure (TLS) connections.

So unless the Plex Android TV client ships its own SSL/TLS client and ca-bundle this must be a issue in the Emby Android TV client.

Also I can't imagine the TV vendor not shipping the ZeroSSL CA. Its firmware is from a couple of months ago and on many forums they recommend the use of ZeroSSL' RSA CA due to its CA being issued way before LetsEncrypt.

For the record, I've also tried it with a new ZeroSSL ECC cert (ec-256) which uses a different chain and I'm getting the same results. It works on the Plex client but not on Emby (Same Android TV device).

Tomorrow I'll bind Emby to localhost and try with Nginx as proxy/ssl-offloader instead.

Will post back the results.

  • Thanks 1
Q-Droid
Posted

Does your pfx file really have the full chain in it? How many certs are in "${HOME}/.acme.sh/mycert/fullchain.cer"?

I'm asking out of curiosity more than anything. The LE certbot creates a fullchain file with only the server and intermediate certs. The root is nowhere in issuing or renewals and I think the ACME standard does not include the trust anchor (root) in the download/deployment. So I'm wondering if PLEX is adding the root on its own.

In reality I don't think this is why your clients are failing to connect because nobody should trust the root cert presented in a TLS handshake. It has to be in the client's keystore and used for the chain validation.

Posted (edited)
40 minutes ago, Q-Droid said:

Does your pfx file really have the full chain in it? How many certs are in "${HOME}/.acme.sh/mycert/fullchain.cer"?

I'm asking out of curiosity more than anything. The LE certbot creates a fullchain file with only the server and intermediate certs. The root is nowhere in issuing or renewals and I think the ACME standard does not include the trust anchor (root) in the download/deployment. So I'm wondering if PLEX is adding the root on its own.

In reality I don't think this is why your clients are failing to connect because nobody should trust the root cert presented in a TLS handshake. It has to be in the client's keystore and used for the chain validation.

Yes, both the fullchain.cer and PFX contain all 3 certificates.
Here you can see the output of all certs when I list them from the PFX which is used by Emby.

mastag@fedora:~/ssd/container_data/emby_data$ openssl pkcs12 -nokeys -info -in cert.pfx
Enter Import Password:
MAC: sha256, Iteration 2048
MAC length: 32, salt length: 8
PKCS7 Encrypted data: PBES2, PBKDF2, AES-256-CBC, Iteration 2048, PRF hmacWithSHA256
Certificate bag
Bag Attributes
    localKeyID: 38 F4 69 A0 5D 7D 41 81 77 A5 6B 50 25 2F A3 93 73 99 19 3D 
subject=CN=XX
issuer=C=AT, O=ZeroSSL, CN=ZeroSSL RSA Domain Secure Site CA
-----BEGIN CERTIFICATE-----
XX
-----END CERTIFICATE-----
Certificate bag
Bag Attributes: <No Attributes>
subject=C=AT, O=ZeroSSL, CN=ZeroSSL RSA Domain Secure Site CA
issuer=C=US, ST=New Jersey, L=Jersey City, O=The USERTRUST Network, CN=USERTrust RSA Certification Authority
-----BEGIN CERTIFICATE-----
XX
-----END CERTIFICATE-----
Certificate bag
Bag Attributes: <No Attributes>
subject=C=US, ST=New Jersey, L=Jersey City, O=The USERTRUST Network, CN=USERTrust RSA Certification Authority
issuer=C=GB, ST=Greater Manchester, L=Salford, O=Comodo CA Limited, CN=AAA Certificate Services
-----BEGIN CERTIFICATE-----
XX
-----END CERTIFICATE-----
PKCS7 Data
Shrouded Keybag: PBES2, PBKDF2, AES-256-CBC, Iteration 2048, PRF hmacWithSHA256

Like I said before, when using the same PFX certificate with Plex Media Server, it will serve the complete chain.
Also the Plex client does work on the same Android TV (with force tls enabled in the server).
It's only Emby's http server which does not.

Edited by MastaG
Q-Droid
Posted

I just remembered something - Emby (via .Net) keeps a cert store and it has caused problems in the past. I wouldn't call it a cache though it seems to behave like one. I have no idea how it works or why it stores certs.

Check under your /config/.dotnet/corefx/cryptography/x509stores/ca to see if there are any files. If there are any stop Emby, delete the files and start it.

 

 

Posted
16 hours ago, Q-Droid said:

I just remembered something - Emby (via .Net) keeps a cert store and it has caused problems in the past. I wouldn't call it a cache though it seems to behave like one. I have no idea how it works or why it stores certs.

Check under your /config/.dotnet/corefx/cryptography/x509stores/ca to see if there are any files. If there are any stop Emby, delete the files and start it.

 

 

Thank you for the suggestion, but the /config directory inside the docker container doesn't have any of these directories.

I just need to find the time to setup nginx as proxy forwarder / ssl offloader.
I'll make sure to use the exact same fullchain.cer.
Then I'll post back my findings.

  • Thanks 1
Posted

So I found the time to setup NGINX for proxy forwarding and ENFORCING TLS by always redirecting.

map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

server {
    listen 8096;
    # Force TLS
    if ($scheme = "http") {
        return 301 https://$host:8920$request_uri;
    }
    listen 8920 ssl http2;
    # listen [::]:443 ssl http2;
    server_name xx;

    access_log /var/log/nginx/emby.access.log;
    error_log /var/log/nginx/emby.error.log;

    # Use Mozilla's guidelines for SSL/TLS settings
    # https://mozilla.github.io/server-side-tls/ssl-config-generator/
    # NOTE: some settings below might be redundant
    ssl_certificate /etc/nginx/acme_cert/fullchain.cer;
    ssl_certificate_key /etc/nginx/acme_cert/xx.key;
    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;
    # intermediate configuration. tweak to your needs.
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;
    ssl_prefer_server_ciphers on;
    ssl_dhparam /etc/pki/tls/certs/dhparam.pem;

    # Add headers to serve security related headers
    # Before enabling Strict-Transport-Security headers please read into this
    # topic first.
    add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always;
    #
    # WARNING: Only add the preload option once you read about
    # the consequences in https://hstspreload.org/. This option
    # will add the domain to a hardcoded list that is shipped
    # in all major browsers and getting removed from this list
    # could take several months.

    location / {
        proxy_pass http://127.0.0.1:8097$request_uri;

        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Port $server_port;
        proxy_set_header X-Forwarded-Scheme $scheme;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Accept-Encoding "";
        proxy_set_header Host $host;

        client_body_buffer_size 512k;
        proxy_read_timeout 86400s;
        client_max_body_size 0;
        proxy_connect_timeout 86400s;
        proxy_send_timeout 86400s;

        # Websocket
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }
}

I've changed the Emby server to listen on port 8097 and I'm using the exact same fullchain.cer and key.

And guess what? It works like a charm on all platforms, including Android (TV).

This means that Emby's builtin http server is DEFINITELY bugged.
It broke somewhere not long ago, but I don't feel like trying out every previous release to figure out which one broke it.

So to sum things up:

- The fullchain.cer generated by ZeroSSL acme.sh client contains all 3 certificates (full chain).


- I've created a PFX using the official acme client:

$ ./acme.sh --home /home/mastag/.acme.sh --domain xx --to-pkcs12 --password 'yy'

  But also manually:

$ openssl pkcs12 -export -inkey "${HOME}/.acme.sh/mycert/mycert.key" -in "${HOME}/.acme.sh/mycert/fullchain.cer" -out "/docker/emby_data/cert.pfx" -password pass:mypassword

In BOTH cases, I can verify that the generated PFX contains all 3 certifcates (full chain) using:

openssl pkcs12 -nokeys -info -in cert.pfx

 

- When I configure Plex Media Server to use the PFX and enforce TLS, it will work on all platforms.
  OpenSSL's s_client will show that Plex Media Server is serving out the full chain, all 3 certificates.

- When I configure Emby Media Server to use the PFX and enforce TLS, it will not work on Android devices.
  My Android smartphone will prompt me to trust/accept the ZeroSSL certificate when I open the Emby application.
  Also OpenSSL's s_client will only show 2 out of the 3 certificates as shown in earlier examples.

- When I use NGINX as proxy forwarder/ssl offloader as shown in the configuration above, it will work on all platforms, including Android TV/Google TV.
  In this case OpenSSL's s_client will show the full chain, all 3 certificates which is served by NGINX.

This means that Emby's builtin http server is definitely messed up.
People shouldn't be setting up their own proxy forwarders.
I hope this bug will be fixed asap.

Q-Droid
Posted

Bug or not you're better off with a proper LB proxy or web server as reverse proxy. You'll have better control over your security, they have a much larger user base, vulnerabilities are discovered sooner and get fixed much faster. Nginx or any of the other big ones is the way to go. Now that you have it working you might as well keep it.

 

  • Like 2
Q-Droid
Posted
On 7/30/2024 at 8:16 AM, MastaG said:
subject=C=US, ST=New Jersey, L=Jersey City, O=The USERTRUST Network, CN=USERTrust RSA Certification Authority
issuer=C=GB, ST=Greater Manchester, L=Salford, O=Comodo CA Limited, CN=AAA Certificate Services

Have you tried Plex and nginx using the self-signed USERTRUST root certificate in your keystore (pfx)  instead of the one that is cross-signed by Comodo? I'm curious if your problematic devices would still work without the much older Comodo root in the chain.

 

Q-Droid
Posted (edited)

@Luke, this thread reveals something @MastaG mentioned earlier and I have been able to verify. Whether it's a bug or by design the Emby server appears to be truncating the certificate chain presented during the TLS handshake.

Technically a TLS termination point (web, proxy, app, etc.) doesn't need to include a Root CA certificate with the chain. And by choice most don't because it's the client that verifies the certs and validates the chain using its own trust store (CA bundle). But this is at the discretion of the admin who configures the server and leaves the Root CA out of the cert list. The servers will normally present what you give them. Emby on the other hand is cutting off the first CA and not presenting the rest even when they're in the keystore. I don't know if it's statically fixed at depth=1 or if it stops at the first CA (x509 Basic Constraints CA:TRUE).

I suspect the OP's problem is some devices don't have the USERTRUST (Sectigo) root in their store but this root also has a cross-signed version which if presented during handshake the client could use either of the Comodo or Microsoft (until 2025) root CAs which have cross-signed them. But Emby is not offering the cross-signed roots when present in the keystore, their depth would be 2 and 3 if allowed.


 

Edited by Q-Droid
Posted
11 hours ago, Q-Droid said:

@Luke, this thread reveals something @MastaG mentioned earlier and I have been able to verify. Whether it's a bug or by design the Emby server appears to be truncating the certificate chain presented during the TLS handshake.

Technically a TLS termination point (web, proxy, app, etc.) doesn't need to include a Root CA certificate with the chain. And by choice most don't because it's the client that verifies the certs and validates the chain using its own trust store (CA bundle). But this is at the discretion of the admin who configures the server and leaves the Root CA out of the cert list. The servers will normally present what you give them. Emby on the other hand is cutting off the first CA and not presenting the rest even when they're in the keystore. I don't know if it's statically fixed at depth=1 or if it stops at the first CA (x509 Basic Constraints CA:TRUE).

I suspect the OP's problem is some devices don't have the USERTRUST (Sectigo) root in their store but this root also has a cross-signed version which if presented during handshake the client could use either of the Comodo or Microsoft (until 2025) root CAs which have cross-signed them. But Emby is not offering the cross-signed roots when present in the keystore, their depth would be 2 and 3 if allowed.


 

Hi, if that's true then that's happening internally within the dotnet runtime. I know I've seen issues in their github repo related to this sort of thing in the past. We'll have to see if there's a way we can configure it preserve the whole chain.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...