はじめに
以前こちらの記事にて、セキュリティ強化のためリクエストの検証を行いました。これにより LINE のサーバー以外からの API コールでは Lambda の処理がエラー終了するようになりました。しかし依然として API Gateway へのリクエストは無制限に可能であるため、DDoS 攻撃を受けると API Gateway の料金および Lambda の料金が増大してしまいます。
そこで今回は API Gateway にコール数制限を設定し、また万が一 DDoS 攻撃を受けた場合に気がつけるように通知を設定していきたいと思います。
手順
API Gateway にコール制限を設定する
マネジメントコンソールから設定します。
API Gateway コンソールから、対象の API > ステージを開き、設定タブを開きます。
スロットリングの有効化にチェックを入れ、レートを1リクエスト/秒、バーストを2リクエスト/秒に設定します。
各パラメータの意味は以下の通りです。
- レート:1秒あたりのリクエスト数
- バースト:バーストとして一時的に許容されるリクエスト数
こちらトークンバケットアルゴリズムと呼ばれており、EBSでも同様のアルゴリズムが採用されています。下記はEBSの例ですが、水道から補充される量がレート、貯蔵できる量がバーストに相当します。
この状態で、一度リクエストを行い、スロットリング設定ができていることを確認します。
以下のシェルを実行します。
for i in `seq 1 10`
do
curl -X POST {API Gatewayのエンドポイント} -H "x-line-signature:hoge" --data "data=hoge"
done
CloudWatch を見ると、「Key throttle limit exceeded ~」というエラーが出ていることがわかります。
サブスクリプションフィルターを作成する
CloudWatch Logs サブスクリプションフィルターの使用の手順に従ってCloudWatchサブスクリプションフィルターを作成します。
関数のコードには下記を設定します。
※事前に通知用のSNSトピックの作成およびサブスクライブ設定を行っていることを前提としています。設定はAmazon SNS 通知の設定を参考にしてください。
※今回は SNS トピック ARN、通知メールの件名は環境変数で設定しています。
alerm_subjectには「【要確認】APIコールの呼び出し回数が異常です。」と設定しました。
import base64
import json
import gzip
import os
import boto3
def lambda_handler(event, context):
data = gzip.decompress(base64.b64decode(event['awslogs']['data']))
data_json = json.loads(data)
events = data_json["logEvents"]
logger.info(json.dumps(events))
for event in events:
try:
sns = boto3.client('sns')
res = sns.publish(
TopicArn = os.environ['sns_topic_arn'],
Subject = os.environ['alerm_subject'],
Message = event['message']
)
except Exception as e:
logger.error(e)
この状態で、もう一度リクエストを行い、スロットリングに応じて通知がされることを確認します。
以下のシェルを実行します。
for i in `seq 1 10`
do
curl -X POST {API Gatewayのエンドポイント} -H "x-line-signature:hoge" --data "data=hoge"
done
狙い通り、メール通知がされました。🎉
おわりに
今回は API Gateway にコール数制限を設定し、また万が一 DDoS 攻撃を受けた場合に気がつけるように通知を設定しました。今回使用したAPI Gateway は私が個人で使用しているものなのでスロットリングの閾値を極端に小さくすることでDDoS対策を行いました。
この記事がどなたかの参考になれば幸いです。
コメント