ELB配下のEC2のうち、1つだけをIPアドレス制限する

月花です。

またAWSでハマってあれやこれややったので備忘録です。

やりたかったけどできなかったこと

ELB配下に複数のEC2インスタンスがあり、うち1つだけをIPアドレス制限する。
セキュリティグループでできると勘違いしていたのだが、実際はELBからEC2の通信を許可している以上、ELBにアクセスできればEC2にアクセスできるため、セキュリティグループの変更では不可能だった。

また、該当のELBにEIPを紐付け、Route53から飛ばすことで、違うURLとはなるが、1基だけIPアドレス制限をしようとしたが、AWSにおいて証明書はELBかCloudFrontにしか結びつかないため、HTTPS接続ができなかった。
図にするとこうなっているためだ。

クライアント <--HTTPS--> ELB(証明書あり) <--HTTP--> EC2(証明書なし)

このためAWSの機構では無理なので、Apacheの設定でどうにか設定した。

Apacheの設定を変更する

実際には.htaccessでやったが、httpd.confでやっても同じことと思われる。

X-Forwarded-For

筆者は全然知らなかったが、こういう名前のHTTPヘッダフィールドが存在する。
内容としては、クライアントのIPアドレスが入っている。
まさに、冒頭のような構成で、実際には負荷分散システムのIPアドレスでアクセスされてしまう際に使われるものだ。
一般的な負荷分散システムであれば、この値を引き渡してくれるらしい。

今回は、この値をホワイトリストとすることで解決した。

CIDR記法と正規表現

さきほどのX-Forwarded-Forの値をホワイトリストとして指定するにあたって、

xxx.xxx.xxx.xxx/26

といった、いわゆるCIDR記法は受け付けてくれない。
なので、このCIDR記法の範囲にあるIPアドレス全てを指定しなければならない。
ところがそれでは億劫なので、正規表現に変換してやる。

筆者は下記のサイトを使って変換した。
d.xenowire.net

このサイトで、許可したい正規表現を作って、それを指定する。

実際に記述する

先程の正規表現を使って、まずはホワイトリストの1件1件を定義する

SetEnvIf X-Forwarded-For "123\.45\.78\.(9[4-9]|[7-9][0-9]|1[0-1][0-9]|12[0-7])" allowed_ip1
SetEnvIf X-Forwarded-For "12\.3\.45\.(6[4-9]|[7-9][0-9]|1[0-1][0-9]|12[0-7])" allowed_ip2

2件あるならばこんな感じ。
「allowed_ip〜」の部分はエイリアスなので、好きな名前をつけよう。

そして、まず全てのアクセスを拒否、次に先程定義したものを許可する。

Order Deny,Allow
Deny from All
Allow from env=allowed_ip1
Allow from env=allowed_ip2

一連の流れとしては、

SetEnvIf X-Forwarded-For "123\.45\.78\.(9[4-9]|[7-9][0-9]|1[0-1][0-9]|12[0-7])" allowed_ip1
SetEnvIf X-Forwarded-For "12\.3\.45\.(6[4-9]|[7-9][0-9]|1[0-1][0-9]|12[0-7])" allowed_ip2
Order Deny,Allow
Deny from All
Allow from env=allowed_ip1
Allow from env=allowed_ip2

こうなる。

今回は.htaccessに書いたので、ディレクトリの指定はしていないが、httpd.confに書くときは、ディレクトリの指定が必要になる場合もある。

おわり。