Elastic Load Balancerを使用したEC2にIPでHTTPアクセス拒否する方法について

# Elastic Load Balancerを使用したEC2にIPでHTTPアクセス拒否する方法について

初投稿です！
脱オンプレ、AWS歴2ヶ月と新卒気分で若返ったarai@cloudpackです。

先日、ある案件でawsのElastic Load Balancer(以下ELB)を使用した構成で、IPや存在しないドメインでのアクセスは拒否したいという依頼がありました。
Default Virtual Host（※以下DVH）を設定すれば、OKと思っていたのですが、実際に設定してみると、Elastic Load Balancerが”OutOfService”になってしまいました。
色々と試行錯誤し、以下の対応で解決できました。

## 設定内容
##### はじめに以下のような設定を行ってみました。（NG設定例）
〆Name Base VirtualHostを使用
〆VirtualHostで複数のドメインを設定
〆以下、DVHを設定

```bash:httpd.conf
        :
<VirtualHost *:80>
    ServerName dummy
    ServerSignature Off
    <Location />
        Order deny,allow
        Deny from All
    </Location>
</VirtualHost>
        :
```

〆Health Check設定
`Ping Protocol：HTTP
Ping Port：80
Ping Path：/index.html
http://example.com/index.html`

## 動作不具合内容
ELBのHealthCheckでhttp://example.com/index.html の監視を行うと、
"OutofService"となってしまう。

## 原因
ELBからEC2にはIPでアクセスされるので、DVHにアクセスが向いてしまう為、拒否(403 Forbidden)されてしまう。

## 対処方法
###その①　ELB healthcheckをTCP 80の監視設定に変更する
`Ping Protocol：TCP
Ping Port：80`

##### デメリット：
本設定だと、Apacheがダウンやゾンビ状態になった時でも、"InService"と認識したままになる為、
ELBが障害サーバの方へ転送した場合、サービスに影響が出るため、その②orその③の対処方法が良いと思います。

### その②　デフォルトバーチャルホストに、除外設定を組み込む(mod_rewriteで対応)
アクセスログを確認。
ELBからのアクセスログは以下のように出力される。
`172.31.28.233 - - [06/Jun/2014:21:12:47 +0900] "GET /index.html HTTP/1.1" 200 496 "-" "ELB-HealthChecker/1.0"`  
UserAgentが”ELB-HealthChecker/1.0”となっているので、UserAgentで指定し、ELBからのアクセス拒否を除外することが可能！  


```bash:httpd.conf
        :
<VirtualHost *:80>
    ServerName dummy
    ServerSignature Off
    RewriteEngine On   　　　　　　　　　　　　　　　　　　　　　　　　　　　　　   # 追記
    RewriteCond %{HTTP_USER_AGENT} ELB-HealthChecker [NC]　　　　　　　　　  # 追記
    RewriteRule (.*) http://example.com/index.html [R=200,L]              # 追記
    <Location />
        Order deny,allow
        Deny from All
    </Location>
</VirtualHost>
        :
```

## 補足
さらに、社内からのみ限定でElastic IPからのアクセスを許可したい場合は、以下を追記して対応可能です。

```bash:httpd.conf
        :
<VirtualHost *:80>
    ServerName dummy
    ServerSignature Off
    RewriteEngine On
    RewriteCond %{HTTP_USER_AGENT} ELB-HealthChecker [NC]
    RewriteRule (.*) http://example.com/index.html [R=200,L]
    RewriteCond %{REMOTE_ADDR}  ^111\.111\.111\.111$　　　　　　 # 追記(社内Global IP)
    RewriteRule (.*) http://example.com$1 [L]　　　　　　　　　   # 追記
    <Location />
        Order deny,allow
        Deny from All
    </Location>
</VirtualHost>
        :
```

### その③デフォルトバーチャルホストに、除外設定を組み込む(mod_accessで対応)

#### mod_extract_forwardedのインストール

Global IPを引き継いで、EC2にアクセスさせるため、インストールする。
（IPでアクセスされた場合、ELBのHealthCheckのみ200を返させるため必要。）

▼インストール
```yum --enablerepo=epel install mod_extract_forwarded```
▼設定
```vim /etc/httpd/conf.d/mod_extract_forwarded.conf```
設定内容

```bash:mod_extract_forwarded.conf
LoadModule extract_forwarded_module modules/mod_extract_forwarded.so
MEForder refuse,accept
MEFrefuse all
MEFaccept all
```
▼DVH用のDocumentRoot、アクセスファイル作成
```mkdir -p /var/www/vhosts/dvh
touch /var/www/vhosts/dvh/index.html```

```bash:httpd.conf
        :
<VirtualHost *:80>
    DocumentRoot /var/www/vhosts/dvh/　 # 追記
    ServerName dummy
    ServerSignature Off
    <Location />
        Order deny,allow
        Deny from All
        Allow from 172　　　　　　　　　  # 追記
    </Location>
</VirtualHost>
        :
```

## 備考
#### ※ ちなみにSSLをELBに設定している場合については、ELB⇒EC2には、443ではなく、80で通信される為、443用のDefault Virtual Hostは不要！

設定反映は忘れずに・・・
```service httpd graceful```