質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.99%

ELB配下のEC2でnginxのリバースプロキシを使っている環境のみアクセス元IPが取得できない

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 5
  • VIEW 7,803

CyberMergina

score 285

ELB × nginx(リバースproxy) × Nodeサーバーの環境で、Nodeサーバー側のシステムにアクセス元IPアドレスを渡したい。

□ 状態(追記しました)

  • リスナー設定
TCP(80) -> TCP(80)
SSL(443) -> TCP(80)

□ 今分かっていること

  • ELB × nginxの環境で、$remote_addrがELBのアドレスになる
  • ELB側でアクセス元IPアドレスがヘッダーの「X-Forwarded-For」に渡されている
    ということは把握しています。
    リバースプロキシを使用しない場合は「X-Forwarded-For」からアクセス元IPアドレスはとれました。

ですが、nginxでリバースプロキシを使用する場合は「X-Forwarded-For」にもELBのアドレスが入ってます。
(これはnginx側でセットされたのでしょうか・・・)

□ nginxの変数
$remote_addr, $proxy_add_x_forwarded_for にはELBのアドレス
$http_x_forwarded_for は空

何か情報をお持ちの方がいらっしゃいましたら、ご教授願います。
よろしくお願いします。


/etc/nginx/nginx.conf

http {
    include         /etc/nginx/mime.types;
    default_type    application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;


    keepalive_timeout   65;
    types_hash_max_size 2048;

    include /etc/nginx/conf.d/*.conf;
    index   index.html index.htm;

#    set_real_ip_from   10.0.0.0/8;
#    real_ip_header     X-Forwarded-For;

}

/etc/nginx/conf.d/default.conf

server {                                                             
server {
  listen 80 proxy_protocol;
  server_name hoge.hoge.jp;
  proxy_request_buffering off;

  set_real_ip_from XX.XX.0.0/XX; # VPC CIDR
  real_ip_header   proxy_protocol;

  location /demo/ { # デモページ(html)
    proxy_pass http://demo.localhost/;
  }

  location / { # socket.io用のjsファイルを読み込むのに使用します。
    proxy_pass http://0.0.0.0:1000;
  }

  location /socket.io/ { # websocket通信
    proxy_pass http://0.0.0.0:2000;
    proxy_set_header X-Real-IP $proxy_protocol_addr;
    proxy_read_timeout 150;
    proxy_set_header Host $host:$server_port;
    proxy_set_header X-Forwarded-For $proxy_protocol_addr;
    proxy_set_header X-Forwarded-Proto http;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
  }

}

□ 進捗

AWSのELBにProxyProtocolを有効にするような設定が必要?

参考
AWS wiki
How to configure AWS ELB and Nginx for WebSocket protocol? [closed]
Using Proxy Protocol With Nginx

>ProxyProtocolを有効にしました。(追記:2016/02/10 16:28)
恐らくあと少しで解決しそうです・・・!

TaichiYanagiyaさんの案①を参考に設定すると、nginxのログにはアクセス元IPが出てきました!

'$proxy_protocol_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent "$http_referer" ' '"$http_user_agent"';
- - [10/Feb/2016:16:15:01 +0900] "PROXY TCP4 [アクセス元IP] XXX.XXX.XXX.XXX 5602 443" 400 172 "-" "-"

但し、BadRequestが出ています・・・
もう少し調べてみます・・・!

>ProxyProtocolを有効にしました。(追記:2016/02/10 19:21)

ひとまず、現状の設定ファイルの内容に更新しました。
ProxyProtocolを有効にしたことで、Bad Requestが発生しています。

AWSのProxyProtocol使用の前提条件に「プロキシサーバーとロードバランサーの両方で有効になっていること」とありました。
http://blog.serverworks.co.jp/tech/2013/08/01/elb-proxy-protocol/
Nodeサーバー側でも何らかの処理が必要になるのでしょうか・・・?

その方面で検索するとこちらの記事を発見しましたので、調べてみます。

>ProxyProtocolを有効にし、BadRequestは解決。ただ、他のVHと共存できない(追記:2016/02/15 18:04)

  • TCPで通信するVirtualHostのみにした際、BadRequestは解決し、ログファイルにも「"PROXY ..."」ではなく「"GET ..."」という形でログが残るようになっていました

ただ、他にHTTPで通信しているVirtualHost(Server Nameで分けている)が接続できなくなった。

構造は以下の通りになっています。

[ELB1]
 server_name hoge.jp
  HTTPS(443) -> HTTP(80)
  HTTP(80)   -> HTTP(80)
  [nginx]
    root(/var/www/html)

[ELB2]
 server_name node.hoge.jp
  SSL(443) -> TCP(80)
  TCP(80)  -> TCP(80)
  [nginx(Reverce Proxy)]
    / -> 3000port(Nodeサーバー)
    /socket.io/ -> 4000port(WSサーバー)

[ELB3]
 server_name main.hoge.jp
  HTTPS(443) -> HTTP(80)
  HTTP(80)   -> HTTP(80)
  [nginx]
    root(/var/www/main)

※インスタンスは1つ
※現在、最小構成にしているのでProxyサーバー、Appサーバーなど分けていません。

proxy protocolを有効にするとELB1ELB3が接続できなくなります。
(ELBのヘルスチェックで引っかかる)

TCPとHTTPの共存は厳しいのでしょうか・・・?

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+2

default.conf の proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 箇所でヘッダを追加していますので、この設定をはずせばいいです。

という単純な問題ではない?

(2016/02/10 12:40 追記)

ELB で ProxyProtocol を有効にした場合、nginx で listen ディレクティブに proxy_protocol を付ける必要があるようです。
とすると、ELB 80番ポートも HTTP から TCP に変更し、X-Forwarded-For の替わりに ProxyProtocol でアクセス元IPを拾うといいと思います。

(ELBリスナー設定)
    TCP  80 -> TCP 80
    SSL 443 -> TCP 80
    (インスタンス側 80番ポートについて ProxyProtocol を有効にする)

(ELBヘルスチェック設定)
    TCP:80
    (他は任意)

(nginx設定)
server {
    listen 80 proxy_protocol;

    set_real_ip_from   10.0.0.0/8;
    real_ip_header     proxy_protocol;

    (中略)

    location /socket.io/ {
        proxy_pass http://0.0.0.0:2000;
        #proxy_set_header X-Real-IP $remote_addr;    # こちらでもOK?
        proxy_set_header X-Real-IP $proxy_protocol_addr;
        proxy_read_timeout 150;
        proxy_set_header Host $host:$server_port;
        #proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;    # こちらでもOK?
        proxy_set_header X-Forwarded-For $proxy_protocol_addr;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}


参考: How to Configure NGINX to Accept the Proxy Protocol

あるいは、現在の 80番ポートをそのまま利用するのであれば、ProxyProtocol 用に別のポートを用意する方法も考えられます。

(ELBリスナー設定)
    HTTP 80 -> HTTP 80
    SSL 443 -> TCP 8080
    (インスタンス側 8080番ポートについて ProxyProtocol を有効にする)

(ELBヘルスチェック設定)
    HTTP:80
    (他は任意)

(nginx設定)
server {
    listen 80;

    set_real_ip_from   10.0.0.0/8;
    real_ip_header     X-Forwarded-For;

    location / {
        proxy_pass http://0.0.0.0:1000;    # これは通常の HTML?
    }
}

server {
    listen 8080 proxy_protocol;

    set_real_ip_from   10.0.0.0/8;
    real_ip_header     proxy_protocol;

    location /socket.io/ {
        proxy_pass http://0.0.0.0:2000;
        # (他、1つ目の設定と同じ)
    }
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/02/15 16:23

    他の80番でLISTENしているVirtual Hostの設定を消すと、正常に動作しました!

    + access.log
    [アクセス元IP] - - [15/Feb/2016:16:13:51 +0900] "GET / HTTP/1.1" 200 191 "-" "curl/7.44.0" "-"

    + socket.conf
    server {
    listen 80 proxy_protocol;
    server_name hoge.hoge.jp;
    proxy_request_buffering off;

    location / {
    proxy_pass http://0.0.0.0:3000;
    set_real_ip_from XX.XX.0.0/XX;
    real_ip_header proxy_protocol;
    proxy_set_header X-Real-IP $proxy_protocol_addr;
    proxy_read_timeout 150;
    proxy_set_header X-Forwarded-For $proxy_protocol_addr;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    }
    }

    FQDNやサブディレクトリまで入れたパスをみて、
    複数に環境を分けているので、少し整理してみます!!

    キャンセル

  • 2016/02/15 18:50

    ELB1, ELB3 からの接続を 80番以外のポートで待ち受けるしかないと思います。

    キャンセル

  • 2016/02/15 19:00

    > ELB1, ELB3 からの接続を 80番以外のポートで待ち受けるしかないと思います。
    内部のポート番号が重なっていることが原因だったのでしょうか・・・
    ひとまず、ELB2の方を別ポートにしました。

    併せて「セキュリティグループ」にポート番号追加、
    nginxのlistenを修正。

    無事に動作することが確認できました。
    (ELB2の方でも大丈夫ですかね・・・)

    [> takotakot さん
    ご回答いただきありがとうございました。

    [> TaichiYanagiya さん
    ご丁寧に最後までお付き合いいただきありがとうございました。

    (!) 解決策等散らばりすぎたので、別途まとめます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.99%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る