Browse Source

allow disabling HTTPS validation by using sourceFingerprint (#665)

pull/643/head
aler9 5 years ago
parent
commit
9155bffefb
  1. 20
      internal/core/hls_source.go
  2. 1
      internal/core/path.go
  3. 45
      internal/hls/client.go
  4. 1
      internal/hls/client_test.go
  5. 4
      rtsp-simple-server.yml

20
internal/core/hls_source.go

@ -23,9 +23,10 @@ type hlsSourceParent interface {
} }
type hlsSource struct { type hlsSource struct {
ur string ur string
wg *sync.WaitGroup fingerprint string
parent hlsSourceParent wg *sync.WaitGroup
parent hlsSourceParent
ctx context.Context ctx context.Context
ctxCancel func() ctxCancel func()
@ -34,16 +35,18 @@ type hlsSource struct {
func newHLSSource( func newHLSSource(
parentCtx context.Context, parentCtx context.Context,
ur string, ur string,
fingerprint string,
wg *sync.WaitGroup, wg *sync.WaitGroup,
parent hlsSourceParent) *hlsSource { parent hlsSourceParent) *hlsSource {
ctx, ctxCancel := context.WithCancel(parentCtx) ctx, ctxCancel := context.WithCancel(parentCtx)
s := &hlsSource{ s := &hlsSource{
ur: ur, ur: ur,
wg: wg, fingerprint: fingerprint,
parent: parent, wg: wg,
ctx: ctx, parent: parent,
ctxCancel: ctxCancel, ctx: ctx,
ctxCancel: ctxCancel,
} }
s.Log(logger.Info, "started") s.Log(logger.Info, "started")
@ -141,6 +144,7 @@ func (s *hlsSource) runInner() bool {
c := hls.NewClient( c := hls.NewClient(
s.ur, s.ur,
s.fingerprint,
onTracks, onTracks,
onFrame, onFrame,
s, s,

1
internal/core/path.go

@ -624,6 +624,7 @@ func (pa *path) staticSourceCreate() {
pa.source = newHLSSource( pa.source = newHLSSource(
pa.ctx, pa.ctx,
pa.conf.Source, pa.conf.Source,
pa.conf.SourceFingerprint,
&pa.sourceStaticWg, &pa.sourceStaticWg,
pa) pa)
} }

45
internal/hls/client.go

@ -3,6 +3,9 @@ package hls
import ( import (
"bytes" "bytes"
"context" "context"
"crypto/sha256"
"crypto/tls"
"encoding/hex"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
@ -428,6 +431,7 @@ type Client struct {
ctx context.Context ctx context.Context
ctxCancel func() ctxCancel func()
httpClient *http.Client
urlParsed *url.URL urlParsed *url.URL
lastDownloadTime time.Time lastDownloadTime time.Time
downloadedSegmentURIs []string downloadedSegmentURIs []string
@ -455,19 +459,44 @@ type Client struct {
// NewClient allocates a Client. // NewClient allocates a Client.
func NewClient( func NewClient(
ur string, ur string,
fingerprint string,
onTracks func(*gortsplib.Track, *gortsplib.Track) error, onTracks func(*gortsplib.Track, *gortsplib.Track) error,
onFrame func(bool, []byte), onFrame func(bool, []byte),
parent ClientParent, parent ClientParent,
) *Client { ) *Client {
ctx, ctxCancel := context.WithCancel(context.Background()) 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{ c := &Client{
ur: ur, ur: ur,
onTracks: onTracks, onTracks: onTracks,
onFrame: onFrame, onFrame: onFrame,
parent: parent, parent: parent,
ctx: ctx, ctx: ctx,
ctxCancel: ctxCancel, ctxCancel: ctxCancel,
httpClient: &http.Client{
Transport: &http.Transport{
TLSClientConfig: tlsConfig,
},
},
segmentQueue: newClientSegmentQueue(), segmentQueue: newClientSegmentQueue(),
allocateProcs: make(chan clientAllocateProcsReq), allocateProcs: make(chan clientAllocateProcsReq),
outErr: make(chan error, 1), outErr: make(chan error, 1),
@ -690,7 +719,7 @@ func (c *Client) downloadPlaylist(innerCtx context.Context) (m3u8.Playlist, erro
return nil, err return nil, err
} }
res, err := http.DefaultClient.Do(req) res, err := c.httpClient.Do(req)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -720,7 +749,7 @@ func (c *Client) downloadSegment(innerCtx context.Context, segmentURI string) ([
return nil, err return nil, err
} }
res, err := http.DefaultClient.Do(req) res, err := c.httpClient.Do(req)
if err != nil { if err != nil {
return nil, err return nil, err
} }

1
internal/hls/client_test.go

@ -116,6 +116,7 @@ func TestClient(t *testing.T) {
c := NewClient( c := NewClient(
"http://localhost:5780/stream.m3u8", "http://localhost:5780/stream.m3u8",
"",
onTracks, onTracks,
onFrame, onFrame,
testClientParent{}, testClientParent{},

4
rtsp-simple-server.yml

@ -144,9 +144,9 @@ paths:
# when interacting with old cameras that require it. # when interacting with old cameras that require it.
sourceAnyPortEnable: no 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 # 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: # 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 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 ':' # openssl x509 -in server.crt -noout -fingerprint -sha256 | cut -d "=" -f2 | tr -d ':'

Loading…
Cancel
Save