28
28
* SUCH DAMAGE.
29
29
*/
30
30
31
+ #include <sys/stat.h>
32
+
31
33
#include "ns_turn_maps.h"
32
34
#include "ns_turn_ioalib.h"
33
35
#include "ns_turn_ratelimit.h"
34
36
35
37
/////////////////// rate limit //////////////////////////
36
38
37
39
ur_addr_map * rate_limit_map = NULL ;
40
+ ur_addr_map * rate_limit_allowlist_map = NULL ;
41
+
38
42
int ratelimit_window_secs = RATELIMIT_DEFAULT_WINDOW_SECS ;
43
+ time_t last_mtime = 0 ;
44
+
39
45
TURN_MUTEX_DECLARE (rate_limit_main_mutex );
46
+ TURN_MUTEX_DECLARE (rate_limit_allowlist_mutex );
47
+
48
+ void ratelimit_remove_newlines (char * str ) {
49
+ char * src = str ;
50
+ char * dst = str ;
51
+
52
+ while (* src != '\0' ) {
53
+ if (* src != '\r' && * src != '\n' ) {
54
+ * dst ++ = * src ;
55
+ }
56
+ src ++ ;
57
+ }
58
+ * dst = '\0' ;
59
+ }
60
+
61
+ void ratelimit_init_allowlist_map () {
62
+ TURN_MUTEX_INIT (& rate_limit_allowlist_mutex );
63
+ TURN_MUTEX_LOCK (& rate_limit_allowlist_mutex );
64
+
65
+ rate_limit_allowlist_map = (ur_addr_map * )malloc (sizeof (ur_addr_map ));
66
+ ur_addr_map_init (rate_limit_allowlist_map );
67
+
68
+ TURN_MUTEX_UNLOCK (& rate_limit_allowlist_mutex );
69
+ }
70
+
71
+ int ratelimit_is_on_allowlist (const char * allowlist , ioa_addr * addr ) {
72
+ /* If no allowlist provided, return early */
73
+ if (!allowlist ) {
74
+ return 0 ;
75
+ }
76
+ /* Init allow_list map if needed */
77
+ if (rate_limit_allowlist_map == NULL ) {
78
+ ratelimit_init_allowlist_map ();
79
+ }
80
+
81
+ /* Check the mtime of the allow list, do we need to update? */
82
+ struct stat fstat ;
83
+ if (stat (allowlist , & fstat ) == 0 ) {
84
+ if (fstat .st_mtime != last_mtime ) {
85
+ last_mtime = fstat .st_mtime ;
86
+
87
+ FILE * file = NULL ;
88
+ file = fopen (allowlist , "r" );
89
+ if (file != NULL ) {
90
+ char line [1024 ];
91
+
92
+ /* Rebuild map */
93
+ ur_addr_map_clean (rate_limit_allowlist_map );
94
+ ur_addr_map_init (rate_limit_allowlist_map );
95
+
96
+ /* loop over file and add entries */
97
+ while (fgets (line , sizeof (line ) - 1 , file ) != NULL ) {
98
+ if (!line ) {
99
+ break ;
100
+ }
101
+
102
+ ioa_addr new_address ;
103
+ ratelimit_remove_newlines (line );
104
+ if (make_ioa_addr_from_full_string ((const uint8_t * )line , 0 , & new_address ) != 0 ) {
105
+ TURN_LOG_FUNC (TURN_LOG_LEVEL_ERROR , "Malformed address in 401 ratelimit allow list file %s: %s\n" , allowlist , line );
106
+ } else {
107
+ ur_addr_map_put (rate_limit_allowlist_map , & new_address , (ur_addr_map_value_type )1 );
108
+ }
109
+ }
110
+
111
+ if (file ) {
112
+ fclose (file );
113
+ }
114
+ } else {
115
+ TURN_LOG_FUNC (TURN_LOG_LEVEL_ERROR , "Could not open 401 ratelimit allow list file: %s\n" , allowlist );
116
+ }
117
+ }
118
+ }
119
+
120
+ ur_addr_map_value_type ratelimit_ptr = 0 ;
121
+ if (ur_addr_map_get (rate_limit_allowlist_map , addr , & ratelimit_ptr )) {
122
+ return 1 ;
123
+ } else {
124
+ return 0 ;
125
+ }
126
+ }
40
127
41
128
void ratelimit_add_node (ioa_addr * address ) {
42
129
// copy address
@@ -63,7 +150,7 @@ void ratelimit_init_map() {
63
150
TURN_MUTEX_UNLOCK (& rate_limit_main_mutex );
64
151
}
65
152
66
- int ratelimit_is_address_limited (ioa_addr * address , int max_requests , int window_seconds ) {
153
+ int ratelimit_is_address_limited (ioa_addr * address , int max_requests , int window_seconds , const char * allowlist ) {
67
154
/* Housekeeping, prune the map when ADDR_MAP_SIZE is hit and delete expired items */
68
155
turn_time_t current_time = turn_time ();
69
156
@@ -87,7 +174,6 @@ int ratelimit_is_address_limited(ioa_addr *address, int max_requests, int window
87
174
addr_set_port (address_new , 0 );
88
175
89
176
if (ur_addr_map_get (rate_limit_map , address_new , & ratelimit_ptr )) {
90
- free (address_new );
91
177
ratelimit_entry * rateLimitEntry = (ratelimit_entry * )(void * )(ur_map_value_type )ratelimit_ptr ;
92
178
TURN_MUTEX_LOCK (& (rateLimitEntry -> mutex ));
93
179
@@ -96,15 +182,25 @@ int ratelimit_is_address_limited(ioa_addr *address, int max_requests, int window
96
182
rateLimitEntry -> request_count = 1 ;
97
183
rateLimitEntry -> last_request_time = current_time ;
98
184
TURN_MUTEX_UNLOCK (& (rateLimitEntry -> mutex ));
185
+ free (address_new );
99
186
return 0 ;
100
187
} else if (rateLimitEntry -> request_count < max_requests ) {
101
188
/* Check if request count is below requests per window; increment the count */
102
189
if (rateLimitEntry -> request_count < UINT32_MAX )
103
190
rateLimitEntry -> request_count ++ ;
104
191
rateLimitEntry -> last_request_time = current_time ;
105
192
TURN_MUTEX_UNLOCK (& (rateLimitEntry -> mutex ));
193
+ free (address_new );
106
194
return 0 ;
107
195
} else {
196
+ /* Before ratelimit, check allow list */
197
+ if (ratelimit_is_on_allowlist (allowlist , address_new )) {
198
+ free (address_new );
199
+ TURN_MUTEX_UNLOCK (& (rateLimitEntry -> mutex ));
200
+ return 0 ;
201
+ }
202
+
203
+ free (address_new );
108
204
/* Request is outside of defined window and count, request is ratelimited */
109
205
if (rateLimitEntry -> request_count < UINT32_MAX )
110
206
rateLimitEntry -> request_count ++ ;
0 commit comments