赶潮流 發表於 2023-12-1 16:35:00

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

<p>一大早接到网络部门通知,我们ip被恶意域名解析了:有未备案的域名解析到了我们ip上,10点前不处理好,将会封ip</p>
<p>接到这个通知,我是一头雾水,因为之前我是做过相关处理的:https://www.cnblogs.com/allay/p/17596091.html</p>
<p>后来把恶意解析域名地址拿来一看,好家伙,居然是https地址:</p>
<p><img src="https://img2023.cnblogs.com/blog/1219004/202312/1219004-20231201155458381-1021579131.png"></p>
<p>&nbsp;那就说的通了,我当时只做了80端口的防解析,443端口并没做</p>
<p>这里说下恶意域名解析原理:</p>
<p>外网域名解析,只能解析到 http://ip(80端口)或者&nbsp;https://ip(443端口)上,再往内部的二级域名等资源解析是没有办法的,因为他只能解析到 http://ip:80或者http://ip:443,nginx内部的 server_name参数他匹配不上</p>
<p>如果当前ip对应的80(或者443)端口在nginx里没有指定默认资源,会以conf.d目录下的顺序第一的配置文件指向的资源为准,也就是用80或者443各排第一个的配置文件为默认资源</p>
<p>这时候如果用一个不相关的域名解析到http://ip(80端口)或者&nbsp;https://ip(443端口)上,就会阴差阳错的关联到conf.d目录下80或者443各排第一位的配置文件对应的资源上</p>
<p>所以防解析的解决方法也很简单,就是指定80和443端口的默认资源,让他们只返回403报错,默认资源没法显示有效内容,域名就没法解析成功</p>
<p>&nbsp;</p>
<p>下面是我的操作步骤:</p>
<p>1.首先想到的就是修改默认资源啊</p>
<p>一开始修改的配置文件如下,重启nginx报错</p>
<p>&nbsp; 1#1: no "ssl_certificate" is defined for the "listen ... ssl" directive in /etc/nginx/conf.</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">server {
    listen </span><span style="color: rgba(128, 0, 128, 1)">80</span><span style="color: rgba(0, 0, 0, 1)"> default;
    return </span><span style="color: rgba(128, 0, 128, 1)">403</span><span style="color: rgba(0, 0, 0, 1)">;
}

server {
    listen </span><span style="color: rgba(128, 0, 128, 1)">443</span><span style="color: rgba(0, 0, 0, 1)"> ssl default;
    return </span><span style="color: rgba(128, 0, 128, 1)">403</span><span style="color: rgba(0, 0, 0, 1)">;
}</span></pre>
</div>
<p>看来443端口没有证书是配置不了了,眼看着10点要到了,暂时就不配置证书了,试试其他方式曲线救国</p>
<p>&nbsp;</p>
<p>2.修改conf.d目录443端口排第一的配置文件</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">server {
                listen</span><span style="color: rgba(128, 0, 128, 1)">443</span><span style="color: rgba(0, 0, 0, 1)"> ssl;
                server_name x.x.x.x;
                ...
                </span><span style="color: rgba(0, 0, 255, 1)">if</span> ($host != <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">x.x.x.x</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">){
                  return </span><span style="color: rgba(128, 0, 128, 1)">403</span><span style="color: rgba(0, 0, 0, 1)">;
                }
               ...
                location </span>/<span style="color: rgba(0, 0, 0, 1)"> {
                        proxy_pass   http:</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">xxxx;</span>
<span style="color: rgba(0, 0, 0, 1)">                        proxy_set_header Host $host;
                        proxy_set_header X</span>-Real-<span style="color: rgba(0, 0, 0, 1)">IP $remote_addr;
                        proxy_set_header X</span>-Forwarded-<span style="color: rgba(0, 0, 0, 1)">For $proxy_add_x_forwarded_for;
                }
                ...

}</span></pre>
</div>
<p>参考文档:https://www.cnblogs.com/mafeng/p/11671793.html</p>
<p>这个方式其实更适合防盗链,加了一个判断语句:只要匹配的域名不是设置的域名就返回403报错,经过实测是可行的!访问https://ip 也显示403了,之前是可以直接显示这个资源对应的网页的,访问正确的域名,网页可以正常打开</p>
<p><img src="https://img2023.cnblogs.com/blog/1219004/202312/1219004-20231201162421195-1826876727.png"></p>
<p>&nbsp;</p>
<p>某种程度上这样就可以了,但是如果后期加了个443资源,排名比他靠前,那这个策略就失效了,所以还是得配置专门的默认资源来返回403</p>
<p>&nbsp;</p>
<p>3.修改默认资源配置</p>
<p>首先得找个域名来生成证书,比如我们域名是abc.cn,那我就用403.abc.cn来做默认资源吧</p>
<p>我这里是使用certbot生成免费证书,关于如何使用certbot可以参考这篇:https://www.cnblogs.com/allay/articles/17319861.html</p>
<p>后来发现一个自签名证书的方式,感觉更好:https://blog.csdn.net/ceboy/article/details/104402486</p>
<p>这里 return 403; 配置需要先注释掉</p>
<p>修改403.conf如下</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">server {
    listen </span><span style="color: rgba(128, 0, 128, 1)">80</span><span style="color: rgba(0, 0, 0, 1)"> default;
    server_name </span><span style="color: rgba(128, 0, 128, 1)">403</span>.abc<span style="color: rgba(0, 0, 0, 1)">.cn;
    #return </span><span style="color: rgba(128, 0, 128, 1)">403</span><span style="color: rgba(0, 0, 0, 1)">;
    #配置http验证可访问
    location </span>~/.well-known/acme-challenge/<span style="color: rgba(0, 0, 0, 1)"> {
    #此目录都是nginx容器内的目录,对应宿主机volumes中的http验证目录,而宿主机的又与certbot容器中命令</span>--webroot-<span style="color: rgba(0, 0, 0, 1)">path指定目录一致,从而就整个串起来了,解决了http验证问题
    root </span>/usr/share/nginx/html/<span style="color: rgba(0, 0, 0, 1)">;
   }

}</span></pre>
</div>
<p>证书生成成功</p>
<p><img src="https://img2023.cnblogs.com/blog/1219004/202312/1219004-20231201163138505-856595398.png"></p>
<p>&nbsp;继续修改配置文件403.conf</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">server {
    listen </span><span style="color: rgba(128, 0, 128, 1)">80</span><span style="color: rgba(0, 0, 0, 1)"> default;
    server_name </span><span style="color: rgba(128, 0, 128, 1)">403</span>.abc<span style="color: rgba(0, 0, 0, 1)">.cn;
    return </span><span style="color: rgba(128, 0, 128, 1)">403</span><span style="color: rgba(0, 0, 0, 1)">;
    #配置http验证可访问
    location </span>~/.well-known/acme-challenge/<span style="color: rgba(0, 0, 0, 1)"> {
    #此目录都是nginx容器内的目录,对应宿主机volumes中的http验证目录,而宿主机的又与certbot容器中命令</span>--webroot-<span style="color: rgba(0, 0, 0, 1)">path指定目录一致,从而就整个串起来了,解决了http验证问题
    root </span>/usr/share/nginx/html/<span style="color: rgba(0, 0, 0, 1)">;
   }

}

server {
    listen </span><span style="color: rgba(128, 0, 128, 1)">443</span><span style="color: rgba(0, 0, 0, 1)"> ssl default;
    server_name </span><span style="color: rgba(128, 0, 128, 1)">403</span>.abc<span style="color: rgba(0, 0, 0, 1)">.cn;
    ssl_certificate         </span>/usr/local/etc/certbot/live/<span style="color: rgba(128, 0, 128, 1)">403</span>.abc.cn/<span style="color: rgba(0, 0, 0, 1)">fullchain.pem;
    ssl_certificate_key       </span>/usr/local/etc/certbot/live/<span style="color: rgba(128, 0, 128, 1)">403</span>.abc.cn/<span style="color: rgba(0, 0, 0, 1)">privkey.pem;

    ssl_session_timeout 5m;
    ssl_protocols TLSv1 TLSv1.</span><span style="color: rgba(128, 0, 128, 1)">1</span> TLSv1.<span style="color: rgba(128, 0, 128, 1)">2</span> TLSv1.<span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">;
    ssl_ciphers ECDHE</span>-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!<span style="color: rgba(0, 0, 0, 1)">DHE;
    ssl_prefer_server_ciphers on;

    return </span><span style="color: rgba(128, 0, 128, 1)">403</span><span style="color: rgba(0, 0, 0, 1)">;
}</span></pre>
</div>
<p>重启nginx,未报错,说明配置成功</p>
<p>最后再把第二步的判断注释掉,再重启nginx</p>
<p>这个时候访问未备案域名,返回403,访问https://ip依然返回403,443端口的防解析配置成功~</p>
<p>&nbsp;</p><br><br>
来源:https://www.cnblogs.com/allay/p/17870387.html
頁: [1]
查看完整版本: nginx防止恶意域名解析:nginx只允许域名访问,禁止通过ip访问443 ssl资源