如何在 Nginx 中防止恶意扫描、垃圾爬虫?
|
admin
2026年8月4日 18:47
本文热度 30
|

Nginx 是目前最常用的 Web 服务器软件,负责接收用户请求并把网页内容返回给浏览器。但总有一些恶意 IP 和垃圾爬虫不停地扫描、抓取网站,不仅消耗带宽和服务器资源,还可能探测漏洞伺机攻击。每次在查看网站日志时,都会发现有许多的恶意扫描和垃圾爬虫。为了网站安全和减轻服务器压力,应该想办法阻止这些垃圾请求。具体操作就是,先通过 Nginx 访问日志,查看哪些是垃圾请求,然后通过 Nginx 配置,屏蔽它们访问。本人网站的 Nginx 为 1.18版本,其 Access 日志在:/var/log/nginx/ 目录。$ awk '{print $1}' access.log|sort | uniq -c |sort -n -k 1 -r|more说明,使用 awk 命令拆分日志,打印第一列($1表示第一列,默认的 access日志,第一列是IP地址),排序和去重后查看。获取到恶意访问的IP后,我们可以使用 deny 指令来屏蔽。可以指定单个IP,也可以按照IP段进行屏蔽。以下是屏蔽示例: deny 108.179.194.35; # 扫描 wordpress deny 159.203.31.171; # 扫描 wp-login deny 158.69.243.0/24; # MJ12bot deny 46.229.168.0/24; # SemRush deny 54.36.148.0/24; # AhrefsBot deny 54.36.149.0/24; # AhrefsBot备注: deny 指令可以在 Nginx 的 http, server, location 上下文中指定。(3)另外还有一个 allow 指令,指明哪些请求可以访问。对于仅限特定用户访问的内容,我们可以指明其允许访问的IP。比如网站管理后台的链接,仅限指定的ip段访问。说明,这里配置的,除了指定的几个ip 或 ip段,剩下的全部拒绝访问。$ awk '{print $7}' access.log|sort | uniq -c |sort -n -k 1 -r|more说明,本人网站的 access.log 第7列为 url 地址(Nginx默认配置),如果在配置文件中专门指明了nginx日志格式,可能会有不同。/wp-includes/css/wp-config.php/wp-includes/wlwmanifest.xml/config/AspCms_Config.asp可以看到这是在扫描 WordPress 和 phpMyAdmin、下载网站的压缩包、扫描网站可能存在的配置。在 Nginx 中,我们可以使用 $document_uri 来获取到请求 uri,根据 uri 我们来判断哪些后缀的请求我们拒绝其访问。if ($document_uri ~* \.(php|asp|aspx|jsp|swp|git|env|yaml|yml|sql|db|bak|ini|docx|doc|rar|tar|gz|zip|log)$) {说明:这里使用 if 语句,匹配以点 . 开始,以 php、asp 、jsp 、env 等后缀结尾的文件,如果存在,nginx 则直接返回 404 给客户端。注意:这里的配置的后缀仅供参考,按需配置,比如你如果想让用户下载doc文件,就把 doc|docx 去掉。Tips: 变量 $document_uri ($uri) 与 $request_uri 有什么不同?比如访问链接是 https://wang123.net/posts/test.db?wd=test&limit=5$document_uri 变量的值为:/posts/test.db$request_uri 变量的值为:/posts/test.db?wd=test&limit=5对于一些我们不能按照后缀进行屏蔽的链接,比如 /wp-includes/wlwmanifest.xml ,这个 xml 后缀不能屏蔽(因为网站其他地方有要用的xml链接,因此我们改用其他关键词进行屏蔽。根据请求 uri 里的的关键词进行屏蔽,示例如下:if ($document_uri ~* (wordpress|phpinfo|wlwmanifest|phpMyAdmin|xmlrpc)) {说明,这里匹配几个特定关键词,匹配上来直接返回 404 错误。再访问 /wp-includes/wlwmanifest.xml 会直接 404。注意,这里的配置要谨慎,如果配置了,url链接里就不能有这些关键词了,否则 nginx 则直接返回 404 错误。浏览器或者爬虫工具访问,一般都会带有 User Agent (浏览器用户标识)。在 Nginx 中,$http_user_agent 变量可以获取到用户的 UA ,匹配到我们指定的关键词,直接返回 403 无权访问。if ($http_user_agent ~* (Scrapy|HttpClient|Postman|ApacheBench|Java|python|node-fetch)) { # 禁止指定的 user agent 以及为空的访问if ($http_user_agent ~ "Nimbostratus|MJ12bot|YisouSpider|^$" ) {注意,这里仅列出来了部分爬虫的 UA 关键词,更多的可以去网上搜索“垃圾爬虫”。有些爬虫也支持 robots 协议, 因此我们在网站根目录的 robots.txt 文件中也可以都加上。
- ngx_http_limit_conn_module 限制并发连接数
- ngx_http_limit_req_module 限制请求速率(漏桶算法)
这里我们使用 ngx_http_limit_conn_module 里的 limit_conn_zone 和 limit_conn 指令配置,限制请求的连接数。 limit_conn_zone $binary_remote_addr zone=perIP:10m; limit_conn_zone $server_name zone=perServer:10m; limit_conn perServer 200;
- limit_conn_zone 配置存在的连接的空间(zone),一个名字叫 perIP,一个名字叫 perServer,空间的大小都指定大小为 10m 。
- limit_conn perIP 10 作用的 key 是 $binary_remote_addr,表示限制单个IP同时最多能持有10个连接。
- limit_conn perServer 200 作用的 key 是 $server_name,表示虚拟主机(server) 同时能处理并发连接的总数为 200。
- limit_conn_status 表示,如果超出链接,直接返回 503 错误。
注意, limit_conn 的数值按需调整。上边的配置会对全站都生效。如果只是想对某个 uri 限流,可以将 limit_conn 写在 location 上下文里。 limit_conn_zone $binary_remote_addr zone=addr:10m;为了方便管理,我们创建两个配置文件,对ip和spider分别管理。deny 108.179.194.35; # 扫描 wordpress deny 159.203.31.171; # 扫描 wp-logindeny 158.69.243.0/24; # MJ12botdeny 46.229.168.0/24; # SemRush deny 54.36.148.0/24; # AhrefsBot deny 54.36.149.0/24; # AhrefsBot屏蔽UA访问 block_spiders.confif ($http_user_agent ~* (Scrapy|HttpClient|PostmanRuntime|ApacheBench|Java|python-requests|Python-urllib|node-fetch)) {# 禁止指定的 user agent 以及为空的访问if ($http_user_agent ~ "Nimbostratus|MJ12bot|MegaIndex|YisouSpider|^$" ) {if ($document_uri ~* \.(php|asp|aspx|jsp|swp|git|env|yaml|yml|sql|db|bak|ini|docx|doc|rar|tar|gz|zip|log)$) {if ($document_uri ~* (wordpress|phpinfo|wlwmanifest|phpMyAdmin|xmlrpc)) {这样在 nginx.conf 中就可以直接 include 进来了。 limit_conn_zone $binary_remote_addr zone=perIP:10m; limit_conn_zone $server_name zone=perServer:10m; limit_conn perServer 200; include /etc/nginx/block_ips.conf; include /etc/nginx/block_spiders.conf;nginx: the configuration file /etc/nginx/nginx.conf syntax is oknginx: configuration file /etc/nginx/nginx.conf test is successful重启 nginx 即可生效。(本机的nginx,是使用 apt 包安装的,可以直接 使用 systemctl 管理 nginx 服务)。$ systemctl reload nginx # 重新加载$ systemctl restart nginx # 重启$ systemctl status nginx # 查看状态$ systemctl start nginx # 启动$ systemctl stop nginx # 停止
阅读原文:点击这里
该文章在 2026/8/4 18:47:56 编辑过