Nginx禁止其他域名访问

今天看到一则来自@kyaky的评论

让我也意识到了这个问题:

如果别人把我的IP地址绑到他的域名上, 那我就是在为别人搭博客了. 我本以为Nginx配置中的server_name选项可以进行阻挡, 看来不实践真的是不能轻易下结论.

今天就回顾一下这个问题的所在, 及解决方案.

DNS解析场景是这样:

域名    类型    IP
A.com    A    a.b.c.d
B.com    A    a.b.c.d

现在我的网站配置的默认服务是A.com.conf:

server {
    listen 80 default;
    server_name A.com;
}

当初我为了避免直接拿IP访问站点, 做了IP的过滤:

if ( $host ~* "\d+\.\d+\.\d+\.\d+" ) {
    return 403;
}

在这种情况下, 访问A.com会找到a.b.c.d这个IP, Nginx解析得知匹配到了A.com.conf, 于是进入document root目录进行服务.

当访问B.com时, DNS也会找到a.b.c.d这个IP, Nginx解析得知没有匹配, 于是也会进入A.com.conf的document root, 继续提供服务 – 因为是default.

当时忽略了域名绑定IP的问题, 那么我再加一条if{}判断, 不符合archean.me的都返回403, 即可解决这个问题了.


但这样做显然不够优雅, 不仅陡然增加了Nginx配置文件的复杂度, 同时如果有多个域名绑定这台机器, 需要修改的地方就太多了.

所以查阅Nginx官方资料, 果然有相应的解决办法

原来我没有做默认服务default.conf的配置, A Default "Catch All" Server Block

server {
    listen 80 default_server;
    server_name _; # This is just an invalid value which will never trigger on a real hostname.
    return 403;
}

关键在于server_name _;, 这是指无效域名, 无论是IP地址, 错误的域名拼写或是未在其他虚拟主机配置中提到的域名, 均会触发return 403;, 显示页面不存在.

于是略加改进, 去掉其他虚拟主机中的default字段; 把default.conf中的return 403;改为重定向到我们期望的默认首页, 即可解决我们的问题.

server {
    listen 80 default_server;
    server_name _;
    rewrite ^ http://archean.me$request_uri?;
}
Author

Archean Zhang

Posted on

2013-10-24

Updated on

2022-07-11

Licensed under

Comments