Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【腾讯云的1001种玩法】Nginx网站使用CDN之后禁止用户真实IP访问的方法

【腾讯云的1001种玩法】Nginx网站使用CDN之后禁止用户真实IP访问的方法

原创
作者头像
张戈
修改于 2017-08-07 07:39:36
修改于 2017-08-07 07:39:36
4K00
代码可运行
举报
文章被收录于专栏:张戈的专栏张戈的专栏
运行总次数:0
代码可运行

做过面向公网 WEB 的运维人员经常会遇见恶意扫描、拉取、注入等图谋不轨的行为,对于直接对外的 WEB 服务器,我们可以直接通过 iptables 、Nginx 的 deny 指令或是程序来 ban 掉这些恶意请求。

而对于套了一层 CDN 或代理的网站,这些方法可能就失效了。尤其是个人网站,可能就一台VPS,然后套一个免费的 CDN 就行走在互联网了。并不是每个 CDN 都能精准的拦截各种恶意请求的,更闹心的是很多 CDN 还不支持用户在 CDN 上添加 BAN 规则,比如腾讯云 CDN。

因此,就有了本文的折腾分享。

一、真假难辨

如何禁止访问,我们先了解下常见的3种网站访问模式:

  1. 用户直接访问对外服务的普通网站: 浏览器 --> DNS解析 --> WEB数据处理 --> 数据吐到浏览器渲染展示。
  2. 用户访问使用了CDN的网站: 浏览器 --> DNS解析 --> CDN节点 --> WEB数据处理 --> 数据吐到浏览器渲染展示。
  3. 用户通过代理上网访问了我们的网站: 浏览器 --> 代理上网 --> DNS解析 --> 上述2种模式均可能。

对于第一种模式,我要禁止这个用户的访问很简单,可以直接通过 iptables 或者 Nginx的deny指令来禁止均可:

iptabels: iptables -I INPUT -s 用户ip -j DROP Nginx的deny指令: 语 法: deny address | CIDR | unix: | all; 默认值: — 配置段: http, server, location, limit_except 顺 序:从上往下 Demo: location / { deny 用户IP或IP段; }

但对于后面2种模式就无能为力了,因为 iptables 和 deny 都只能针对直连IP,而后面2种模式中,WEB服务器直连IP是CDN节点或者代理服务器,此时使用 iptable 或 deny 就只能把 CDN节点 或代理IP给封了,可能误杀一大片正常用户了,而真正的罪魁祸首轻轻松松换一个代理IP又能继续请求了。

那我们可以通过什么途径去解决以上问题呢?

二、火眼金睛

如果长期关注张戈博客的朋友,应该还记得之前转载过一篇分享 Nginx 在 CDN 加速之后,获取用户真实 IP 做并发访问限制的方法。说明 Nginx 还是可以实实在在的拿到用户真实 IP 地址的,那么事情就好办了。

要拿到用户真实 IP,只要在 Nginx 的 http 模块内加入如下配置:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#获取用户真实IP,并赋值给变量$clientRealIP
map $http_x_forwarded_for  $clientRealIp {
        ""      $remote_addr;
        ~^(?P<firstAddr>[0-9\.]+),?.*$  $firstAddr;
}

那么,$clientRealIP就是用户真实IP了,其实就是匹配了 $http_x_forwarded_for 的第一个值,具体原理前文也简单分享过:

其实,当一个 CDN 或者透明代理服务器把用户的请求转到后面服务器的时候,这个 CDN 服务器会在 Http 的头中加入一个记录X-Forwarded-For : 用户IP, 代理服务器IP。 如果中间经历了不止一个代理服务器,这个记录会是这样X-Forwarded-For :用户IP, 代理服务器1-IP, 代理服务器2-IP, 代理服务器3-IP, …. 可以看到经过好多层代理之后, 用户的真实IP 在第一个位置, 后面会跟一串中间代理服务器的IP地址,从这里取到用户真实的IP地址,针对这个 IP 地址做限制就可以了。

而且代码中还配合使用了 $remote_addr,因此$clientRealIP 还能兼容上文中第1种直接访问模式,不像 $http_x_forwarded_for 在直接访问模式中将会是空值!

所以,$clientRealIP 还能配置到 Nginx 日志格式中,替代传统的 $remote_addr 使用,推荐!

三、隔山打牛

既然已经拿到了真实IP,却不能使用 iptables 和 deny 指令,是否无力感油然而生?

哈哈,在强大的 Nginx 面前只要想得到,你就做得到!通过对 $clientRealIP 这个变量的判断,Nginx就能实现隔山打牛的目的,而且规则简单易懂:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#如果真实IP121.42.0.18121.42.0.19,那么返回403
if ($clientRealIp ~* "121.42.0.18|121.42.0.19") {
        #如果你的nginx安装了echo模块,还能如下输出语言,狠狠的发泄你的不满(但不兼容返回403,试试200)!
        #add_header Content-Type text/plain;
        #echo "son of a bitch,you mother fucker,go fuck yourself!";
        return 403;
        break;
}

把这个保存为 deny_ip.conf ,上传到 Nginx 的 conf 文件夹,然后在要生效的网站 server 模块中引入这个配置文件,并 Reload 重载 Nginx 即可生效:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#禁止某些用户访问
include deny_ip.conf;

如果再想添加其他要禁止的IP,只需要编辑这个文件,插入要禁止的IP,使用分隔符 | 隔开即可,记得每次修改都需要 reload 重载 Nginx才能生效。

四、奇淫巧计

为了更方便的添加和删除这些黑名单IP,昨晚熬夜写了一个小脚本,一键添加和删除,懒人有福了!

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#!/bin/bash
###################################################################
#  Deny Real IP for Nginx;  Author: Jager <ge@zhangge.net>        #
# For more information please visit https://zhangge.net/5096.html #
#-----------------------------------------------------------------#
#  Copyright ©2016 zhangge.net. All rights reserved.              #
###################################################################

NGINX_BIN=/usr/local/nginx/sbin/nginx
DENY_CONF=/usr/local/nginx/conf/deny_ip.conf

COLOR_RED=$(    echo -e "\e[31;49m" )
COLOR_GREEN=$(  echo -e "\e[32;49m" )
COLOR_RESET=$(  echo -e "\e[0m"     )

rep_info() { echo;echo -e "${COLOR_GREEN}$*${COLOR_RESET}";echo; }
rep_error(){ echo;echo -e "${COLOR_RED}$*${COLOR_RESET}";echo;exit 1; }

show_help()
{
printf "
###################################################################
#  Deny Real IP for Nginx;  Author: Jager <ge@zhangge.net>        #
# For more information please visit https://zhangge.net/5096.html #
#-----------------------------------------------------------------#
#  Copyright ©2016 zhangge.net. All rights reserved.              #
###################################################################

Usage: $0 [OPTIONS]

OPTIONS:
-h | --help   : Show help of this script
-a | --add    : Add a deny ip to nginx, for example: ./$0 -a 192.168.1.1
-c | --create : Create deny config file($DENY_CONF) for Nginx
-d | --del    : Delete a ip from deny list, for example: ./$0 -d 192.168.1.1
-s | --show   : Show current deny list

"
}

reload_nginx()
{
    $NGINX_BIN -t >/dev/null 2>&1 && \
    $NGINX_BIN -s reload && \
    return 0
}

show_list()
{
   awk -F '["){|]' '/if/ {for(i=2;i<=NF;i++) if ($i!="") printf $i"\n"}' $DENY_CONF 
}

pre_check()
{
    test -f $NGINX_BIN || rep_error "$NGINX_BIN not found,Plz check and edit."
    test -f $DENY_CONF || rep_error "$DENY_CONF not found,Plz check and edit." 
    MATCH_COUNT=$(show_list | grep -w $1 | wc -l)
    return $MATCH_COUNT
}

create_rule()
{
test -f $DENY_CONF && \
rep_error "$DENY_CONF already exist!."
cat >$DENY_CONF<<EOF
if (\$clientRealIp ~* "8.8.8.8") {
    #add_header Content-Type text/plain;
    #echo "son of a bitch,you mother fucker,go fuck yourself!"; 
    return 403;
    break;
}
EOF
test -f $DENY_CONF && \
rep_info "$DENY_CONF create success!" && \
cat $DENY_CONF && \
exit 0

rep_error "$DENY_CONF create failed!" && \
exit 1

}

add_ip()
{
    pre_check $1
    if [[ $? -eq 0 ]];then
        sed -i "s/\")/|$1&/g" $DENY_CONF && \
        reload_nginx && \
        rep_info "add $1 to deny_list success." || \
        rep_error "add $1 to deny_list failed."
    else
        rep_error "$1 has been in deny list!"
        exit
    fi
}

del_ip()
{
    pre_check $1
    if [[ $? -ne 0 ]];then
        sed -ie "s/\(|$1\|$1|\)//g" $DENY_CONF && \
        reload_nginx && \
        rep_info "del $1 from deny_list success." || \
        rep_error "del $1 from deny_list failed."
    else
        rep_error "$1 not found in deny list!"
        exit
    fi
}

case $1 in
    "-s"|"--show" )
        show_list
        exit
        ;;
    "-h"|"--help" )
        show_help
        exit
        ;;
    "-c"|"--create" )
        create_rule
    ;;
esac

while [ $2 ];do
    case $1 in
        "-a"|"--add" )
            add_ip $2;
            ;;
        "-d"|"--del" )
            del_ip $2
            ;;
        * )
            show_help
            ;; 
    esac
    exit
done
show_help

使用方法:

  1. 根据实际情况修改第9、10行 Nginx 二进制文件及其deny配置文件路径
  2. 然后将此脚本保存为 deny_ctrl.sh 上传到服务器任意目录,比如放到 /root
  3. 给脚本赋予可执行权限:chmod +x deny_ctrl.sh 即可使用
  4. 使用参数:
    • Usage: deny_ctrl.sh [OPTIONS]
    • OPTIONS:
    • -h | --help : 显示帮助信息
    • -a | --add : 添加一个黑名单IP, 例如: ./deny_ctrl.sh -a 192.168.1.1
    • -c | --create : 初始化创建一个禁止IP的配置文件,需要自行include 到需要的网站server模块
    • -d | --del : 删除一个黑名单IP,例如: ./deny_ctrl.sh -d 192.168.1.1
    • -s | --show : 显示当前已拉黑IP清单

初次使用,先执行./deny_ctrl.sh -c创建一下 Nginx 相关配置文件:deny_ip.conf,默认内容如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if ($clientRealIp ~* "8.8.8.8") {
    #add_header Content-Type text/plain;
    #echo "son of a bitch,you mother fucker,go fuck yourself!"; 
    return 403;
    break;
}

8.8.8.8 是为了占位,规避为空的情况,实际使用中也请注意,必须要有一个IP占位,否则可能导致误杀哦!

生成这个文件之后,编辑网站对应的配置文件,比如 zhangge.net.conf,在 server {}模块内部插入 include deny_ip.conf; (注意有英文分号)即可。

比如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
server
    {
        listen 80;   
        server_name zhangge.net;
        index index.html index.htm index.php default.html default.htm default.php;
        root  /home/wwwroot/zhangge.net;

        include agent_deny.conf;  #新增此行
        #其他略 ...

最后,使用nginx -s reload 重载nginx即可。

后面需要添加黑名单或删除黑名单都可以使用 deny_ctrl.sh 脚本来操作了!

最后,顺便说明一下,本文分享的方法仅作为使用CDN网站遇到恶意IP的一种手工拉黑方案。而自动化限制的方案可以参考博客之前的分享:《Nginx在CDN加速之后,获取用户真实IP做并发访问限制的方法》

好了,本文分享到此,希望对你有所帮助。

相关推荐: 腾讯存储与CDN免费体验 Nginx双向认证配置指南

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【详解】Nginx如何封禁IP和IP段?
在Web服务器的日常管理中,有时需要对特定的IP地址或IP段进行访问限制,以保护网站的安全。Nginx作为一个高性能的HTTP和反向代理服务器,提供了灵活的配置选项来实现这一需求。本文将详细介绍如何使用Nginx封禁单个IP地址和IP段。
大盘鸡拌面
2025/05/12
2520
雷池+frp 批量设置proxy_protocol实现真实IP透传
内网部署safeline,通过frp让外网访问内部web网站服务,让safeline记录真实外网攻击IP
用户3358450
2024/10/10
3380
获取用户的真实ip
做网站时候经常会用到remote_addr和x_forwarded_for 这两个头信息来获取,客户端ip,然而当有反向代理或者CDN的情况下,这两个就不够准确了,需要调整一些配置 remote_addr: remote_addr 代表客户端的ip,但它的值不是由客户端提供的,而是服务端根据服务端的ip指定的, 当你的浏览器访问某个网站时候,假设中间没有任何代理,那么网站的web服务器(Nginx,Apache等) 就会把remote_addr设为你的机器ip 如果你用了某代理,那么你的浏览器会先访问这
joshua317
2018/04/16
4.5K0
CDN NGINX防止CC攻击 防采集 宝塔面板可用 及识别CDN真实访问者IP并屏蔽思路
CC 攻击和采集都是同个IP发起大量访问请求,这个会造成大量请求拥堵,导致服务器资源耗尽,CC攻击主要针对特定服务接口,属于实现 DoS 攻击的一种方式。
Qicloud
2022/01/21
1.7K0
史上最全的nginx安全访问控制配置
准备两台带有yum安装的nginx的虚拟机,一台作为代理服务器,一台作为真实服务器。
码农编程进阶笔记
2021/07/20
3.8K0
Nginx反向代理及获取真实的客户端IP地址
在构建网络应用时,很常见的一种场景是使用反向代理服务器,例如 Nginx。反向代理可以提供负载均衡、安全保护、缓存等多种功能,因此在现代 web 开发中扮演着非常重要的角色。然而,使用反向代理的同时,也引入了一个新的问题:如何获取到真实的客户端 IP 地址?
高久峰
2023/09/28
12.8K1
Nginx在CDN加速之后,获取用户真实IP做并发访问限制的方法
从昨晚忙到现在就是为了做网站防护,为了简单抵挡一下某些XX的DDoS攻击,网站开启了百度云的免费CDN服务。 开启CDN之后,我之前写的Shell防护脚本也就宣告无效了,因为不管是正常访问还是攻击访问,脚本拿到的IP都是CDN节点的,而我不可能把CDN的节点IP也给禁用了,那就都不能访问了(其实已经犯过错了,导致天津,北京的大面积不可以访问站点,仅有几个存在的CDN可以访问!多亏朋友提示!)。 为了解决这个窘迫,我想到了以前看过的Nginx访问限制。通过查资料,让我拜读了一枚大神的神作,感觉收获颇丰!于是转
老七Linux
2018/05/31
4.1K0
Nginx 不受 CDN 服务影响获取访客真实 IP
获取和记录站点访客的真实 IP 对于站点日志的分析和安全策略的指定很有帮助,Nginx 默认的日志记录获取到的 IP 地址如果站点启用了 CDN 服务,那么这里的 IP 地址都是 CDN 服务器节点的 IP 地址了,并不是用户访客的 IP 地址(如图 1),这时候分析 Nginx 日志看到的数据就不是很真实了,影响判断呀!今天明月就给大家分享一个 Nginx 不受 CDN 服务影响获取访客真实 IP 的方法。
双面人
2019/04/10
2K0
Nginx 不受 CDN 服务影响获取访客真实 IP
Nginx从入门到放弃05-访问日志与日志切割
当我们访问nginx服务时,nginx会记录日志,nginx日志分两种,一种是访问日志,一种是错误日志,访问日志记录在”access.log”文件中,错误日志记录在”error.log”文件中。
星哥玩云
2022/06/24
5640
Nginx从入门到放弃05-访问日志与日志切割
万字长文带你了解最常用的开源 Squid 代理服务器
Squid:是一个高性能的代理缓存服务器,Squid 支持 FTP、gopher、HTTPS 和 HTTP协议。和一般的代理缓存软件不同,Squid用一个单独的、非模块化的、I/O驱动的进程来处理所有的客户端请求,作为应用层的代理服务软件,Squid 主要提供缓存加速、应用层过滤控制的功能。
杰哥的IT之旅
2020/06/18
4.5K0
万字长文带你了解最常用的开源 Squid 代理服务器
Nginx防盗链+Nginx访问控制+Nginx解析php相关配置+Nginx 代理
一、Nginx防盗链: 1.1 打开配置文件: /usr/local/nginx/conf/vhost/haha.com.conf 增加如下配置文件: location ~* ^.+\.(gif|jpg|png|swf|flv|rar|zip|doc|pdf|gz|bz2|jpeg|bmp|xls)$ { expires 7d; valid_referers none blocked server_names *.haha.com ; if ($invalid_referer) {
老七Linux
2018/05/09
1.1K0
nginx——关于获取真实ip
做网站时经常会用到remote_addr和x_forwarded_for这两个头信息来获取客户端的IP,然而当有反向代理或者CDN的情况下,这两个值就不够准确了,需要调整一些配置。
江小白
2018/07/16
5.3K0
nginx——关于获取真实ip
Nginx防盗链,Nginx访问控制,,Nginx解析php相关配置,Nginx代理
vim /usr/local/nginx/conf/vhost/test.com.conf
端碗吹水
2020/09/23
1.9K0
Nginx防盗链,Nginx访问控制,,Nginx解析php相关配置,Nginx代理
Nginx防盗链,Nginx访问控制,Nginx解析php相关配置, Nginx代理
Nginx防盗链: vim /usr/local/nginx/conf/vhost/test.com.conf    = 默认虚拟主机配置防盗链 #防盗链核心配置 location ~* ^.+\.(
叶瑾
2018/06/14
8080
【腾讯云的1001种玩法】Nginx网站服务器学习与入门
魏豪
2017/04/24
5.6K2
【腾讯云的1001种玩法】Nginx网站服务器学习与入门
linux学习第四十六篇:Nginx防盗链,Nginx访问控制,Nginx解析php相关配置,Nginx代理
Nginx防盗链 vim /usr/local/nginx/conf/vhost/test.com.conf 配置如下,可以和上面的配置结合起来: location ~* ^.+\.(gif|jpg|png|swf|flv|rar|zip|doc|pdf|gz|bz2|jpeg|bmp|xls)$ { expires 7d; valid_referers none blocked server_names *.test.com ; //定义白名单 if ($invalid_re
用户1215343
2018/02/05
1.7K0
linux学习第四十六篇:Nginx防盗链,Nginx访问控制,Nginx解析php相关配置,Nginx代理
Nginx 与 X-Forwarded-For
今天的这篇文章发布于2016年01月,是介绍HTTP扩展头部 X-Forwarded-For,以及在nginx中使用http_x_forwarded_for变量来完成一些"特殊"功能,例如网站后台面向内部工作人员,所以希望只允许办公室网络IP访问。
用户1560186
2019/11/19
7.4K0
nginx防盗链、访问控制、PHP解析、服务器代理
说明: “location ~* ^.+”在此0“ * ”的作用是后面匹配的内容不区分大小写。
阿dai学长
2019/04/03
1K0
Nginx开启fastcgi_cache缓存加速,支持html伪静态页面
张戈博客不久前分享过 Nginx 开启缓存为 WordPress 加速的教程,其中分享了 2 种缓存模式:代理模式和本地模式。我一直以为单个 ngx_cache_purge 缓存模块只支持 proxy
张戈
2018/03/23
3.7K0
Nginx开启fastcgi_cache缓存加速,支持html伪静态页面
ASP.NET Core 搭配 Nginx 的真实IP问题
Nginx(Engine X)是一个高性能HTTP和反向代理服务,是由俄罗斯人伊戈尔·赛索耶夫为访问量第二的Rambler.ru站点(俄文:Рамблер)开发的,第一个公开版本0.1.0发布于2004年10月4日。 如果你是一名 ASP.NET Core 开发人员,并且你的 ASP.NET Core 应用部署在Linux上,相信你应该或多或少与 Nginx 有过接触,在我们将 ASP.NET Core 部署在 Linux 上时,它是被用做反向代理的最好选择之一。今天和大家聊一聊当我们使用了 Nginx 反向代理后,我们程序中获取真实IP(客户端真实ip,本文简称“真实IP”)的问题。
晓晨
2018/12/12
9290
推荐阅读
相关推荐
【详解】Nginx如何封禁IP和IP段?
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验