玄関の鍵を1秒に100回ガチャガチャされたら?APIレート制限で守る「システムの治安」
こんにちは。セキュリティの現場で日々、防御の最前線に立っている者です。
今日は、開発者なら必ず一度は耳にする「レート制限(Rate Limiting)」についてお話しします。「難しそうだな…」と身構える必要はありません。まずは身近な「家の防犯」からイメージしてみましょう。
—
1. なぜ「レート制限」が必要なのか?(泥棒の視点)
あなたが家に住んでいると想像してください。頑丈な玄関ドアと鍵がありますよね。泥棒がその家を狙うとき、どうやって侵入するでしょうか?
窓を割るような派手な方法もありますが、一番手っ取り早いのは「ありとあらゆる鍵のパターンを片っ端から試すこと」です。これをITの世界ではブルートフォース攻撃(総当たり攻撃)と呼びます。
もし、泥棒が1秒間に100回もの猛スピードで鍵をガチャガチャと回し続けたらどうなるでしょう?どんなに頑丈な鍵でも、いつかは開いてしまいますよね。それに、あまりの騒がしさに家主(サーバー)は他の作業ができなくなり、ノイローゼになって倒れてしまいます。これがDoS攻撃(サービス拒否攻撃)です。
レート制限とは、「1分間に鍵を回せるのは最大でも3回まで!」と決めてしまう防犯ルールのことなんです。
—
2. 実装のキモ:Redisを使った「門番」の配置
では、開発現場ではどうやってこの「門番」を配置するのでしょうか。
一番シンプルで強力な方法は、Redisという超高速なデータ置き場を使うことです。
なぜRedisを使うのか? それは「今、この人は何回鍵を回したか?」という情報を、ミリ秒単位で確認できるスピードが必要だからです。
実装のイメージ(擬似コード)
例えば、ユーザーIDごとに「1分間に10回までしかAPIを叩かせない」というルールを作るなら、こんな流れになります。
import redis
Redisサーバーに接続
r = redis.Redis(host=’localhost’, port=6379, db=0)
def check_rate_limit(user_id):
key = f”rate_limit:{user_id}”
# 呼び出し回数をカウントアップ
current_count = r.incr(key)
# 初回アクセスなら、有効期限(1分=60秒)を設定
if current_count == 1:
r.expire(key, 60)
# 10回を超えていたら「拒否」
if current_count > 10:
return False # 門前払い!
return True # 通過OK
この仕組みがあれば、攻撃者がいくら猛スピードでリクエストを送ってきても、11回目からはサーバーが「もう今日は終わりですよ」と門前払いをしてくれるようになります。
—
3. レスポンスヘッダーで「優しさ」を伝える
レート制限をかけるとき、ただエラー(HTTP 429 Too Many Requests)を返すだけでは、ユーザーに対して少し不親切です。
「あとどれくらい待てばいいの?」という情報を、レスポンスヘッダーを使って親切に伝えてあげましょう。
- `X-RateLimit-Limit`: 制限の合計回数
- `X-RateLimit-Remaining`: 残り回数
- `Retry-After`: 次にアクセス可能になるまでの待ち時間(秒)
これらをAPIの戻り値に含めておくことで、正常なユーザー(アプリなど)は「おっと、ちょっとリクエストを控えて待とう」と、自動的に賢い挙動をしてくれるようになります。
—
4. 盲点:IPアドレスだけで制限してはいけない?
初心者の方が陥りやすい罠があります。「IPアドレスだけで制限すればいいよね?」という考えです。
確かにIPアドレスによる制限は基本ですが、これには弱点があります。例えば、大きなオフィスや学校のWi-Fiを使っている人たちは、全員が「同じIPアドレス」を共有しています。一人が悪さをしたせいで、そのWi-Fiを使っている全員が巻き添えを食ってAPIを使えなくなるという悲劇が起こるのです。
防御のベストプラクティス
1. IPアドレス+ユーザーID(または認証トークン)の組み合わせで制限をかける。
2. ログイン前ならIPで制限し、ログイン後ならユーザーIDで制限を切り替える。
3. 重たい処理(検索やファイルアップロードなど)には、より厳しめの制限を設ける。
—
最後に:セキュリティは「いたちごっこ」を楽しむもの
セキュリティの対策に「これさえやれば絶対安心」という魔法はありません。でも、レート制限という「門番」を置くだけで、泥棒があなたのシステムを攻撃するコストは跳ね上がります。
「面倒くさい相手だな」と攻撃者に思わせたら、こちらの勝ちです。
まずは小さなプロジェクトから、Redisを使ったカウント制限を試してみてください。自分の書いたコードがシステムを守る「盾」になる瞬間、きっとエンジニアとしての面白さを感じてもらえるはずですよ。
それでは、また次回の記事でお会いしましょう!安全な開発ライフを!

コメント