NGINX:送信元IPアドレスでサーバーを振り分けてみる
HTTPリクエストがWebサーバーに到達した際に、特定のソースIPアドレスの場合には、特定の宛先サーバーに振り分けたい、という話はよくあることではないでしょうか。例えば、特定の顧客、または、社内からのアクセスであれば特定のサーバーへのアクセスを許容する、などです。今回はそんな場合のNGINXの設定に関してです。
今回は、送信元IPアドレスでサーバーを振り分けするNGINXの設定に関してです。
以下の内容で進めていきます。
送信元IPアドレスを使ってサーバーを振り分ける
送信元IPアドレスを取得するには、NGINXの変数$remote_addr
を使います。 そして、IPアドレスと振り分け先サーバーとの組み合わせる方法はいくつかありますが、まずは map
ディレクティブを使って実現してみましょう。
なお、今回の前提としてクライアントとNGINXの途中にロードバランサーやプロキシとなるシステムが存在しないこととします。
mapディレクティブを使って振り分けルールを書く
map
での書き方はシンプルで 送信元IPアドレス と 振り分け先となるサーバー情報を記述します。
-
構成 クライアント → NGINXサーバー(10.20.1.102) → 振り分け先サーバー(10.20.1.103:80、10.20.1.103:9001、10.20.1.103:9002)
-
振り分けルール
送信元IPアドレス | 振り分け先サーバー | 振り分け先サーバーで表示するコンテンツ |
---|---|---|
10.20.1.10 | pool_A | Hello NGINX. Welcome Server 1. |
10.20.1.100 | pool_B | Hello NGINX. Welcome Server 2. |
上記以外 | 10.20.1.103:80 | Welcome to nginx! on default-web server. |
-
テスト用のconf
upstream pool_A { server 10.20.1.103:9001; } upstream pool_B { server 10.20.1.103:9002; } map $remote_addr $selected { default 10.20.1.103; 10.20.1.10 pool_A; 10.20.1.100 pool_B; } server { listen 80; location / { add_header X-remoteaddr "remote-addr-test $remote_addr" always; proxy_pass http://$selected/; proxy_http_version 1.1; proxy_set_header Host $http_host; proxy_set_header Connection ""; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
-
テスト結果:送信元IPアドレス 10.20.1.10 の場合 → 変数 $selected には pool_A が設定されたため、pool_A に振り分けられた
[ec2-user@ip-10-20-1-10 ~]$ curl http://10.20.1.102/ Hello NGINX. Welcome Server 1.
-
テスト結果:送信元IPアドレス 10.20.1.100 の場合 → 変数 $selected には pool_B が設定されたため、pool_B に振り分けられた
[ec2-user@ip-10-20-1-100 ~]$ curl http://10.20.1.102/ Hello NGINX. Welcome Server 2.
-
テスト結果:送信元IPアドレス 10.20.1.201 の場合 → 変数 $selected には 10.20.1.103 が設定されたため、10.20.1.103:80 に振り分けられた
ubuntu@ip-10-20-1-201:~$ curl http://10.20.1.102/ Welcome to nginx! on default-web server.
複数の送信元IPアドレスを対象にしたい場合には、map
の正規表現を使って実現します。
mapの正規表現で振り分けルールを書く
-
送信元IPアドレスが沢山ある場合、
~(チルダ)
を使って正規表現を設定することができます。例えば~10.20.1.1[0-9]
であれば、10.20.1.10 から 10.20.1.19 までが対象になります。map $remote_addr $selected { default 10.20.1.103; ~10.20.1.1[0-9] pool_A; 10.20.1.100 pool_B; }
ですが、IPアドレスの正規表現は少し面倒です。 map
の代わりに geo
を使うとCIDRでの指定が可能になり正規表現を使わずに実現できます。
geoディレクティブを使って振り分けルールを書く
送信元IPアドレスと振り分け先となるサーバー情報の組み合わせルールを geo
ディレクティブ で記述します。
-
前述のテスト用のconfの
map
ディレクティブ をgeo
ディレクティブ に置き換えます。 CIDRを使ってIPアドレスを記述する書式になります。geo $remote_addr $selected { default 10.20.1.103; 10.20.1.0/25 pool_A; 10.20.1.201/32 pool_B; }
振り分けルールを別ファイルに外出しする
-
通常は pool_A に振り分け、特定の振り分けルールを別ファイルに記述することもできます。以下のサンプルの geo.conf を修正変更した場合も NGINXの設定のリロードは必要となります。
-
/etc/nginx/conf.d/test.confの抜粋
geo $remote_addr $selected { default pool_A; include geo.conf; }
-
/etc/nginx/geo.conf
10.20.1.201/32 pool_B;
なお、
map
ディレクティブでもinclude
を使って別ファイルに組み合わせルールを外出しすることができます。 -
まとめ
map
ディレクティブを使うことで特定のIPアドレスと振り分け先のサーバー情報のルールを記述するだけで簡単に実現は可能です。ですが、IPアドレスが複数沢山ある場合に、CIDRでIPアドレスを纏めたい場合には geo
ディレクティブを使った方が簡単になります。