Rate limiting is a crucial defense method against service misuse. The Halon platform implements this in a global rate controlling service called rated
. It handles rate limiting for all processes (HSL contexts), based on an "items per time interval" algorithm. Our implementation features a sliding rate limit (in contrast to leaking bucket; which has a fixed output rate regardless of exactly when the rate was exceeded).
Implementation
The rate() function takes up to five arguments, the last one is for the optional array. For each defined namespace you can have multiple entries and if the count value is greater than zero it will increase the rate by one for each time the function is called with the same arguments. The function will return true
as long as the rate()
call interval is less than its rate limit, but false
when exceeded.
rate(namespace, entry, count, interval[, options])
You can use this function in use cases like
- Limit bulk / spam outbreaks from specific senders or authenticated users
- Prevent brute-force attacks against any type of SASL AUTH mechanism
- Service abuse control
Here's an example how you can limit how many suspicious messages a authenticated user can send per day.
// increase, and reject if exceeded
if ($is_spam)
if (rate("spammers", $senderip, 100, 86400) == false)
Reject("You may only send 100 suspicious messages per day");
Or if you want to check if a specific namespace and entry has exceeded the limit
// get the rate limit number, without increasing
if (rate("failed-login:saslusername", $saslusername, 0, 60) >= 3)
Reject("Too many failed logins");
Rate limits may be read and cleared using the REST API.
Clustering
Rate limits are synchronized in the cluster if a HMAC-SHA1 key is specified on the Configuration > Server > Settings page. The protocol is based on UDP and uses port 13131. In terms of security it may be wise to only activate this feature on local networks, as the HMAC-SHA1 only serves as a packet-authenticity firewall. It does not provide encryption nor protect against replay attacks. It should probably be protected by other means such as a VPN tunnel or psychical security (DMZ).
Performance
The rate limits performance is roughly O(log N + log M) and lookups are currently implemented as a C++ std::multimap.
Management
Under the Operations -> Activity -> Rate limiting page you can find all rates that have been registered by the rate() function. It's possible to search for a specific namespace, entry and only show rates that have exceeded a threshold. In this view you can also delete rates to reset the counter.
Column | Description |
Namespace | The namespace or "bucket". |
Entry | The name of the rate limit entry. |
See tables below | |
Rate | count divided by the interval . |
Interval | The time between first and last count. |
Most recent | When a count was last added to this entry. |
Cluster
If All hosts is selected under the Host selector. The rate limit may or may not be synchronized.
Synchronized
Column | Description |
Count | The maximum count a single node has; this should preferable be the same on all nodes. |
Min | If shown, it is the lowest count a single node has. |
Non-synchronized
Column | Description |
Same as for synchronized | |
Sum | The total sum of all count values on all nodes. |
Single node
If a node is selected under the Host selector.
Column | Description |
Count | The count this node has. |
Local count | If shown, the count created on this node (otherwise the same as Count). |
Comments
0 comments
Article is closed for comments.