タケユー・ブログ(旧)

フリーWebエンジニアとして食いつなぐ日々

クライアントのIPによって振り分け先を変える

たとえば、nginxをフロントに使ってるとして、

  • 内部のネットワーク(192.168.0.1/24)からのアクセスをアプリケーションサーバに振り分け
  • それ以外からのアクセスに対して、エラーページ(メンテナンス中のとか)を置いてるサーバに振り分け

するとき、nginxの設定だけで実現可能。

HTTP ProxyModuleRewriteModule を使う。
今回は使ってないが、Geo Moduleを使えば、かなり柔軟な指定ができると思う。

# 設定例
# サブディレクトリで運用するRailsアプリを振り分け
#   http://www.hoge.com/app1
#   http://www.hoge.com/app2
#   http://www.hoge.com/app3
#     →アプリケーションサーバ(192.168.0.11:80, 192.168.0.12:80)に振り分け
#   それ以外
#     →静的ファイルを扱うサーバ(192.168.0.10:80)に振り分け
# ただし、外部からのアクセスについては、パスに関係なく、
# 仮設サーバ(192.168.0.100:80)の /503.cgi に振り分ける
# (メンテナンス中を示す画面とステータスコード503を返すCGIとする)

user nginx;
worker_processes 2;  # コア数にあわせて適当に

error_log /var/log/nginx/error.log;

pid /var/run/nginx.pid;

events {
   use epoll;
   worker_connections  1024;
}

http {
   include                 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"';

   sendfile on;

   tcp_nodelay             on;
   keepalive_timeout       65;
   client_header_timeout   3m;
   client_body_timeout     3m;
   send_timeout            3m;

   # output compression saves bandwidth
   gzip                    on;
   gzip_min_length         1024;
   gzip_buffers            4 8k;
   gzip_http_version       1.0;
   gzip_comp_level         2;
   gzip_proxied            any;
   gzip_types              text/plain text/html text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript application/json text/json text/javascript+json;

   upstream web {
      server 192.168.0.10:80;
   }

   upstream app {
      server 192.168.0.11:80;
      server 192.168.0.12:80;
   }

   server {
      listen     80;
      server_name     www.hoge.com;

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

      client_max_body_size    10m;
      client_header_buffer_size 10k;

      proxy_set_header   X-Real-IP       $remote_addr;
      proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header   Host       $http_host;
      proxy_redirect     false;

      location ~ ^/(app1|app2|app3)(/|$) {
         if ($remote_addr !~ ^192.168.0.\d+$) {
            rewrite ^.*$ /503.cgi break;
            proxy_pass http://192.168.0.100;
         }
         if ($remote_addr ~ ^192.168.0.\d+$) {
            proxy_connect_timeout   90;
            proxy_send_timeout      90;
            proxy_read_timeout      90;
            proxy_pass http://app;
            break;
         }
      }

      location / {
         if ($remote_addr !~ ^192.168.0.\d+$) {
            rewrite ^.*$ /503.cgi break;
            proxy_pass http://192.168.0.100;
         }
         if ($remote_addr ~ ^192.168.0.\d+$) {
            proxy_connect_timeout   90;
            proxy_send_timeout      90;
            proxy_read_timeout      90;
            proxy_pass http://web;
            break;
         }
      }
   }
}

参考
nginx wiki