RATELIMIT module
Admin Guide
Section titled “Admin Guide”Overview
Section titled “Overview”This module implements rate limiting for SIP requests. In contrast to the PIKE module this limits the flow based on a per SIP request type basis and not per source IP. The latest sources allow you to dynamically group several messages into some entities and limit the traffic based on them. The MI interface can be used to change tunables while running OpenSIPS.
This module is also integrated with the OpenSIPS Key-Value Interface, providing support for distributed rate limiting using Redis or Memcached CacheDB backends.
Use Cases
Section titled “Use Cases”Limiting the rate messages are processed on a system directly influences the load. The ratelimit module can be used to protect a single host or to protect an OpenSIPS cluster when run on the dispatching box in front.
Distributed limiting is useful when the rate limit should be performed not only on a specific node, but on the entire platform. The internal limiting data will no longer be kept on each OpenSIPS instance. It will be stored in a distributed Key-Value database and queried by each instance before deciding if a SIP message should be blocked or not.
A sample configuration snippet might look like this:
... if (!rl_check("$rU", "50", "TAILDROP")) { sl_send_reply("503", "Server Unavailable"); exit; };...Upon every incoming request listed above rl_check is invoked and the entity identified by the R-URI user is checked. It returns an OK code if the current per request load is below the configured threshold. If the load is exceeded the function returns an error and an administrator can discard requests with a stateless response.
Static Rate Limiting Algorithms
Section titled “Static Rate Limiting Algorithms”The ratelimit module supports two different static algorithms to be used by rl_check to determine whether a message should be blocked or not.
Tail Drop Algorithm (TAILDROP)
Section titled “Tail Drop Algorithm (TAILDROP)”This is a trivial algorithm that imposes some risks when used in conjunction with long timer intervals. At the start of each interval an internal counter is reset and incremented for each incoming message. Once the counter hits the configured limit rl_check returns an error.
The downside of this algorithm is that it can lead to SIP client synchronization. During a relatively long interval only the first requests (i.e. REGISTERs) would make it through. Following messages (i.e. RE-REGISTERs) will all hit the SIP proxy at the same time when a common Expire timer expired. Other requests will be retransmissed after given time, the same on all devices with the same firmware/by the same vendor.
Random Early Detection Algorithm (RED)
Section titled “Random Early Detection Algorithm (RED)”Random Early Detection tries to circumvent the synchronization problem imposed by the tail drop algorithm by measuring the average load and adapting the drop rate dynamically. When running with the RED algorithm OpenSIPS will return errors to the OpenSIPS routing engine every n’th packet trying to evenly spread the measured load of the last timer interval onto the current interval. As a negative side effect OpenSIPS might drop messages although the limit might not be reached within the interval. Decrease the timer interval if you encounter this.
Network Algorithm (NETWORK)
Section titled “Network Algorithm (NETWORK)”This algorithm relies on information provided by network interfaces. The total amount of bytes waiting to be consumed on all the network interfaces is retrieved once every timer_interval seconds. If the returned amount exceeds the limit specified in the modparam, rl_check returns an error.
Dynamic Rate Limiting Algorithms
Section titled “Dynamic Rate Limiting Algorithms”When running OpenSIPS on different machines, one has to adjust the drop rates for the static algorithms to maintain a sub 100% load average or packets start getting dropped in the network stack. While this is not in itself difficult, it isn’t neither accurate nor trivial: another server taking a notable fraction of the cpu time will require re-tuning the parameters.
While tuning the drop rates from the outside based on a certain factor is possible, having the algorithm run inside ratelimit permits tuning the rates based on internal server parameters and is somewhat more flexible (or it will be when support for external load factors - as opposed to cpu load - is added).
Feedback Algorithm (FEEDBACK)
Section titled “Feedback Algorithm (FEEDBACK)”Using the PID Controller model (see Wikipedia page), the drop rate is adjusted dynamically based on the load factor so that the load factor always drifts towards the specified limit (or setpoint, in PID terms).
As reading the cpu load average is relatively expensive (opening /proc/stat, parsing it, etc), this only happens once every timer_interval seconds and consequently the FEEDBACK value is only at these intervals recomputed. This in turn makes it difficult for the drop rate to adjust quickly. Worst case scenarios are request rates going up/down instantly by thousands - it takes up to 20 seconds for the controller to adapt to the new request rate.
Generally though, as real life request rates drift by less, adapting should happen much faster.
Dependencies
Section titled “Dependencies”OpenSIPS Modules
Section titled “OpenSIPS Modules”The following modules must be loaded before this module:
- No dependencies on other OpenSIPS modules.
External Libraries or Applications
Section titled “External Libraries or Applications”The following libraries or applications must be installed before running OpenSIPS with this module loaded:
- None.
Exported Parameters
Section titled “Exported Parameters”timer_interval (integer)
Section titled “timer_interval (integer)”The initial length of a timer interval in seconds. All amounts of messages have to be divided by this timer to get a messages per second value.
Default value is 10.
...modparam("ratelimit", "timer_interval", 5)...expire_time (integer)
Section titled “expire_time (integer)”This parameter specifies how long a pipe should be kept in memory until deleted.
Default value is 3600.
...modparam("ratelimit", "expire_time", 1800)...hash_size (integer)
Section titled “hash_size (integer)”The size of the hash table internally used to keep the pipes. A larger table is much faster but consumes more memory. The hash size must be a power of 2 number.
Default value is 1024.
...modparam("ratelimit", "hash_size", 512)...default_algorithm (string)
Section titled “default_algorithm (string)”Specifies which algorithm should be assumed in case it isn’t explicitly specified in the rl_check function.
Default value is “TAILDROP”.
...modparam("ratelimit", "default_algorithm", "RED")...cachedb_url (string)
Section titled “cachedb_url (string)”Enables distributed rate limiting and specifies the backend that should be used by the CacheDB interface.
Default value is “disabled”.
...modparam("ratelimit", "cachedb_url", "redis://root:root@127.0.0.1/")...db_prefix (string)
Section titled “db_prefix (string)”Specifies what prefix should be added to the pipe name. This is only used when distributed rate limiting is enabled.
Default value is “rl_pipe_”.
...modparam("ratelimit", "db_prefix", "ratelimit_")...Exported Functions
Section titled “Exported Functions”rl_check(name, limit[, algorithm])
Section titled “rl_check(name, limit[, algorithm])”Check the current request against the pipe identified by name and changes/updates the limit. If no pipe is found, then a new one is created with the specified limit and algorithm, if specified. If the algorithm parameter doesn’t exist, the default one is used.
The method will return an error code if the limit for the matched pipe is reached.
Meaning of the parameters is as follows:
- name - this is the name that identifies the pipe which should be checked. This parameter accepts both strings and pseudovariables.
- limit - this specifies the threshold limit of the pipe. It is strongly related to the algorithm used. This parameter accepts an integer or a pseudovariable. Note that the limit should be specified as per-second, not per-timer_interval.
- algorithm - this is parameter is optional and reffers to the algorithm used to check the pipe. If it is not set, the default value is used. It accepts a string or a pseudovariable.
This function can be used from REQUEST_ROUTE.
... # perform a pipe match for all INVITE methods using RED algorithm if (is_method("INVITE")) { if (!rl_check("pipe_INVITE", "100", "RED")) { sl_send_reply("503", "Server Unavailable"); exit; }; };... # use default algorithm for each different gateway $var(limit) = 10; if (!rl_check("gw_$ru", "$var(limit)")) { sl_send_reply("503", "Server Unavailable"); exit; };...rl_dec_count(name)
Section titled “rl_dec_count(name)”This function decreases a counter that could have been previously increased by rl_check function.
Meaning of the parameters is as follows:
- name - identifies the name of the pipe.
This function can be used from REQUEST_ROUTE.
... if (!rl_check("gw_$ru", "100", "TAILDROP")) { exit; } else { rl_dec_count("gw_$ru"); };...rl_reset_count(name)
Section titled “rl_reset_count(name)”This function resets a counter that could have been previously increased by rl_check function.
Meaning of the parameters is as follows:
- name - identifies the name of the pipe.
This function can be used from REQUEST_ROUTE.
... if (!rl_check("gw_$ru", "100", "TAILDROP")) { exit; } else { rl_reset_count("gw_$ru"); };...Exported MI Functions
Section titled “Exported MI Functions”rl_list
Section titled “rl_list”Lists the parameters and variabiles in the ratelimit module.
Name: rl_list
Parameters:
- pipe - indicates the name of the pipe. This parameter is optional. If it doesn’t exist, all the active pipes are listed. Otherwise only the one specified.
MI FIFO Command Format:
:rl_list:_reply_fifo_file_gw_10.0.0.1_empty_line_:rl_list:_reply_fifo_file__empty_line_rl_reset_pipe
Section titled “rl_reset_pipe”Resets the counter of a specified pipe.
Name: rl_reset_pipe
Parameters:
- pipe - indicates the name of the pipe whose couter should be reset.
MI FIFO Command Format:
:rl_reset_pipe:_reply_fifo_file_gw_10.0.0.1_empty_line_rl_set_pid
Section titled “rl_set_pid”Sets the PID Controller parameters for the Feedback Algorithm.
Name: rl_set_pid
Parameters:
- ki - the integral parameter.
- kp - the proportional parameter.
- kd - the derivative parameter.
MI FIFO Command Format:
:rl_set_pid:_reply_fifo_file_0.50.50.5_empty_line_rl_get_pid
Section titled “rl_get_pid”Gets the list of in use PID Controller parameters.
Name: rl_get_pid
Parameters: none
MI FIFO Command Format:
:rl_get_pid:_reply_fifo_file__empty_line_Contributors
Section titled “Contributors”By Commit Statistics
Section titled “By Commit Statistics”Top contributors by DevScore(1), authored commits(2) and lines added/removed(3)
| # | Name | DevScore | Commits | Lines++ | Lines— |
|---|---|---|---|---|---|
| 1. | Razvan Crainea (@razvancrainea) | 78 | 17 | 2212 | 2529 |
| 2. | Ovidiu Sas (@ovidiusas) | 41 | 17 | 2503 | 66 |
| 3. | Bogdan-Andrei Iancu (@bogdan-iancu) | 18 | 15 | 76 | 73 |
| 4. | Stefan Darius (@dariusstefan) | 14 | 5 | 658 | 136 |
| 5. | Daniel-Constantin Mierla (@miconda) | 9 | 7 | 24 | 18 |
| 6. | Henning Westerholt (@henningw) | 4 | 2 | 16 | 14 |
| 7. | Arnaud Boussus | 3 | 1 | 46 | 15 |
| 8. | Sergio Gutierrez | 3 | 1 | 8 | 8 |
| 9. | Stanislaw Pitucha | 3 | 1 | 7 | 1 |
| 10. | Bill Hau | 3 | 1 | 3 | 3 |
All remaining contributors: Konstantin Bokarius, Vlad Paiu (@vladpaiu), Walter Doekes (@wdoekes), Edson Gellert Schubert.
(1) DevScore = author_commits + author_lines_added / (project_lines_added / project_commits) + author_lines_deleted / (project_lines_deleted / project_commits)
(2) including any documentation-related commits, excluding merge commits
(3) ignoring whitespace edits, renamed files and auto-generated files
By Commit Activity
Section titled “By Commit Activity”| # | Name | Commit Activity |
|---|---|---|
| 1. | Stefan Darius (@dariusstefan) | Jun 2026 - Jul 2026 |
| 2. | Razvan Crainea (@razvancrainea) | Sep 2011 - Jun 2026 |
| 3. | Bill Hau | Jul 2014 - Jul 2014 |
| 4. | Bogdan-Andrei Iancu (@bogdan-iancu) | Feb 2008 - Jan 2013 |
| 5. | Vlad Paiu (@vladpaiu) | Aug 2012 - Aug 2012 |
| 6. | Walter Doekes (@wdoekes) | Apr 2010 - Apr 2010 |
| 7. | Ovidiu Sas (@ovidiusas) | Feb 2008 - Oct 2009 |
| 8. | Stanislaw Pitucha | Oct 2009 - Oct 2009 |
| 9. | Arnaud Boussus | Mar 2009 - Mar 2009 |
| 10. | Sergio Gutierrez | Aug 2008 - Aug 2008 |
All remaining contributors: Henning Westerholt (@henningw), Daniel-Constantin Mierla (@miconda), Konstantin Bokarius, Edson Gellert Schubert.
(1) including any documentation-related commits, excluding merge commits
Documentation
Section titled “Documentation”Contributors
Section titled “Contributors”Last edited by: Razvan Crainea (@razvancrainea), Bogdan-Andrei Iancu (@bogdan-iancu), Walter Doekes (@wdoekes), Arnaud Boussus, Daniel-Constantin Mierla (@miconda), Konstantin Bokarius, Henning Westerholt (@henningw), Ovidiu Sas (@ovidiusas), Edson Gellert Schubert.
License
Section titled “License”All documentation files (i.e. .md extension) are licensed under the Creative Common License 4.0