GeekFactory

int128.hatenablog.com

CloudFront→ELB→EC2構成におけるIPアドレスのアクセス制御

AWSでCloudFront → ELB → EC2の構成を採用する場合に、IPアドレスによるアクセス制御を行う方法を説明します。

方法1: EC2上のWebサーバによるアクセス制御

CloudFrontやELBはリクエストを受けると x-forwarded-for ヘッダにクライアントのIPアドレスを付与します。 このヘッダを利用してIPアドレスによるアクセス制御を実現できます。

CloudFrontとELBを組み合わせる場合は下記のようなヘッダを受け取ります。

クライアント
↓
CloudFront
↓ x-forwarded-for: <クライアントのIPアドレス>
ELB
↓ x-forwarded-for: <クライアントのIPアドレス>, <CloudFrontエッジのIPアドレス>
EC2

クライアントがヘッダを偽装した場合も考慮しておきましょう。もし、クライアントが x-forwarded-for ヘッダを付けてアクセスした場合は下記のようになります。

クライアント
↓ x-forwarded-for: <クライアントが付けた内容>
CloudFront
↓ x-forwarded-for: <クライアントが付けた内容>, <クライアントのIPアドレス>
ELB
↓ x-forwarded-for: <クライアントが付けた内容>, <クライアントのIPアドレス>, <CloudFrontエッジのIPアドレス>
EC2

したがって、 x-forwarded-for ヘッダをカンマで区切って右から2番目の要素を取得すると、クライアントのIPアドレスを取り出すことができます。

Apacheを利用している場合は SetEnvIf正規表現を指定してIPアドレスをチェックします。例えば、 10.20.30.40 に対してアクセスを許可するには下記の設定になります。

<Directory "/var/www/html">
  SetEnvIf x-forwarded-for "(:?^| )10\.20\.30\.40, [\d.]+$" permit_staging
  Order Deny,Allow
  Deny from all
  Allow from env=permit_staging
</Directory>

Apache 2.4からはmod_remoteipモジュールが利用できますが、ヘッダの右から2番目の要素といった指定はできないようです。 クライアントがヘッダを偽装するケースを考慮すると、現時点では正規表現が安全と思います。

CloudFrontやELBが付与する x-forwarded-for ヘッダの仕様は下記を参照してください。

docs.aws.amazon.com

docs.aws.amazon.com

方法2: WAFによるアクセス制御

CloudFrontにWAF(Web Application Firewall)のルールをアタッチすることで、IPアドレスによるアクセス制御を実現できます。 ただし、CloudFrontからELBにアクセスできるようにセキュリティグループを開けておく必要があります。 かなり広いIPアドレスブロックを開けておく必要があるため、攻撃者からELBに直接アクセスされるリスクがあります。

docs.aws.amazon.com