使用Nginx实现根据 IP 匹配指定 URL
业务需求
业务和开发同事需要我这边做一条规则,所有访问ip为非上海、广州office外网ip,url为http://test.com/fuck/index.html的请求都跳转到http://test.com/index.html。然后所有在上海和广州office的外网IP访问http://test.com/fuck/index.html依然还是http://test.com/fuck/index.html。这样就可以在生产上做隔离,不影响其他用户的服务。
注:因为目前生产上的Nginx没有做lua支持,所以就无法通过使用lua来实现该需求,也没有安装geoip,所以也无法用模块来支持,只能原生的。
原始的nginx配置
upstreamservice_test{ server127.0.0.1:8080; } server { listen80; server_nametest.com; indexindex.htmlindex.php; root/tmp/test.com; error_page404http://test.com/404.html; error_page502http://test.com/502.html; error_page500http://test.com/500.html; location~*\.(gif|jpg|jpeg|png|css|js|ico|txt|svg|woff|ttf|eot)$ { rewrite^(.*)$/static$1break; root/tmp/test.com;# expires1d; } location~*\.(html|htm)$ { rewrite^(.*)$/static$1break; roo/tmp/test.com;# expires900s; } location/{ proxy_passhttp://service_test; include/opt/conf/nginx/proxy.conf; }
修改后的Nginx配置
upstreamservice_test{ server127.0.0.1:8080; } server { listen80; server_nametest.com; indexindex.htmlindex.php; root/tmp/test.com; error_page404http://test.com/404.html; error_page502http://test.com/502.html; error_page500http://test.com/500.html; location~*\.(gif|jpg|jpeg|png|css|js|ico|txt|svg|woff|ttf|eot)$ { rewrite^(.*)$/static$1break; root/tmp/test.com;# expires1d; } location~*\.(html|htm)$ { rewrite^(.*)$/static$1break; roo/tmp/test.com;# expires900s; } set$flag0; if($request_uri~*"^/fuck/\w+\.html$"){ set$flag"${flag}1"; } if($remote_addr!~*"192.168.0.50|192.168.0.51|192.168.0.56"){ set$flag"${flag}2"; } if($flag="012"){ rewrite^/index.htmlpermanent; } location/{ proxy_passhttp://service_test; include/opt/conf/nginx/proxy.conf; }
在实现需求的过程中出现的问题
把if指令和proxy_pass都放在location下面的话,if指令里面的内容不会执行,只会执行proxy_pass。
location/{ if($remote_addr!~*"192.168.0.50|192.168.0.51|192.168.0.56"){ rewrite^/index.htmlpermanent; } proxy_passhttp://service_test; include/opt/conf/nginx/proxy.conf; }
if指令下面使用proxy_pass指令问题
像下面这样使用会报错,错误的方式:
if($remote_addr~*"192.168.0.50|192.168.0.51|192.168.0.56"){ proxy_passhttp://test.com/fuck; }
正确的方式:
if($remote_addr~*"192.168.0.50|192.168.0.51|192.168.0.56"){ proxy_passhttp://test.com$request_uri; }
或是
if($remote_addr~*"192.168.0.50|192.168.0.51|192.168.0.56"){ proxy_passhttp://test.com; }
如果你是直接另外启动一个location的话,比如启动如下location:
location/fund{ if($remote_addr!~*"192.168.0.50|192.168.0.51|192.168.0.56"){ rewrite^/index.htmlpermanent; } }
这样的方式也是不支持的,当用IP192.168.0.50访问的时候,没有达到我们的业务需求,会报错400
注:各位有其他好的建议,欢迎探讨。