ネットワーク

NGINX:送信元IPアドレスでサーバーを振り分けてみる

HTTPリクエストがWebサーバーに到達した際に、特定のソースIPアドレスの場合には、特定の宛先サーバーに振り分けたい、という話はよくあることではないでしょうか。例えば、特定の顧客、または、社内からのアクセスであれば特定のサーバーへのアクセスを許容する、などです。今回はそんな場合のNGINXの設定に関してです。

今回は、送信元IPアドレスでサーバーを振り分けするNGINXの設定に関してです。

 

以下の内容で進めていきます。

  1.  

1.mapディレクティブを使って振り分けルールを書く

2.mapの正規表現で振り分けルールを書く

3.geoディレクティブを使って振り分けルールを書く

4.振り分けルールを別ファイルに外出しする

 

送信元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ディレクティブを使った方が簡単になります。

この記事に関連する製品・サービス

この記事に関連する記事