mirror of
https://github.com/aler9/rtsp-simple-server
synced 2025-11-01 03:22:50 +08:00
webrtc, hls: prevent brute-force attacks by waiting before sending responses (#2100)
Some checks reported warnings
lint / code (push) Has been cancelled
lint / mod-tidy (push) Has been cancelled
lint / apidocs (push) Has been cancelled
test / test64 (push) Has been cancelled
test / test32 (push) Has been cancelled
test / test_highlevel (push) Has been cancelled
Some checks reported warnings
lint / code (push) Has been cancelled
lint / mod-tidy (push) Has been cancelled
lint / apidocs (push) Has been cancelled
test / test64 (push) Has been cancelled
test / test32 (push) Has been cancelled
test / test_highlevel (push) Has been cancelled
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
gopath "path"
|
gopath "path"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
|
||||||
@@ -14,6 +15,10 @@ import (
|
|||||||
"github.com/bluenviron/mediamtx/internal/logger"
|
"github.com/bluenviron/mediamtx/internal/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
hlsPauseAfterAuthError = 2 * time.Second
|
||||||
|
)
|
||||||
|
|
||||||
//go:embed hls_index.html
|
//go:embed hls_index.html
|
||||||
var hlsIndex []byte
|
var hlsIndex []byte
|
||||||
|
|
||||||
@@ -166,6 +171,10 @@ func (s *hlsHTTPServer) onRequest(ctx *gin.Context) {
|
|||||||
remoteAddr := net.JoinHostPort(ip, port)
|
remoteAddr := net.JoinHostPort(ip, port)
|
||||||
|
|
||||||
s.Log(logger.Info, "connection %v failed to authenticate: %v", remoteAddr, terr.message)
|
s.Log(logger.Info, "connection %v failed to authenticate: %v", remoteAddr, terr.message)
|
||||||
|
|
||||||
|
// wait some seconds to stop brute force attacks
|
||||||
|
<-time.After(hlsPauseAfterAuthError)
|
||||||
|
|
||||||
ctx.Writer.WriteHeader(http.StatusUnauthorized)
|
ctx.Writer.WriteHeader(http.StatusUnauthorized)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
rtmpConnPauseAfterAuthError = 2 * time.Second
|
rtmpPauseAfterAuthError = 2 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
func pathNameAndQuery(inURL *url.URL) (string, url.Values, string) {
|
func pathNameAndQuery(inURL *url.URL) (string, url.Values, string) {
|
||||||
@@ -367,7 +367,7 @@ func (c *rtmpConn) runRead(ctx context.Context, u *url.URL) error {
|
|||||||
if res.err != nil {
|
if res.err != nil {
|
||||||
if terr, ok := res.err.(*errAuthentication); ok {
|
if terr, ok := res.err.(*errAuthentication); ok {
|
||||||
// wait some seconds to stop brute force attacks
|
// wait some seconds to stop brute force attacks
|
||||||
<-time.After(rtmpConnPauseAfterAuthError)
|
<-time.After(rtmpPauseAfterAuthError)
|
||||||
return terr
|
return terr
|
||||||
}
|
}
|
||||||
return res.err
|
return res.err
|
||||||
@@ -782,7 +782,7 @@ func (c *rtmpConn) runPublish(u *url.URL) error {
|
|||||||
if res.err != nil {
|
if res.err != nil {
|
||||||
if terr, ok := res.err.(*errAuthentication); ok {
|
if terr, ok := res.err.(*errAuthentication); ok {
|
||||||
// wait some seconds to stop brute force attacks
|
// wait some seconds to stop brute force attacks
|
||||||
<-time.After(rtmpConnPauseAfterAuthError)
|
<-time.After(rtmpPauseAfterAuthError)
|
||||||
return terr
|
return terr
|
||||||
}
|
}
|
||||||
return res.err
|
return res.err
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
rtspConnPauseAfterAuthError = 2 * time.Second
|
rtspPauseAfterAuthError = 2 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
type rtspConnParent interface {
|
type rtspConnParent interface {
|
||||||
@@ -204,7 +204,7 @@ func (c *rtspConn) handleAuthError(authErr error) (*base.Response, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// wait some seconds to stop brute force attacks
|
// wait some seconds to stop brute force attacks
|
||||||
<-time.After(rtspConnPauseAfterAuthError)
|
<-time.After(rtspPauseAfterAuthError)
|
||||||
|
|
||||||
return &base.Response{
|
return &base.Response{
|
||||||
StatusCode: base.StatusUnauthorized,
|
StatusCode: base.StatusUnauthorized,
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
@@ -318,6 +319,10 @@ func (s *webRTCHTTPServer) onRequest(ctx *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
s.Log(logger.Info, "connection %v failed to authenticate: %v", remoteAddr, terr.message)
|
s.Log(logger.Info, "connection %v failed to authenticate: %v", remoteAddr, terr.message)
|
||||||
|
|
||||||
|
// wait some seconds to stop brute force attacks
|
||||||
|
<-time.After(webrtcPauseAfterAuthError)
|
||||||
|
|
||||||
ctx.Writer.WriteHeader(http.StatusUnauthorized)
|
ctx.Writer.WriteHeader(http.StatusUnauthorized)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
webrtcPauseAfterAuthError = 2 * time.Second
|
||||||
webrtcHandshakeTimeout = 10 * time.Second
|
webrtcHandshakeTimeout = 10 * time.Second
|
||||||
webrtcTrackGatherTimeout = 2 * time.Second
|
webrtcTrackGatherTimeout = 2 * time.Second
|
||||||
webrtcPayloadMaxSize = 1188 // 1200 - 12 (RTP header)
|
webrtcPayloadMaxSize = 1188 // 1200 - 12 (RTP header)
|
||||||
|
|||||||
@@ -240,8 +240,12 @@ func (s *webRTCSession) runPublish() (int, error) {
|
|||||||
})
|
})
|
||||||
if res.err != nil {
|
if res.err != nil {
|
||||||
if _, ok := res.err.(*errAuthentication); ok {
|
if _, ok := res.err.(*errAuthentication); ok {
|
||||||
|
// wait some seconds to stop brute force attacks
|
||||||
|
<-time.After(webrtcPauseAfterAuthError)
|
||||||
|
|
||||||
return http.StatusUnauthorized, res.err
|
return http.StatusUnauthorized, res.err
|
||||||
}
|
}
|
||||||
|
|
||||||
return http.StatusBadRequest, res.err
|
return http.StatusBadRequest, res.err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -363,11 +367,16 @@ func (s *webRTCSession) runRead() (int, error) {
|
|||||||
})
|
})
|
||||||
if res.err != nil {
|
if res.err != nil {
|
||||||
if _, ok := res.err.(*errAuthentication); ok {
|
if _, ok := res.err.(*errAuthentication); ok {
|
||||||
|
// wait some seconds to stop brute force attacks
|
||||||
|
<-time.After(webrtcPauseAfterAuthError)
|
||||||
|
|
||||||
return http.StatusUnauthorized, res.err
|
return http.StatusUnauthorized, res.err
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.HasPrefix(res.err.Error(), "no one is publishing") {
|
if strings.HasPrefix(res.err.Error(), "no one is publishing") {
|
||||||
return http.StatusNotFound, res.err
|
return http.StatusNotFound, res.err
|
||||||
}
|
}
|
||||||
|
|
||||||
return http.StatusBadRequest, res.err
|
return http.StatusBadRequest, res.err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user