ELBを使うと何が困るか
ELBを使ってEC2にアクセスする場合、nginxが認識する直近のアクセス元は全てELBとなります。
従って、アクセスログをみるとアクセスがすべてELBということになったり、IP制限をかけようにもクライアントのIPが取得できなくて困ることがあります。
そういう時にはX-Forwarded-For
を使うといいと言うことがさらっと書いてあることが多いのですが、もう少し細かく記載しておきます。
実際の設定
set_real_ip_from 172.32.10.0/20; # プライベートIPは実際のものを使ってください
set_real_ip_from 172.32.18.0/20; # プライベートIPは実際のものを使ってください
real_ip_header X-Forwarded-For;
real_ip_recursive on;
この設定を追加します。この設定を追加するとset_real_ip_from
で設定したサブネットからのアクセスはX-Forwarded-For
を利用するようになります。real_ip_recursive
をon
にしておくことで、その他のプロキシなどが噛んでいた場合も元々のクライアントのIPが取得できるようになります。recursiveなので再帰的に転送元をたどる設定かと。
set_real_ip_fromにはELBの存在するサブネットを設定しておきます。基本的には複数あると思うので並べて記載すればOKです。
この設定を反映することでaccess.logの$remote_addr
にはELBではなく、実際のユーザーのIPアドレスが記録されるようになります。$http_x_forwarded_for
を使わずともクライアントのIPが記録可能となります。
limit_reqとlimit_con
同一IPからの集中アクセスがある場合も
# limit req
limit_req_zone $binary_remote_addr zone=limit_req_by_ip:10m rate=10r/s;
limit_req_log_level error;
limit_req_status 503;
# limit conn
limit_conn_zone $binary_remote_addr zone=limit_per_ip:10m;
limit_conn_log_level error;
limit_conn_status 503;
このように設定してlocationディレクティブで
location / {
limit_req zone=limit_req_by_ip burst=10;
limit_conn limit_per_ip 5;
}
このように設定します。こうすると同一IPから一秒間に10リクエスト以上、または同一IPから同時に5接続という制限がかかり、制限を超えると503エラーを返します。
これもreal_ip_header
の設定をしていないと、全てELBからのアクセスとなるため、間違ってしまうと不要にエラーを返してしまうことにあります。
調べながら書いたので正しくない箇所もあると思うので指摘あったらいただけると助かります。