AWS Lambda@Edge
AWS Lambda@Edge を使用すると、CloudFront のグローバルエッジロケーション全体でカスタム Node.js 関数を実行できます。このミドルウェアは受信したビューワーリクエストを検証し、実際のクライアント IP を抽出して、オリジンインフラに到達する前に不要なプロキシや VPN トラフィックをブロックします。
実装
この関数は CloudFront の Viewer Request イベントにフックします。イベントオブジェクトから直接クライアント IP を読み取り、ProxyTracer への高速な非同期フェッチを実行して、プロキシが検出された場合は構築された 403 Forbidden レスポンスをユーザーに直接返します。
export const handler = async (event) => {
const request = event.Records[0].cf.request;
// 1. CloudFrontから直接クライアントIPを安全に抽出
const clientIp = request.clientIp;
// ローカルテスト環境またはIPが見つからない場合はパススルー
if (!clientIp) {
return request;
}
try {
// 2. ProxyTracer APIにクエリを実行 (Lambda Node 18以降はネイティブfetchをサポート)
const ptResponse = await fetch(`https://api.proxytracer.com/v1/check/${clientIp}`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${process.env.PROXYTRACER_API_KEY}`
},
// AbortControllerを使用して厳格な500msのタイムアウトを強制
signal: AbortSignal.timeout(500)
});
if (ptResponse.ok) {
const data = await ptResponse.json();
// 3. プロキシが検出された場合は直ちに接続を切断
if (data.proxy === true) {
// カスタムレスポンスを返すことでCloudFrontリクエストをショートサーキット(即時終了)
return {
status: '403',
statusDescription: 'Forbidden',
headers: {
'content-type': [{ key: 'Content-Type', value: 'application/json' }]
},
body: JSON.stringify({ error: "Access Denied: VPN or Proxy detected." })
};
}
}
} catch (error) {
// フェイルオープン: APIがタイムアウトした場合でも稼働率を維持するためトラフィックを許可
console.error('ProxyTracer API Error:', error);
}
// 4. トラフィックは正常です。リクエストオブジェクトを返してオリジンへのルーティングを継続します
return request;
};デプロイ時の注意: CloudFront の仕様上、すべての Lambda@Edge 関数はグローバルにレプリケートされる前に us-east-1 リージョンにデプロイされている必要があります。
最終更新日: