使用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
注:各位有其他好的建议,欢迎探讨。