「APIの門番」を強化しよう:DoS攻撃からサービスを守るための「レート制限」入門
こんにちは!セキュリティの世界へようこそ。
皆さんは普段、自分の家をどうやって守っていますか?頑丈な鍵をかけるのはもちろん、怪しい訪問者が来たらインターホン越しに追い返したり、あるいは「今日はもう遅いからまた明日来てね」と丁重にお断りしたりしますよね。
Webサービスにおいて、APIは「家への入り口」です。しかし、インターネット上には、強引にドアをこじ開けようとしたり、一度に何千人分もの注文を同時に送りつけて「店をパンクさせよう」とする迷惑な泥棒(攻撃者)がうろついています。
今回は、そんな攻撃からあなたのサービスを守るための「APIレート制限」について、一緒に紐解いていきましょう!
—
なぜ「制限」が必要なのか?(DoS攻撃の正体)
サービスを提供していると、稀にDoS(Denial of Service:サービス拒否)攻撃というものに遭遇します。これは、攻撃者が短時間に膨大な数のリクエストを送りつけ、サーバーを過労死させる攻撃のことです。
たとえるなら、「1人のお客さんが、1分間に1万回『いらっしゃいませ!』と叫び続け、店員が他の接客をできなくする嫌がらせ」のようなものです。
これを防ぐのが「レート制限(Rate Limiting)」です。これは、店員のルールとして「1分間に注文できるのは1人3回まで!」という制限を設ける仕組みのことですね。
—
現場で使われる「トークンバケット」アルゴリズム
レート制限を実装する際、よく使われるのが「トークンバケット」という考え方です。少し難しそうに聞こえますが、イメージは簡単です。
1. あなたの店の入り口に、「入店チケット(トークン)」が入ったバケツが置いてあります。
2. お客さん(リクエスト)が来たら、バケツからチケットを1枚取って入店します。
3. バケツの中身が空っぽになったら? そう、「今はチケットがないから、また後で来てね!」とお断りするわけです。
4. バケツには一定時間ごとに新しいチケットが自動で補充されます。
これなら、一気に大勢が押し寄せても、チケットがない人は「429 Too Many Requests(リクエストが多すぎます)」というエラーを受け取り、システム全体がダウンするのを防ぐことができます。
—
実装のヒント:Nginxで「門番」を雇おう
サーバーの入り口である「APIゲートウェイ」や「Nginx」などのミドルウェアで、この制限をかけるのが最も効率的です。以下は、Nginxで簡単に実装する例です。
1秒間に1リクエストまで許可し、バケツのサイズを5(一時的なスパイクを許容)にする設定
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=1r/s;
server {
location /api/ {
# 設定した制限を適用
limit_req zone=api_limit burst=5 nodelay;
# 制限を超えたら「429」を返す
limit_req_status 429;
proxy_pass http://backend_server;
}
}
zone=api_limit:10m: どのIPアドレスが何回アクセスしたかを記録するメモ帳(メモリ)を10MB確保します。rate=1r/s: 「1秒間に1回まで」という厳しいルールです。burst=5: 「急に5回くらいなら許してあげる」という、少しだけ優しいバッファです。limit_req_status 429: 制限に引っかかった人に対して、「今は忙しいので後でね」という429エラーをしっかり返します。
—
「429 Too Many Requests」とどう向き合う?
制限に引っかかったユーザーに対して、ただ「エラーです!」と突き放すのは少し不親切ですよね。APIを設計する際は、レスポンスヘッダーに少しだけ情報を添えてあげましょう。
Retry-Afterヘッダー: 「あと何秒待てば再度アクセスできるか」を数字で伝えます。- 例:
Retry-After: 30(あと30秒待ってね)
これだけで、行儀の良いクライアント(正当なアプリなど)は、自動的に待機してから再送してくれるようになります。これが、セキュリティを保ちつつユーザー体験も守るという、プロのエンジニアの心遣いです。
—
一歩ずつ、強固なサービスへ
セキュリティ対策というと「ガチガチに固める」イメージがあるかもしれませんが、実際は「誰を優先し、誰をいなすか」という交通整理に近いものです。
まずは、自分のAPIに「1人何回まで」というルールを設けることから始めてみてください。攻撃者は「抵抗が少ない場所」を好みます。少しの工夫で、あなたのサービスは攻撃者にとって「面倒で、割に合わないターゲット」に変わるはずです。
「難しそうだな」と思ったら、まずは開発環境でレート制限をかけて、自分で429エラーを発生させてみてください。自分の手で門番をコントロールできたとき、きっとセキュリティの面白さが少しだけ分かってくるはずですよ。
それでは、また次の記事でお会いしましょう!安全な開発ライフを。
コメント