Feature Request: Ability to add/use self-signed certificates for HLS streams in Custom Channels source.
I'm attempting to utilize LLHLS streams from docker-wyze-bridge.
When setting LLHLS=true
in my Docker compose, I'm able to access the stream through a browser by IP or DNS hostname (https://nas01.lan:8888/living-room/ or https://172.16.0.15:8888/living-room/) after bypassing the certificate warning (NET::ERR_CERT_AUTHORITY_INVALID)
.
However, I'm unable to view the HLS stream (HTTPS) through Channels:
hostname
#[ERR] Failed to start stream for ch9340: M3U: Could not fetch playlist: nas01.lan:8888: Get "https://nas01.lan:8888/living-room/stream.m3u8": x509: certificate is not valid for any names, but wanted to match nas01.lan
#[HLS] Couldn't generate stream playlist for ch9340-dANY-ip172.16.0.246: M3U: Could not fetch playlist: nas01.lan:8888: Get "https://nas01.lan:8888/living-room/stream.m3u8": x509: certificate is not valid for any names, but wanted to match nas01.lan
IP Address
#[ERR] Failed to start stream for ch9340: M3U: Could not fetch playlist: 172.16.0.15:8888: Get "https://172.16.0.15:8888/living-room/stream.m3u8": x509: cannot validate certificate for 172.16.0.15 because it doesn't contain any IP SANs
#[HLS] Couldn't generate stream playlist for ch9340-dANY-ip172.16.0.246: M3U: Could not fetch playlist: 172.16.0.15:8888: Get "https://172.16.0.15:8888/living-room/stream.m3u8": x509: cannot validate certificate for 172.16.0.15 because it doesn't contain any IP SANs
Note: I'm able to access the (HTTP) stream through Channels when NOT using LLHLS=true
environment variable.
It's my understanding that LLHLS requires a certificate, and I believe that it's automatically generated and stored in /tokens
in the container.
I've tried bridge and host networking in Docker, as well as setting the environment variable WB_HLS_URL=https://nas01.lan:8888/
(although I don't believe this is the intended use case).
Inside the Channels container:
# curl -v https://172.16.0.15:8888/living-room/
* Trying 172.16.0.15:8888...
* Connected to 172.16.0.15 (172.16.0.15) port 8888 (#0)
* ALPN: offers h2
* ALPN: offers http/1.1
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: none
* [CONN-0-0][CF-SSL] TLSv1.0 (OUT), TLS header, Certificate Status (22):
* [CONN-0-0][CF-SSL] TLSv1.3 (OUT), TLS handshake, Client hello (1):
* [CONN-0-0][CF-SSL] TLSv1.2 (IN), TLS header, Certificate Status (22):
* [CONN-0-0][CF-SSL] TLSv1.3 (IN), TLS handshake, Server hello (2):
* [CONN-0-0][CF-SSL] TLSv1.2 (IN), TLS header, Finished (20):
* [CONN-0-0][CF-SSL] TLSv1.2 (IN), TLS header, Supplemental data (23):
* [CONN-0-0][CF-SSL] TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* [CONN-0-0][CF-SSL] TLSv1.2 (IN), TLS header, Supplemental data (23):
* [CONN-0-0][CF-SSL] TLSv1.3 (IN), TLS handshake, Certificate (11):
* [CONN-0-0][CF-SSL] TLSv1.2 (OUT), TLS header, Unknown (21):
* [CONN-0-0][CF-SSL] TLSv1.3 (OUT), TLS alert, unknown CA (560):
* SSL certificate problem: self-signed certificate
* Closing connection 0
curl: (60) SSL certificate problem: self-signed certificate
More details here: https://curl.se/docs/sslcerts.html
curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
I then copied and installed the certificates from the wyze bridge container to the channels container, per the recommendation in the issue that I created.
admin@nas01:/volume1/config/wyze/tokens$ cp hls_server.crt /volume1/config/channels/data/
admin@nas01:/volume1/config/channels/data$ sudo chown root:root hls_server.crt && sudo chmod 644 hls_server.crt
Added bind mount and recreated the container.
volumes:
- /volume1/config/channels/data/hls_server.crt:/usr/local/share/ca-certificates/hls_server.crt
Open console for Channels with Portainer:
ls -l /etc/ssl/certs/ca-certificates.crt
-rw-r--r-- 1 root root 211749 Jan 16 16:21 ca-certificates.crt`
update-ca-certificates
ls -l /etc/ssl/certs/ca-certificates.crt
-rw-r--r-- 1 root root 213052 Feb 19 23:35 ca-certificates.crt
lrwxrwxrwx 1 root root 47 Feb 19 23:35 ca-cert-hls_server.pem -> /usr/local/share/ca-certificates/hls_server.crt
ca-certificates.crt
file did update, and the hls_server.pem
file is now installed.
Ran curl inside channels container again:
# curl -v https://172.16.0.15:8888/living-room/
* Trying 172.16.0.15:8888...
* Connected to 172.16.0.15 (172.16.0.15) port 8888 (#0)
* ALPN: offers h2
* ALPN: offers http/1.1
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: none
* [CONN-0-0][CF-SSL] TLSv1.0 (OUT), TLS header, Certificate Status (22):
* [CONN-0-0][CF-SSL] TLSv1.3 (OUT), TLS handshake, Client hello (1):
* [CONN-0-0][CF-SSL] TLSv1.2 (IN), TLS header, Certificate Status (22):
* [CONN-0-0][CF-SSL] TLSv1.3 (IN), TLS handshake, Server hello (2):
* [CONN-0-0][CF-SSL] TLSv1.2 (IN), TLS header, Finished (20):
* [CONN-0-0][CF-SSL] TLSv1.2 (IN), TLS header, Supplemental data (23):
* [CONN-0-0][CF-SSL] TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* [CONN-0-0][CF-SSL] TLSv1.2 (IN), TLS header, Supplemental data (23):
* [CONN-0-0][CF-SSL] TLSv1.3 (IN), TLS handshake, Certificate (11):
* [CONN-0-0][CF-SSL] TLSv1.2 (IN), TLS header, Supplemental data (23):
* [CONN-0-0][CF-SSL] TLSv1.3 (IN), TLS handshake, CERT verify (15):
* [CONN-0-0][CF-SSL] TLSv1.2 (IN), TLS header, Supplemental data (23):
* [CONN-0-0][CF-SSL] TLSv1.3 (IN), TLS handshake, Finished (20):
* [CONN-0-0][CF-SSL] TLSv1.2 (OUT), TLS header, Finished (20):
* [CONN-0-0][CF-SSL] TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* [CONN-0-0][CF-SSL] TLSv1.2 (OUT), TLS header, Supplemental data (23):
* [CONN-0-0][CF-SSL] TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256
* ALPN: server accepted h2
* Server certificate:
* subject: C=US; ST=WA; L=Kirkland; O=WYZE BRIDGE; CN=wyze-bridge
* start date: Feb 20 04:32:14 2023 GMT
* expire date: Feb 17 04:32:14 2033 GMT
* SSL: certificate subject name 'wyze-bridge' does not match target host name '172.16.0.15'
* Closing connection 0
[12:05 AM]
continued:
* [CONN-0-0][CF-SSL] TLSv1.2 (IN), TLS header, Supplemental data (23):
* [CONN-0-0][CF-SSL] TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* [CONN-0-0][CF-SSL] TLSv1.2 (OUT), TLS header, Supplemental data (23):
* [CONN-0-0][CF-SSL] TLSv1.3 (OUT), TLS alert, close notify (256):
curl: (60) SSL: certificate subject name 'wyze-bridge' does not match target host name '172.16.0.15'
More details here: https://curl.se/docs/sslcerts.html
Created a custom DNS for wyze-bridge
pointing to the docker host IP (172.16.0.15) in Pi-hole:
# curl -v https://wyze-bridge:8888/living-room/
* Trying 172.16.0.15:8888...
* Connected to wyze-bridge (172.16.0.15) port 8888 (#0)
* ALPN: offers h2
* ALPN: offers http/1.1
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: none
* [CONN-0-0][CF-SSL] TLSv1.0 (OUT), TLS header, Certificate Status (22):
* [CONN-0-0][CF-SSL] TLSv1.3 (OUT), TLS handshake, Client hello (1):
* [CONN-0-0][CF-SSL] TLSv1.2 (IN), TLS header, Certificate Status (22):
* [CONN-0-0][CF-SSL] TLSv1.3 (IN), TLS handshake, Server hello (2):
* [CONN-0-0][CF-SSL] TLSv1.2 (IN), TLS header, Finished (20):
* [CONN-0-0][CF-SSL] TLSv1.2 (IN), TLS header, Supplemental data (23):
* [CONN-0-0][CF-SSL] TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* [CONN-0-0][CF-SSL] TLSv1.2 (IN), TLS header, Supplemental data (23):
* [CONN-0-0][CF-SSL] TLSv1.3 (IN), TLS handshake, Certificate (11):
* [CONN-0-0][CF-SSL] TLSv1.2 (IN), TLS header, Supplemental data (23):
* [CONN-0-0][CF-SSL] TLSv1.3 (IN), TLS handshake, CERT verify (15):
* [CONN-0-0][CF-SSL] TLSv1.2 (IN), TLS header, Supplemental data (23):
* [CONN-0-0][CF-SSL] TLSv1.3 (IN), TLS handshake, Finished (20):
* [CONN-0-0][CF-SSL] TLSv1.2 (OUT), TLS header, Finished (20):
* [CONN-0-0][CF-SSL] TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* [CONN-0-0][CF-SSL] TLSv1.2 (OUT), TLS header, Supplemental data (23):
* [CONN-0-0][CF-SSL] TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256
* ALPN: server accepted h2
* Server certificate:
* subject: C=US; ST=WA; L=Kirkland; O=WYZE BRIDGE; CN=wyze-bridge
* start date: Feb 20 04:32:14 2023 GMT
* expire date: Feb 17 04:32:14 2033 GMT
* common name: wyze-bridge (matched)
* issuer: C=US; ST=WA; L=Kirkland; O=WYZE BRIDGE; CN=wyze-bridge
* SSL certificate verify ok.
* Using HTTP2, server supports multiplexing
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* [CONN-0-0][CF-SSL] TLSv1.2 (OUT), TLS header, Supplemental data (23):
* [CONN-0-0][CF-SSL] TLSv1.2 (OUT), TLS header, Supplemental data (23):
* [CONN-0-0][CF-SSL] TLSv1.2 (OUT), TLS header, Supplemental data (23):
* h2h3 [:method: GET]
* h2h3 [:path: /living-room/]
* h2h3 [:scheme: https]
* h2h3 [:authority: wyze-bridge:8888]
* h2h3 [user-agent: curl/7.87.0]
* h2h3 [accept: */*]
* Using Stream ID: 1 (easy handle 0x7f117e088a90)
* [CONN-0-0][CF-SSL] TLSv1.2 (OUT), TLS header, Supplemental data (23):
> GET /living-room/ HTTP/2
> Host: wyze-bridge:8888
> user-agent: curl/7.87.0
> accept: */*
>
* [CONN-0-0][CF-SSL] TLSv1.2 (IN), TLS header, Supplemental data (23):
* [CONN-0-0][CF-SSL] TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* [CONN-0-0][CF-SSL] TLSv1.2 (IN), TLS header, Supplemental data (23):
* Connection state changed (MAX_CONCURRENT_STREAMS == 250)!
* [CONN-0-0][CF-SSL] TLSv1.2 (OUT), TLS header, Supplemental data (23):
* [CONN-0-0][CF-SSL] TLSv1.2 (IN), TLS header, Supplemental data (23):
* [CONN-0-0][CF-SSL] TLSv1.2 (IN), TLS header, Supplemental data (23):
* [CONN-0-0][CF-SSL] TLSv1.2 (IN), TLS header, Supplemental data (23):
< HTTP/2 200
< access-control-allow-credentials: true
< access-control-allow-origin: *
< content-type: text/html
< server: rtsp-simple-server
< content-length: 1240
< date: Mon, 20 Feb 2023 06:02:24 GMT
<
* [CONN-0-0][CF-SSL] TLSv1.2 (IN), TLS header, Supplemental data (23):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
html, body {
margin: 0;
padding: 0;
height: 100%;
overflow: hidden;
}
#video {
width: 100%;
height: 100%;
background: black;
}
</style>
</head>
<body>
<video id="video" muted controls autoplay playsinline></video>
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<script>
const create = () => {
const video = document.getElementById('video');
// always prefer hls.js over native HLS.
// this is because some Android versions support native HLS
// but don't support fMP4s.
if (Hls.isSupported()) {
const hls = new Hls({
maxLiveSyncPlaybackRate: 1.5,
});
hls.on(Hls.Events.ERROR, (evt, data) => {
if (data.fatal) {
hls.destroy();
setTimeout(create, 2000);
}
});
hls.loadSource('index.m3u8');
hls.attachMedia(video);
video.play();
} else if (video.canPlayType('application/vnd.apple.mpegurl')) {
// since it's not possible to detect timeout errors in iOS,
// wait for the playlist to be available before starting the stream
fetch('stream.m3u8')
.then(() => {
video.src = 'index.m3u8';
video.play();
});
}
};
window.addEventListener('DOMContentLoaded', create);
</script>
</body>
</html>
* Connection #0 to host wyze-bridge left intact
and the cert seemed to work. However, after updating the M3U with the new URL, https://wyze-bridge:8888/living-room/stream.m3u8
, I receive this message:
x509: certificate relies on legacy Common Name field, use SANs instead
2023/02/20 00:12:13.795140 [HLS] Couldn't generate stream playlist for ch9340-dANY-ip172.16.0.246: M3U: Could not fetch playlist: wyze-bridge:8888: Get "https://wyze-bridge:8888/living-room/stream.m3u8": x509: certificate relies on legacy Common Name field, use SANs instead
Thank you @tmm1 for your help so far with this!