mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 02:37:10 +00:00 
			
		
		
		
	res_rtp_asterisk.c: Add "seqno" strictrtp option
When networks experience disruptions, there can be large gaps of time between receiving packets. When strictrtp is enabled, this created issues where a flood of packets could come in and be seen as an attack. Another option - seqno - has been added to the strictrtp option that ignores the time interval and goes strictly by sequence number for validity. Change-Id: I8a42b8d193673899c8fc22fe7f98ea87df89be71
This commit is contained in:
		
				
					committed by
					
						 Benjamin Keith Ford
						Benjamin Keith Ford
					
				
			
			
				
	
			
			
			
						parent
						
							aa10d6d5eb
						
					
				
				
					commit
					b11a6643cf
				
			
							
								
								
									
										11
									
								
								CHANGES
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								CHANGES
									
									
									
									
									
								
							| @@ -8,6 +8,17 @@ | ||||
| === | ||||
| ============================================================================== | ||||
|  | ||||
| ------------------------------------------------------------------------------ | ||||
| --- Functionality changes from Asterisk 16.0.0 to Asterisk 16.1.0 ------------ | ||||
| ------------------------------------------------------------------------------ | ||||
|  | ||||
| res_rtp_asterisk | ||||
| ------------------ | ||||
|  * The existing strictrtp option in rtp.conf has a new choice availabe, called | ||||
|    'seqno', which behaves the same way as setting strictrtp to 'yes', but will | ||||
|    ignore the time interval during learning so that bursts of packets can still | ||||
|    trigger learning our source. | ||||
|  | ||||
| ------------------------------------------------------------------------------ | ||||
| --- Functionality changes from Asterisk 15 to Asterisk 16 -------------------- | ||||
| ------------------------------------------------------------------------------ | ||||
|   | ||||
| @@ -31,6 +31,10 @@ rtpend=20000 | ||||
| ; seconds after starting learning mode.  Once learning mode completes the | ||||
| ; current stream is locked in and cannot change until the next | ||||
| ; renegotiation. | ||||
| ; Valid options are "no" to disable strictrtp, "yes" to enable strictrtp, | ||||
| ; and "seqno", which does the same thing as strictrtp=yes, but only checks | ||||
| ; to make sure the sequence number is correct rather than checking the time | ||||
| ; interval as well. | ||||
| ; This option is enabled by default. | ||||
| ; strictrtp=yes | ||||
| ; | ||||
|   | ||||
| @@ -157,6 +157,12 @@ enum strict_rtp_state { | ||||
| 	STRICT_RTP_CLOSED,   /*! Drop all RTP packets not coming from source that was learned */ | ||||
| }; | ||||
|  | ||||
| enum strict_rtp_mode { | ||||
| 	STRICT_RTP_NO = 0,	/*! Don't adhere to any strict RTP rules */ | ||||
| 	STRICT_RTP_YES,		/*! Strict RTP that restricts packets based on time and sequence number */ | ||||
| 	STRICT_RTP_SEQNO,	/*! Strict RTP that restricts packets based on sequence number */ | ||||
| }; | ||||
|  | ||||
| /*! | ||||
|  * \brief Strict RTP learning timeout time in milliseconds | ||||
|  * | ||||
| @@ -166,7 +172,7 @@ enum strict_rtp_state { | ||||
|  */ | ||||
| #define STRICT_RTP_LEARN_TIMEOUT	5000 | ||||
|  | ||||
| #define DEFAULT_STRICT_RTP -1	/*!< Enabled */ | ||||
| #define DEFAULT_STRICT_RTP STRICT_RTP_YES	/*!< Enabled by default */ | ||||
| #define DEFAULT_ICESUPPORT 1 | ||||
|  | ||||
| extern struct ast_srtp_res *res_srtp; | ||||
| @@ -3154,28 +3160,31 @@ static int rtp_learning_rtp_seq_update(struct rtp_learning_info *info, uint16_t | ||||
| 		info->received = ast_tvnow(); | ||||
| 	} | ||||
|  | ||||
| 	switch (info->stream_type) { | ||||
| 	case AST_MEDIA_TYPE_UNKNOWN: | ||||
| 	case AST_MEDIA_TYPE_AUDIO: | ||||
| 		/* | ||||
| 		 * Protect against packet floods by checking that we | ||||
| 		 * received the packet sequence in at least the minimum | ||||
| 		 * allowed time. | ||||
| 		 */ | ||||
| 		if (ast_tvzero(info->received)) { | ||||
| 			info->received = ast_tvnow(); | ||||
| 		} else if (!info->packets | ||||
| 			&& ast_tvdiff_ms(ast_tvnow(), info->received) < learning_min_duration) { | ||||
| 			/* Packet flood; reset */ | ||||
| 			info->packets = learning_min_sequential - 1; | ||||
| 			info->received = ast_tvnow(); | ||||
| 	/* Only check time if strictrtp is set to yes. Otherwise, we only needed to check seqno */ | ||||
| 	if (strictrtp == STRICT_RTP_YES) { | ||||
| 		switch (info->stream_type) { | ||||
| 		case AST_MEDIA_TYPE_UNKNOWN: | ||||
| 		case AST_MEDIA_TYPE_AUDIO: | ||||
| 			/* | ||||
| 			 * Protect against packet floods by checking that we | ||||
| 			 * received the packet sequence in at least the minimum | ||||
| 			 * allowed time. | ||||
| 			 */ | ||||
| 			if (ast_tvzero(info->received)) { | ||||
| 				info->received = ast_tvnow(); | ||||
| 			} else if (!info->packets | ||||
| 				&& ast_tvdiff_ms(ast_tvnow(), info->received) < learning_min_duration) { | ||||
| 				/* Packet flood; reset */ | ||||
| 				info->packets = learning_min_sequential - 1; | ||||
| 				info->received = ast_tvnow(); | ||||
| 			} | ||||
| 			break; | ||||
| 		case AST_MEDIA_TYPE_VIDEO: | ||||
| 		case AST_MEDIA_TYPE_IMAGE: | ||||
| 		case AST_MEDIA_TYPE_TEXT: | ||||
| 		case AST_MEDIA_TYPE_END: | ||||
| 			break; | ||||
| 		} | ||||
| 		break; | ||||
| 	case AST_MEDIA_TYPE_VIDEO: | ||||
| 	case AST_MEDIA_TYPE_IMAGE: | ||||
| 	case AST_MEDIA_TYPE_TEXT: | ||||
| 	case AST_MEDIA_TYPE_END: | ||||
| 		break; | ||||
| 	} | ||||
|  | ||||
| 	info->max_seq = seq; | ||||
| @@ -6736,6 +6745,8 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc | ||||
| 			&& STRICT_RTP_LEARN_TIMEOUT < ast_tvdiff_ms(ast_tvnow(), rtp->rtp_source_learn.start)) { | ||||
| 			ast_verb(4, "%p -- Strict RTP learning complete - Locking on source address %s\n", | ||||
| 				rtp, ast_sockaddr_stringify(&rtp->strict_rtp_address)); | ||||
| 			ast_test_suite_event_notify("STRICT_RTP_LEARN", "Source: %s", | ||||
| 				ast_sockaddr_stringify(&rtp->strict_rtp_address)); | ||||
| 			rtp->strict_rtp_state = STRICT_RTP_CLOSED; | ||||
| 		} else { | ||||
| 			struct ast_sockaddr target_address; | ||||
| @@ -6822,6 +6833,16 @@ static struct ast_frame *ast_rtp_read(struct ast_rtp_instance *instance, int rtc | ||||
| 		} | ||||
| 		ast_debug(1, "%p -- Received RTP packet from %s, dropping due to strict RTP protection.\n", | ||||
| 			rtp, ast_sockaddr_stringify(&addr)); | ||||
| #ifdef TEST_FRAMEWORK | ||||
| 	{ | ||||
| 		static int strict_rtp_test_event = 1; | ||||
| 		if (strict_rtp_test_event) { | ||||
| 			ast_test_suite_event_notify("STRICT_RTP_CLOSED", "Source: %s", | ||||
| 				ast_sockaddr_stringify(&addr)); | ||||
| 			strict_rtp_test_event = 0; /* Only run this event once to prevent possible spam */ | ||||
| 		} | ||||
| 	} | ||||
| #endif | ||||
| 		return &ast_null_frame; | ||||
| 	case STRICT_RTP_OPEN: | ||||
| 		break; | ||||
| @@ -8110,7 +8131,13 @@ static int rtp_reload(int reload) | ||||
| 		}; | ||||
| 	} | ||||
| 	if ((s = ast_variable_retrieve(cfg, "general", "strictrtp"))) { | ||||
| 		strictrtp = ast_true(s); | ||||
| 		if (ast_true(s)) { | ||||
| 			strictrtp = STRICT_RTP_YES; | ||||
| 		} else if (!strcasecmp(s, "seqno")) { | ||||
| 			strictrtp = STRICT_RTP_SEQNO; | ||||
| 		} else { | ||||
| 			strictrtp = STRICT_RTP_NO; | ||||
| 		} | ||||
| 	} | ||||
| 	if ((s = ast_variable_retrieve(cfg, "general", "probation"))) { | ||||
| 		if ((sscanf(s, "%d", &learning_min_sequential) != 1) || learning_min_sequential <= 1) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user