5
4

nginxの多段リバースプロキシ環境での各proxy_set_headerの設定

Last updated at Posted at 2024-01-28

はじめに

dockerコンテナでwebサーバを公開する際、いくつかのリバースプロキシを経由することになります。その際、正しくアクセス元のIP(remote_addr)を最後段のバックエンドまで伝えるために、各リバースプロキシとバックエンドの設定(主にproxy_set_header)を整理してみました。

参考↓

こんな感じを想定

多段プロキシ環境でのnginx設定_a.png

インターネットからのアクセス元(remote_addr)
1.ルータのWAN(グローバルIP:153.153.153.153)にhttp://www.hoge.com/でアクセス
2.ルータはポート80を最初のリバースプロキシ(revproxy0)にポートフォワード
3.revproxy0はまずdocker host pcにproxy_pass
4.docker host pcは内部のdockerコンテナに転送
5.dockerコンテナの内部のrevproxy1で受けrevproxy2に転送
6.最終的にrevproxy2はbackendに転送

IPの流れ

図2_a.png

各リバースプロキシの設定

※全てnginxとします。

  • revproxy0(192.168.1.1)
    ルータのポートフォワードを受けdocker host pc(192.168.1.100)に転送する最初のリバースプロキシ
server {
	server_name xxx.hoge.com;
	listen 80;
	location / {
	  proxy_set_header    Host    $host;
	  proxy_set_header    X-Forwarded-Host       $host;
	  proxy_set_header    X-Real-IP    $remote_addr;
	  proxy_set_header    X-Forwarded-For    $remote_addr;
	  proxy_pass	http://192.168.1.100/;
	}
}

  • docker host pc(192.168.1.100)
    dockerを起動していればrevproxy1に転送される。
    ↓dockerでの多段リバースプロキシ環境構築はこちら

  • revproxy1(172.16.0.10)
    dockerコンテナの1番目のリバースプロキシ、revproxy2に転送する。
server {
    server_name  _;
    listen       80;
    location / {
      proxy_set_header Host                   $host;
      proxy_set_header X-Forwarded-Host       $host;
      proxy_set_header X-Real-IP              $remote_addr;
      proxy_set_header X-Forwarded-For        "$http_x_forwarded_for, $realip_remote_addr";
      proxy_pass                              http://revproxy2;
    }
}

  • revproxy2(172.16.0.20)
    dockerコンテナの2番目のリバースプロキシ、backendに転送する。
    revproxy1とはproxy_passが異なるだけ。
server {
    server_name _;
    listen      80;
    location / {
      proxy_set_header Host                   $host;
      proxy_set_header X-Forwarded-Host       $host;
      proxy_set_header X-Real-IP              $remote_addr;
      proxy_set_header X-Forwarded-For        "$http_x_forwarded_for, $realip_remote_addr";
      proxy_pass                              http://backend;
    }
}

  • backend(172.16.1.100)
    最終的にWEBページを表示させるwebサーバ。運用ではwebアプリ(railsなど)になると思うが、検証環境なのでここもdockerコンテナのnginx。
    revproxyと異なるのは後段にproxyする必要がないのでproxy_set_headerの記述が無い。
  server {
    server_name _;
    listen       80;
    set_real_ip_from 192.168.1.1;
    set_real_ip_from proxy1;
    set_real_ip_from proxy2;
    real_ip_header    X-Forwarded-For;
    real_ip_recursive on;
    location / {
      root  /usr/share/nginx/html;
      index index.html;
    }
  }

まとめ

1. ルータから受け取る最初のリバースプロキシ(revproxy0)のX-Forwarded-Forは「$remote_addr」

2. 前段からデータを受け取って後段に流す各リバースプロキシ(revproxy1,revproxy2)のproxy_set_headerはどちらも同じ設定でよい。異なるのはproxy_pass先のみ。

X-Forwarded-For "$http_x_forwarded_for,$realip_remote_addr”;

このようにすると、経由したリバースプロキシがわかる。

↓参考

3. 最終的なbackendには、前段まで経由した各リバースプロキシをset_real_ip_fromで記述する。
docker内のリバースプロキシはdockerホスト名で良いが、最初のリバースプロキシはdocker内でホスト名の解決ができないため、IPアドレスで指定する。
real_ip_recursive onにすることで、remote_addrがバックエンドに伝わる。

    #経由するリバースプロキシをすべて記載
    set_real_ip_from 192.168.1.1;
    set_real_ip_from proxy1;
    set_real_ip_from proxy2;

    real_ip_header    X-Forwarded-For;
    real_ip_recursive on;
5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4