自分の業務でrspamdを使う場面が増えてる。 rspamdはメールのスパム検知などをになってくれるソフトウェアで、postfixなどからmilterとして利用することができる。 最近だとRatelimitモジュールを使ってるのだが、レートリミットの振る舞いについて理解が浅かったので整理した。
rspamdのRatelimitモジュールとは
rspamdではさまざまなモジュール提供しており、Ratelimitモジュールもその一つ。 文字通りレートリミットをかけられる。
ref:https://rspamd.com/doc/modules/ratelimit.html
設定例
この記事では以下のような設定を考える。 rspamd触りたての自分は、この設定は以下のような意味だろうと考えていた。
<制限したいドメイン>について1時間あたり60通送信したらレートリミットがかかる- ただし、5通だけは超過を許容している
この考え方は合っているようで合ってない。 以下もう少し詳しく触れていく。
$ sudo cat /etc/rspamd/local.d/ratelimit.conf
rates {
sample = {
selector = 'rcpts';
key = '<制限したいドメイン>';
bucket = [
{
burst = 5;
rate = "60 / 1h";
},
];
}
Token Bucket Algorithm
前提として Token Bucket Algorithm というものを理解する必要がある。 Ratelimitモジュールでもこのアルゴリズムが採用されており、上記パラメータはこのアルゴリズムで利用されるからである。
Token Bucket Algorithmとはデータの流量を制御する時に採用されるアルゴリズムの一種で、メールに限らずあらゆる帯域制御やレートリミットで採用されている。 大まかなコンセプトとしては「一定時間のデータ転送に制限をかけつつある程度のバースト性を許容する」というもの。 データの送信がある度に消費されるトークンと、トークンを蓄えるバケットを利用して流量を制御する。
具体的には以下のようにして流量制御される。
- 一定時間おきにバケットにトークンが追加される
- ただしバケットが満杯の時は新しいトークンは破棄される
- メッセージが到達すると、バケット内に十分なトークンが残っているかチェック
- バースト分についてはバケット内のトークン数をマイナスにする形で許容されるが、その後はトークンが補充されるまでレートリミットがかけられる
今回の設定だとどうなるか
ここでもう一回設定例をみてみる。
selector = 'rcpts';
key = '<制限したいドメイン>';
bucket = [
{
burst = 5;
rate = "60 / 1h";
},
burstとrateはどちらもToken Bucket Algorithmで使うパラメータである。
このアルゴリズムに当てはめると以下のようになる。
- アルゴリズムの適用対象は宛先が
<制限したいドメイン>の場合とする(それ以外のメールには影響しない) - 1時間で60個のトークンを継続的に補充する(60秒で1トークン)
- バケットの容量は60
- バーストは5なので、一時であればバケット内のトークン数-5にして送信できるが、その後レートリミットがかかる
- レートリミットがかかったらバケット内のトークン数が0以上になるまで解除されない
タイムラインでイメージしてみる
0:00〜1:00の間で考えてみる。 簡略化のためにタイムラインは10分刻みとしている。
10分刻みで考えているのでトークンの補充頻度は10分で10トークンとなる。 この補充頻度に対して、送信量が超過してバケット内のトークン数が0下回った場合、0以上までトークンが補充されるまではレートリミットがかかったままになる。 以下の表だと0:40にburstしたので、0:40〜0:50の間はレートリミットがかかる。 これが解除されるのはトークンが補充されて0以上になる0:50である(0でもバーストはできるので送信可能らしい)。
| 時刻 | 送信されたメール数 | 補充 or 消費されるトークン数 | バケット内のトークン数 | 備考 |
|---|---|---|---|---|
| 00:00 | 0 | 10 補充 / 0 消費 | 60.0 | |
| 00:10 | 40 | 10 補充 / 40 消費 | 30.0 | |
| 00:20 | 10 | 10 補充 / 10 消費 | 30.0 | |
| 00:30 | 15 | 10 補充 / 15 消費 | 25.0 | |
| 00:40 | 45 | 10 補充 / 45 消費 | -10.0 | burst |
| ❌ | - / - | -10.0 から徐々に補充 | ratelimit exceeded | |
| 00:50 | 0 | 10 補充 / 0消費 | 0.0 | ratelimit lifted |
| 01:00 | 0 | 10 補充 / 0 消費 | 10.0 |