diff --git a/internal/conf/path.go b/internal/conf/path.go index b11b2c6b..689fb727 100644 --- a/internal/conf/path.go +++ b/internal/conf/path.go @@ -110,10 +110,6 @@ func (pconf *PathConf) checkAndFillMissing(name string) error { return fmt.Errorf("'%s' is not a valid RTSP URL", pconf.Source) } - if strings.HasPrefix(pconf.Source, "rtsps://") && pconf.SourceFingerprint == "" { - return fmt.Errorf("sourceFingerprint is required with a RTSPS URL") - } - case strings.HasPrefix(pconf.Source, "rtmp://"): if pconf.Regexp != nil { return fmt.Errorf("a path with a regular expression (or path 'all') cannot have a RTMP source; use another path") diff --git a/internal/core/rtsp_source.go b/internal/core/rtsp_source.go index 3fbab4ae..41ed33f9 100644 --- a/internal/core/rtsp_source.go +++ b/internal/core/rtsp_source.go @@ -117,24 +117,28 @@ func (s *rtspSource) run() { func (s *rtspSource) runInner() bool { s.log(logger.Debug, "connecting") + tlsConfig := &tls.Config{} + + if s.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(s.fingerprint) + + if hstr != fingerprintLower { + return fmt.Errorf("server fingerprint do not match: expected %s, got %s", + fingerprintLower, hstr) + } + + return nil + } + } + client := &gortsplib.Client{ - Transport: s.proto.Transport, - TLSConfig: &tls.Config{ - InsecureSkipVerify: true, - VerifyConnection: func(cs tls.ConnectionState) error { - h := sha256.New() - h.Write(cs.PeerCertificates[0].Raw) - hstr := hex.EncodeToString(h.Sum(nil)) - fingerprintLower := strings.ToLower(s.fingerprint) - - if hstr != fingerprintLower { - return fmt.Errorf("server fingerprint do not match: expected %s, got %s", - fingerprintLower, hstr) - } - - return nil - }, - }, + Transport: s.proto.Transport, + TLSConfig: tlsConfig, ReadTimeout: time.Duration(s.readTimeout), WriteTimeout: time.Duration(s.writeTimeout), ReadBufferCount: s.readBufferCount, diff --git a/rtsp-simple-server.yml b/rtsp-simple-server.yml index 74d22b7a..555e8f0e 100644 --- a/rtsp-simple-server.yml +++ b/rtsp-simple-server.yml @@ -144,9 +144,10 @@ paths: # when interacting with old cameras that require it. sourceAnyPortEnable: no - # if the source is an RTSPS URL, the fingerprint of the certificate of the source - # must be provided in order to prevent man-in-the-middle attacks. - # it can be obtained from the source by running: + # if the source is a RTSPS 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. + # the fingerprint can be obtained by running: # openssl s_client -connect source_ip:source_port /dev/null | sed -n '/BEGIN/,/END/p' > server.crt # openssl x509 -in server.crt -noout -fingerprint -sha256 | cut -d "=" -f2 | tr -d ':' sourceFingerprint: