mirror of
				https://github.com/aler9/rtsp-simple-server
				synced 2025-10-31 19:13:22 +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" | ||||
| 	gopath "path" | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/gin-gonic/gin" | ||||
|  | ||||
| @@ -14,6 +15,10 @@ import ( | ||||
| 	"github.com/bluenviron/mediamtx/internal/logger" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	hlsPauseAfterAuthError = 2 * time.Second | ||||
| ) | ||||
|  | ||||
| //go:embed hls_index.html | ||||
| var hlsIndex []byte | ||||
|  | ||||
| @@ -166,6 +171,10 @@ func (s *hlsHTTPServer) onRequest(ctx *gin.Context) { | ||||
| 			remoteAddr := net.JoinHostPort(ip, port) | ||||
|  | ||||
| 			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) | ||||
| 			return | ||||
| 		} | ||||
|   | ||||
| @@ -30,7 +30,7 @@ import ( | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	rtmpConnPauseAfterAuthError = 2 * time.Second | ||||
| 	rtmpPauseAfterAuthError = 2 * time.Second | ||||
| ) | ||||
|  | ||||
| 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 terr, ok := res.err.(*errAuthentication); ok { | ||||
| 			// wait some seconds to stop brute force attacks | ||||
| 			<-time.After(rtmpConnPauseAfterAuthError) | ||||
| 			<-time.After(rtmpPauseAfterAuthError) | ||||
| 			return terr | ||||
| 		} | ||||
| 		return res.err | ||||
| @@ -782,7 +782,7 @@ func (c *rtmpConn) runPublish(u *url.URL) error { | ||||
| 	if res.err != nil { | ||||
| 		if terr, ok := res.err.(*errAuthentication); ok { | ||||
| 			// wait some seconds to stop brute force attacks | ||||
| 			<-time.After(rtmpConnPauseAfterAuthError) | ||||
| 			<-time.After(rtmpPauseAfterAuthError) | ||||
| 			return terr | ||||
| 		} | ||||
| 		return res.err | ||||
|   | ||||
| @@ -17,7 +17,7 @@ import ( | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	rtspConnPauseAfterAuthError = 2 * time.Second | ||||
| 	rtspPauseAfterAuthError = 2 * time.Second | ||||
| ) | ||||
|  | ||||
| type rtspConnParent interface { | ||||
| @@ -204,7 +204,7 @@ func (c *rtspConn) handleAuthError(authErr error) (*base.Response, error) { | ||||
| 	} | ||||
|  | ||||
| 	// wait some seconds to stop brute force attacks | ||||
| 	<-time.After(rtspConnPauseAfterAuthError) | ||||
| 	<-time.After(rtspPauseAfterAuthError) | ||||
|  | ||||
| 	return &base.Response{ | ||||
| 		StatusCode: base.StatusUnauthorized, | ||||
|   | ||||
| @@ -10,6 +10,7 @@ import ( | ||||
| 	"regexp" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/gin-gonic/gin" | ||||
| 	"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) | ||||
|  | ||||
| 				// wait some seconds to stop brute force attacks | ||||
| 				<-time.After(webrtcPauseAfterAuthError) | ||||
|  | ||||
| 				ctx.Writer.WriteHeader(http.StatusUnauthorized) | ||||
| 				return | ||||
| 			} | ||||
|   | ||||
| @@ -23,6 +23,7 @@ import ( | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	webrtcPauseAfterAuthError  = 2 * time.Second | ||||
| 	webrtcHandshakeTimeout     = 10 * time.Second | ||||
| 	webrtcTrackGatherTimeout   = 2 * time.Second | ||||
| 	webrtcPayloadMaxSize       = 1188 // 1200 - 12 (RTP header) | ||||
|   | ||||
| @@ -240,8 +240,12 @@ func (s *webRTCSession) runPublish() (int, error) { | ||||
| 	}) | ||||
| 	if res.err != nil { | ||||
| 		if _, ok := res.err.(*errAuthentication); ok { | ||||
| 			// wait some seconds to stop brute force attacks | ||||
| 			<-time.After(webrtcPauseAfterAuthError) | ||||
|  | ||||
| 			return http.StatusUnauthorized, res.err | ||||
| 		} | ||||
|  | ||||
| 		return http.StatusBadRequest, res.err | ||||
| 	} | ||||
|  | ||||
| @@ -363,11 +367,16 @@ func (s *webRTCSession) runRead() (int, error) { | ||||
| 	}) | ||||
| 	if res.err != nil { | ||||
| 		if _, ok := res.err.(*errAuthentication); ok { | ||||
| 			// wait some seconds to stop brute force attacks | ||||
| 			<-time.After(webrtcPauseAfterAuthError) | ||||
|  | ||||
| 			return http.StatusUnauthorized, res.err | ||||
| 		} | ||||
|  | ||||
| 		if strings.HasPrefix(res.err.Error(), "no one is publishing") { | ||||
| 			return http.StatusNotFound, res.err | ||||
| 		} | ||||
|  | ||||
| 		return http.StatusBadRequest, res.err | ||||
| 	} | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Alessandro Ros
					Alessandro Ros