nginx防止盗链,恶意域名解析:nginx只允许域名访问,禁止通过ip访问443 ssl资源

发布时间 2023-12-01 16:36:11作者: 06

一大早接到网络部门通知,我们ip被盗链了:有未备案的域名解析到了我们ip上,10点前不处理好,将会封ip

接到这个通知,我是一头雾水,因为之前我是做过相关处理的:https://www.cnblogs.com/allay/p/17596091.html

后来把盗链域名地址拿来一看,好家伙,居然是https地址:

 那就说的通了,我当时只做了80端口的防盗链,443端口并没做

这里说下盗链,恶意域名解析原理:

外网域名解析,只能解析到 http://ip(80端口)或者 https://ip(443端口)上,再往内部的二级域名等资源解析是没有办法的,因为有nginx server_name参数限制

如果当前ip对应的80(或者443)端口在nginx里没有指定默认资源,会以conf.d目录下的顺序第一的配置文件指向的资源为准,也就是用80或者443各排第一个的配置文件为默认资源

这时候如果用一个不相关的域名解析到http://ip(80端口)或者 https://ip(443端口)上,就会阴差阳错的关联到conf.d目录下80或者443各排第一位的配置文件对应的资源上

所以防盗链的解决方法也很简单,就是指定80和443端口的默认资源,让他们只返回403报错,默认资源没法显示有效内容,域名就没法解析成功

下面是我的操作步骤:

1.首先想到的就是修改默认资源啊

一开始修改的配置文件如下,重启nginx报错

 [emerg] 1#1: no "ssl_certificate" is defined for the "listen ... ssl" directive in /etc/nginx/conf.

server {
    listen 80 default;
    return 403;
}

server {
    listen 443 ssl default;
    return 403;
}

看来443端口没有证书是配置不了了,眼看着10点要到了,暂时就不配置证书了,试试其他方式曲线救国

 

2.修改conf.d目录443端口排第一的配置文件

server {
                listen  443 ssl;
                server_name x.x.x.x;
                ...
                if ($host != 'x.x.x.x'){
                  return 403;
                }
                 ...
                location / {
                        proxy_pass   http://xxxx;
                        proxy_set_header Host $host;
                        proxy_set_header X-Real-IP $remote_addr;
                        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                }
                ...

}

参考文档:https://www.cnblogs.com/mafeng/p/11671793.html

加了一个判断语句,只要匹配的域名不是设置的域名就返回403报错,经过实测是可行的,访问https://ip也显示403了,之前是可以直接显示这个资源对应的网页的

 

某种程度上这样就可以了,但是如果后期加了个443资源,排名比他靠前,那这个策略就失效了,所以还是得配置专门的默认资源来返回403

 

3.修改默认资源配置

首先得找个域名来生成证书,比如我们域名是abc.cn,那我就用403.abc.cn来做默认资源吧

我这里是使用certbot生成免费证书,return 403; 配置需要先注释掉

修改403.conf如下

server {
    listen 80 default;
    server_name 403.abc.cn;
    #return 403;
    #配置http验证可访问
    location ~/.well-known/acme-challenge/ {
    #此目录都是nginx容器内的目录,对应宿主机volumes中的http验证目录,而宿主机的又与certbot容器中命令--webroot-path指定目录一致,从而就整个串起来了,解决了http验证问题
    root /usr/share/nginx/html/;
     }

}

证书生成成功

 继续修改配置文件403.conf

server {
    listen 80 default;
    server_name 403.abc.cn;
    return 403;
    #配置http验证可访问
    location ~/.well-known/acme-challenge/ {
    #此目录都是nginx容器内的目录,对应宿主机volumes中的http验证目录,而宿主机的又与certbot容器中命令--webroot-path指定目录一致,从而就整个串起来了,解决了http验证问题
    root /usr/share/nginx/html/;
     }

}

server {
    listen 443 ssl default;
    server_name 403.abc.cn;
    ssl_certificate           /usr/local/etc/certbot/live/403.abc.cn/fullchain.pem;
    ssl_certificate_key       /usr/local/etc/certbot/live/403.abc.cn/privkey.pem;

    ssl_session_timeout 5m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
    ssl_prefer_server_ciphers on;

    return 403;
}

重启nginx,未报错,说明配置成功

最后再把第二步的判断注释掉,再重启nginx

这个时候访问盗链域名,返回403,访问https://ip依然返回403,防盗链配置成功~