forked from External/mediamtx
allow disabling HTTPS validation by using sourceFingerprint (#665)
This commit is contained in:
parent
d30822cb1b
commit
9155bffefb
5 changed files with 53 additions and 18 deletions
|
|
@ -23,9 +23,10 @@ type hlsSourceParent interface {
|
|||
}
|
||||
|
||||
type hlsSource struct {
|
||||
ur string
|
||||
wg *sync.WaitGroup
|
||||
parent hlsSourceParent
|
||||
ur string
|
||||
fingerprint string
|
||||
wg *sync.WaitGroup
|
||||
parent hlsSourceParent
|
||||
|
||||
ctx context.Context
|
||||
ctxCancel func()
|
||||
|
|
@ -34,16 +35,18 @@ type hlsSource struct {
|
|||
func newHLSSource(
|
||||
parentCtx context.Context,
|
||||
ur string,
|
||||
fingerprint string,
|
||||
wg *sync.WaitGroup,
|
||||
parent hlsSourceParent) *hlsSource {
|
||||
ctx, ctxCancel := context.WithCancel(parentCtx)
|
||||
|
||||
s := &hlsSource{
|
||||
ur: ur,
|
||||
wg: wg,
|
||||
parent: parent,
|
||||
ctx: ctx,
|
||||
ctxCancel: ctxCancel,
|
||||
ur: ur,
|
||||
fingerprint: fingerprint,
|
||||
wg: wg,
|
||||
parent: parent,
|
||||
ctx: ctx,
|
||||
ctxCancel: ctxCancel,
|
||||
}
|
||||
|
||||
s.Log(logger.Info, "started")
|
||||
|
|
@ -141,6 +144,7 @@ func (s *hlsSource) runInner() bool {
|
|||
|
||||
c := hls.NewClient(
|
||||
s.ur,
|
||||
s.fingerprint,
|
||||
onTracks,
|
||||
onFrame,
|
||||
s,
|
||||
|
|
|
|||
|
|
@ -624,6 +624,7 @@ func (pa *path) staticSourceCreate() {
|
|||
pa.source = newHLSSource(
|
||||
pa.ctx,
|
||||
pa.conf.Source,
|
||||
pa.conf.SourceFingerprint,
|
||||
&pa.sourceStaticWg,
|
||||
pa)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,9 @@ package hls
|
|||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"crypto/tls"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
|
@ -428,6 +431,7 @@ type Client struct {
|
|||
|
||||
ctx context.Context
|
||||
ctxCancel func()
|
||||
httpClient *http.Client
|
||||
urlParsed *url.URL
|
||||
lastDownloadTime time.Time
|
||||
downloadedSegmentURIs []string
|
||||
|
|
@ -455,19 +459,44 @@ type Client struct {
|
|||
// NewClient allocates a Client.
|
||||
func NewClient(
|
||||
ur string,
|
||||
fingerprint string,
|
||||
onTracks func(*gortsplib.Track, *gortsplib.Track) error,
|
||||
onFrame func(bool, []byte),
|
||||
parent ClientParent,
|
||||
) *Client {
|
||||
ctx, ctxCancel := context.WithCancel(context.Background())
|
||||
|
||||
tlsConfig := &tls.Config{}
|
||||
|
||||
if fingerprint != "" {
|
||||
tlsConfig.InsecureSkipVerify = true
|
||||
tlsConfig.VerifyConnection = func(cs tls.ConnectionState) error {
|
||||
h := sha256.New()
|
||||
h.Write(cs.PeerCertificates[0].Raw)
|
||||
hstr := hex.EncodeToString(h.Sum(nil))
|
||||
fingerprintLower := strings.ToLower(fingerprint)
|
||||
|
||||
if hstr != fingerprintLower {
|
||||
return fmt.Errorf("server fingerprint do not match: expected %s, got %s",
|
||||
fingerprintLower, hstr)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
c := &Client{
|
||||
ur: ur,
|
||||
onTracks: onTracks,
|
||||
onFrame: onFrame,
|
||||
parent: parent,
|
||||
ctx: ctx,
|
||||
ctxCancel: ctxCancel,
|
||||
ur: ur,
|
||||
onTracks: onTracks,
|
||||
onFrame: onFrame,
|
||||
parent: parent,
|
||||
ctx: ctx,
|
||||
ctxCancel: ctxCancel,
|
||||
httpClient: &http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: tlsConfig,
|
||||
},
|
||||
},
|
||||
segmentQueue: newClientSegmentQueue(),
|
||||
allocateProcs: make(chan clientAllocateProcsReq),
|
||||
outErr: make(chan error, 1),
|
||||
|
|
@ -690,7 +719,7 @@ func (c *Client) downloadPlaylist(innerCtx context.Context) (m3u8.Playlist, erro
|
|||
return nil, err
|
||||
}
|
||||
|
||||
res, err := http.DefaultClient.Do(req)
|
||||
res, err := c.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -720,7 +749,7 @@ func (c *Client) downloadSegment(innerCtx context.Context, segmentURI string) ([
|
|||
return nil, err
|
||||
}
|
||||
|
||||
res, err := http.DefaultClient.Do(req)
|
||||
res, err := c.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@ func TestClient(t *testing.T) {
|
|||
|
||||
c := NewClient(
|
||||
"http://localhost:5780/stream.m3u8",
|
||||
"",
|
||||
onTracks,
|
||||
onFrame,
|
||||
testClientParent{},
|
||||
|
|
|
|||
|
|
@ -144,9 +144,9 @@ paths:
|
|||
# when interacting with old cameras that require it.
|
||||
sourceAnyPortEnable: no
|
||||
|
||||
# if the source is a RTSPS URL, and the source certificate is self-signed
|
||||
# if the source is a RTSPS or HTTPS URL, and the source certificate is self-signed
|
||||
# or invalid, you can provide the fingerprint of the certificate in order to
|
||||
# validate it anyway, and at the same time prevent man-in-the-middle attacks.
|
||||
# validate it anyway.
|
||||
# the fingerprint can be obtained by running:
|
||||
# openssl s_client -connect source_ip:source_port </dev/null 2>/dev/null | sed -n '/BEGIN/,/END/p' > server.crt
|
||||
# openssl x509 -in server.crt -noout -fingerprint -sha256 | cut -d "=" -f2 | tr -d ':'
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue