AWS-WAF-CDN基于速率rate的永久黑名单方案(基于lambda实现)

参考方案(有坑), 所以产生了这篇博客: 点击跳转

1. 部署waf (有则跳过)

在这里插入图片描述
必须存在一个rate速率规则,后面的方案堆栈要用

新建rate速率规则

在这里插入图片描述
在这里插入图片描述
关联cdn资源
在这里插入图片描述

2.部署堆栈 (美国东部 (弗吉尼亚北部 us-east-1)

1 .堆栈文件获取方式:

1.公开s3桶调用:https://actwill-cloudformation-template.s3.amazonaws.com/waf-block-rate-ip/waf_block_rate_ip_20231208.template

2.也可以手动选择复制保存

# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0AWSTemplateFormatVersion: '2010-09-09'
Parameters:Scope:Type: StringDescription: Enter WebACL Scope CLOUDFRONT or REGIONALAllowedValues: [REGIONAL, CLOUDFRONT]WebACLName:Type: StringDescription: Enter WebACL nameWebACLId:Type: StringDescription: Enter WebACL IDRateBasedRuleName:Type: StringDescription: Enter Rate Based Rule NameCustomBlockPeriod:Type: NumberDescription: Enter custom block period for blocking the IP addresses in minutes. Minimum is 06 minutesMinValue: 6Resources:CustomRBRLogBucket:Type: "AWS::S3::Bucket"Properties:BucketName: !Join- "-"- - "custom-rbr-log-bucket"- !Select- 0- !Split- "-"- !Select- 2- !Split- "/"- !Ref "AWS::StackId"BucketEncryption:ServerSideEncryptionConfiguration:- ServerSideEncryptionByDefault:SSEAlgorithm: AES256PublicAccessBlockConfiguration: BlockPublicAcls: trueBlockPublicPolicy: trueIgnorePublicAcls: trueRestrictPublicBuckets: trueLoggingConfiguration: DestinationBucketName: !Ref AccessLoggingBucketCustomRBRLogBucketPolicy:Type: AWS::S3::BucketPolicyProperties:Bucket:Ref: CustomRBRLogBucketPolicyDocument:Statement:- Action: "s3:*"Condition:Bool:aws:SecureTransport: 'false'Effect: DenyPrincipal: "*"Resource:- !GetAtt CustomRBRLogBucket.Arn- !Join ["/", [!GetAtt CustomRBRLogBucket.Arn, "*"]]Sid: HttpsOnlyVersion: '2012-10-17'AccessLoggingBucket:Type: AWS::S3::BucketProperties:BucketEncryption:ServerSideEncryptionConfiguration:- ServerSideEncryptionByDefault:SSEAlgorithm: AES256PublicAccessBlockConfiguration:BlockPublicAcls: TrueBlockPublicPolicy: TrueIgnorePublicAcls: TrueRestrictPublicBuckets: TrueMetadata:cfn_nag:rules_to_suppress:- id: W35reason: "This bucket is an access logging bucket for another bucket and does not require access logging to be configured for it."    AccessLoggingBucketPolicy:Type: AWS::S3::BucketPolicyProperties:Bucket:Ref: AccessLoggingBucketPolicyDocument:Statement:- Action: "s3:*"Condition:Bool:aws:SecureTransport: 'false'Effect: DenyPrincipal: "*"Resource:- !GetAtt AccessLoggingBucket.Arn- !Join ["/", [!GetAtt AccessLoggingBucket.Arn, "*"]]Sid: HttpsOnlyVersion: '2012-10-17'IPv4IPset:Type: "AWS::WAFv2::IPSet"Properties:Name: !Join- "-"- - "IPv4-IPset"- !Select- 0- !Split- "-"- !Select- 2- !Split- "/"- !Ref "AWS::StackId"Scope: !Ref ScopeDescription: "IPv4 IP set for custom rate based block rule"IPAddressVersion: "IPV4"Addresses: []IPv6IPset:Type: "AWS::WAFv2::IPSet"Properties:Name: !Join- "-"- - "IPv6-IPset"- !Select- 0- !Split- "-"- !Select- 2- !Split- "/"- !Ref "AWS::StackId"Scope: !Ref ScopeDescription: "IPv6 IP set for custom rate based block rule"IPAddressVersion: "IPV6"Addresses: []CustomRBRLambdaFunction:Type: 'AWS::Lambda::Function'Properties:FunctionName: !Join- "-"- - "CustomRBRLambdaFunction"- !Select- 0- !Split- "-"- !Select- 2- !Split- "/"- !Ref "AWS::StackId"Description: Lambda function containing the logic for custom RBRHandler: index.lambda_handlerRole: !GetAtt LambdaRole.ArnRuntime: python3.9Environment:Variables:SCOPE: !Ref ScopeWEB_ACL_NAME: !Ref WebACLNameWEB_ACL_ID: !Ref WebACLIdRATE_BASED_RULE_NAME: !Ref RateBasedRuleNameCUSTOM_BLOCK_PERIOD: !Ref CustomBlockPeriodCONFIG_LOG_BUCKET: !Ref CustomRBRLogBucketCONFIG_LOG_KEY: blocked_ips_list.jsonIP_SET_ID_CUSTOM_V4: !GetAtt IPv4IPset.IdIP_SET_NAME_CUSTOM_V4: !Select- "0"- !Split [ "|" , Ref: IPv4IPset]IP_SET_ID_CUSTOM_V6: !GetAtt IPv6IPset.IdIP_SET_NAME_CUSTOM_V6: !Select- "0"- !Split [ "|" , Ref: IPv6IPset]Code:ZipFile: |import jsonimport boto3import loggingimport datetimeimport oswafv2_client = boto3.client('wafv2')s3_client = boto3.client('s3')def update_custom_ipset_and_config(log, latest_ipv4_blocked_list,latest_ipv6_blocked_list):try:# update the custom v4 IP setipv4_lock_token = get_lock_token(log, wafv2_client,os.getenv('IP_SET_ID_CUSTOM_V4'),os.getenv('IP_SET_NAME_CUSTOM_V4'))update_ip_set(log, wafv2_client,os.getenv('IP_SET_ID_CUSTOM_V4'),list(latest_ipv4_blocked_list.keys()),ipv4_lock_token,os.getenv('IP_SET_NAME_CUSTOM_V4'))# update the custom v6 IP setipv6_lock_token = get_lock_token(log, wafv2_client,os.getenv('IP_SET_ID_CUSTOM_V6'),os.getenv('IP_SET_NAME_CUSTOM_V6'))update_ip_set(log, wafv2_client,os.getenv('IP_SET_ID_CUSTOM_V6'),list(latest_ipv6_blocked_list.keys()),ipv6_lock_token,os.getenv('IP_SET_NAME_CUSTOM_V6'))except Exception as e:# log error messagelog.error("[update_custom_ipset_and_config] ""Error updating custom ipset.")raise etry:# create json object of the latest custom configlatest_custom_config = {'IPv4': latest_ipv4_blocked_list,'IPv6': latest_ipv6_blocked_list}byte_latest_custom_config = json.dumps(latest_custom_config).encode()# upload the config to s3s3_client.put_object(Bucket=os.getenv('CONFIG_LOG_BUCKET'),Body=byte_latest_custom_config,Key=os.getenv('CONFIG_LOG_KEY'))except Exception as e:# log error messagelog.error("[update_custom_ipset_and_config] ""Error uploading config to S3.")raise edef get_lock_token(log, wafv2_client, ip_set_id, name):try:ipv4_get_response = wafv2_client.get_ip_set(Scope=os.getenv('SCOPE'),Name=name,Id=ip_set_id)return ipv4_get_response['LockToken']except Exception as e:log.error(f"Error in get_lock_token: {e}")raisedef update_ip_set(log, wafv2_client, ip_set_id, addresses,lock_token, name):try:wafv2_client.update_ip_set(Scope=os.getenv('SCOPE'),Name=name,Id=ip_set_id,Description='Last Update: ' +datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%d %H:%M:%S %Z%z"),Addresses=addresses,LockToken=lock_token)except Exception as e:log.error("Error in update_ip_set: {}".format(e))raisedef sync_ip_from_rbr_to_custom_ipset(log, rbr_managed_ip_list,custom_managed_ip_config):# Get the current timestamp in UTC formatutc_now_timestamp = datetime.datetime.now(datetime.timezone.utc)# Convert the timestamp to stringutc_now_timestamp_str = utc_now_timestamp.strftime("%Y-%m-%d %H:%M:%S %Z%z")# Iterate over the managed IPs in the RBR listfor managed_ip in rbr_managed_ip_list:# If the IP is already in the custom IP configif managed_ip in custom_managed_ip_config.keys():# Get the timestamp when the IP was blocked in UTC formatutc_blocked_at = datetime.datetime.strptime(custom_managed_ip_config[managed_ip],"%Y-%m-%d %H:%M:%S %Z%z").astimezone(datetime.timezone.utc)# Calculate the difference in minutes between now and when the IP# was blockedtotal_diff_min = ((utc_now_timestamp - utc_blocked_at).total_seconds()) / 60# If the difference is greater than block period, update the timestampif round(total_diff_min) >= int(os.getenv('CUSTOM_BLOCK_PERIOD')):custom_managed_ip_config[managed_ip] = utc_now_timestamp_str# If the IP is not in the custom IP config, add it with the current# timestampelse:custom_managed_ip_config[managed_ip] = utc_now_timestamp_str# Create a new dictionary to store the latest blocked IPslatest_ip_blocked_list = {}# Iterate over the custom IP configfor blocked_ip, blocked_at_str in custom_managed_ip_config.items():# Get the timestamp when the IP was blocked in UTC formatutc_blocked_at = datetime.datetime.strptime(custom_managed_ip_config[blocked_ip],"%Y-%m-%d %H:%M:%S %Z%z").astimezone(datetime.timezone.utc)# Calculate the difference in minutes between now and when the IP# was blockedtotal_diff_min = ((utc_now_timestamp - utc_blocked_at).total_seconds()) / 60# If the difference is less than the custom block period#then add it to the latest blocked IPs listif round(total_diff_min) < int(os.getenv('CUSTOM_BLOCK_PERIOD')):latest_ip_blocked_list[blocked_ip] = blocked_at_strreturn latest_ip_blocked_listdef get_custom_config_file(log):try:# Get the custom config file from S3s3_response = s3_client.get_object(Bucket=os.getenv('CONFIG_LOG_BUCKET'),Key=os.getenv('CONFIG_LOG_KEY'))# Load the custom config file as a JSON objectcustom_managed_ip_config = json.loads(s3_response['Body'].read())except Exception as e:log.error("[get_custom_config_file] Error to get the custom config ""file from S3")log.error(e)# If there is an error, return an empty configcustom_managed_ip_config = {'IPv4': {}, 'IPv6': {}}return custom_managed_ip_configdef get_rbr_managed_ip_list(log):try:       # Get the list of IPs blocked by the rate based rulewafv2_response = wafv2_client.get_rate_based_statement_managed_keys(Scope=os.getenv('SCOPE'),WebACLName=os.getenv('WEB_ACL_NAME'),WebACLId=os.getenv('WEB_ACL_ID'),RuleName=os.getenv('RATE_BASED_RULE_NAME'))return wafv2_responseexcept Exception as e:log.error("[get_rbr_managed_ip_list] ""Error to get the list of IP blocked by rate based rule")log.error(e)# If there is an error, raise the exceptionraise edef lambda_handler(event, context):log = logging.getLogger()try:# Set Log Levellog.setLevel(logging.ERROR)# Get the list of IP blocked by rate based rulerbr_managed_list = get_rbr_managed_ip_list(log)# Get custom config file from S3custom_managed_ip_config = get_custom_config_file(log)# Update IP from rate based rule list to custom listlatest_ipv4_blocked_list = sync_ip_from_rbr_to_custom_ipset(log, rbr_managed_list['ManagedKeysIPV4']['Addresses'],custom_managed_ip_config['IPv4'])latest_ipv6_blocked_list = sync_ip_from_rbr_to_custom_ipset(log, rbr_managed_list['ManagedKeysIPV6']['Addresses'],custom_managed_ip_config['IPv6'])# Update latest blocked list to S3 and WAF IPsetupdate_custom_ipset_and_config(log, latest_ipv4_blocked_list,latest_ipv6_blocked_list)return {'statusCode': 200,'body': json.dumps('Update Success!')}except Exception as e:log.error(e)return {'statusCode': 500,'body': e}Timeout: 10Metadata:cfn_nag:rules_to_suppress:- id: W89reason: There is no need to run this lambda in a VPC- id: W92reason: There is no need for Reserved ConcurrencyLambdaRole:Type: "AWS::IAM::Role"Properties:AssumeRolePolicyDocument:Version: "2012-10-17"Statement:- Effect: "Allow"Principal:Service:- "lambda.amazonaws.com"Action: "sts:AssumeRole"ManagedPolicyArns:- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRolePolicies:- PolicyName: !Join- "-"- - "LambdaRolePolicy"- !Select- 0- !Split- "-"- !Select- 2- !Split- "/"- !Ref "AWS::StackId"PolicyDocument:Version: "2012-10-17"Statement:- Sid: "S3BucketPermissions"Effect: "Allow"Action:- "s3:PutObject"- "s3:GetObject"Resource:- !Sub 'arn:${AWS::Partition}:s3:::${CustomRBRLogBucket}/blocked_ips_list.json'- Sid: "WAFIPSetPermissions"Effect: "Allow"Action:- "wafv2:GetIPSet"- "wafv2:UpdateIPSet"Resource:- !GetAtt IPv6IPset.Arn- !GetAtt IPv4IPset.Arn- Sid: "WAFRBRPermissions"Effect: "Allow"Action: "wafv2:GetRateBasedStatementManagedKeys"Resource: !Sub- 'arn:${AWS::Partition}:wafv2:${AWS::Region}:${AWS::AccountId}:${WebACLSope}/webacl/${WebACLName}/${WebACLId}'- WebACLSope: !If [IsRegional, "regional", "global"]EventBridgeRule:Type: "AWS::Events::Rule"Properties:Name: !Join- "-"- - "EventBridgeRule"- !Select- 0- !Split- "-"- !Select- 2- !Split- "/"- !Ref "AWS::StackId"ScheduleExpression: "rate(1 minute)"State: "ENABLED"Targets:- Id: "CustomRBRLambdaFunction"Arn: !GetAtt CustomRBRLambdaFunction.ArnLambdaPermissionForEventBridge:Type: "AWS::Lambda::Permission"Properties:FunctionName: !Ref CustomRBRLambdaFunctionAction: "lambda:InvokeFunction"Principal: "events.amazonaws.com"SourceArn: !GetAtt EventBridgeRule.ArnOutputs:IPv4IPsetName:Description: IPv4 IPSet for custom rate based block ruleValue: !Select- "0"- !Split [ "|" , Ref: IPv4IPset]IPv6IPsetName:Description: IPv6 IPSet for custom rate based block ruleValue: !Select- "0"- !Split [ "|" , Ref: IPv6IPset]Conditions:IsRegional:!Equals [!Ref Scope, "REGIONAL"]

2. 新建堆栈

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
等待创建完成,查看相关参数资源
在这里插入图片描述
在这里插入图片描述

3. 回到waf确认,无误后开始测试

在这里插入图片描述

发现已经创建对应的ip规则集

在这里插入图片描述

添加到对应的waf中拒绝此ip集

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

开始测试

找一个终端,这里我使用cloudshell
使用我编写的脚本进行测试
在这里插入图片描述

$ cat waf.sh #!/bin/bash
while true; do curl -I  http://xxxxxx.cloudfront.net/xxxx.pngsleep 0.5
done##开始测试
# sh waf.sh 

在这里插入图片描述
查看是否在ip黑名单中
在这里插入图片描述
cdn备用域名测试
在这里插入图片描述
说明方案生效(从ip集中删除即可恢复访问)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/231438.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

短视频账号剪辑矩阵系统源码技术3年自研开发框架

短视频账号剪辑矩阵系统源码技术3年自研开发框架&#xff0c;这个市场截至到现在基本上违规开发的&#xff0c;没有正规接口开发的&#xff0c;基本上都已经筛选完了&#xff0c;目前各位技术者公司想要考察的话&#xff0c;只需要甄别3方面即可 1.剪辑是不是自己核心研发的&a…

正则表达式:简化模式匹配的利器

正则表达式&#xff1a;简化模式匹配的利器 一、正则表达式简介1.1 正则表达式介绍1.2 正则表达式使用场景 二、正则表达式语法2.1 正则表达式元字符和特性2.2 正则表达式常用匹配 三、正则表达式实战3.1 常见的正则表达式用法3.2 正则表达式的过滤用法3.3 正则表达式的代码用法…

Hadoop Single Node Cluster的安装

Hadoop Single Node Cluster的安装 安装JDK查看java -version更新本地软件包安装JDK查看java安装位置 设置SSH无密码登录安装hadoop下载安装设置hadoop环境变量修改hadoop配置设置文件设置core-site.xml设置YARN-site.xml设置mapred-site.xml设置HDFS分布式文件系统创建并格式化…

华为配置OSPF与BFD联动示例

组网需求 如图1所示&#xff0c;SwitchA、SwitchB和SwitchC之间运行OSPF&#xff0c;SwitchA和SwitchB之间的交换机仅作透传功能。现在需要SwitchA和SwitchB能快速感应它们之间的链路状态&#xff0c;当链路SwitchA-SwitchB发生故障时&#xff0c;业务能快速切换到备份链路Swi…

HTML---CSS美化网页元素

文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 一.div 标签&#xff1a; <div>是HTML中的一个常用标签&#xff0c;用于定义HTML文档中的一个区块&#xff08;或一个容器&#xff09;。它可以包含其他HTML元素&#xff0c;如文本、图像…

3.2 内容管理模块 - 课程分类、新增课程、修改课程

内容管理模块-课程分类、新增课程、修改课程 文章目录 内容管理模块-课程分类、新增课程、修改课程一、课程分类1.1 课程分类表1.2 查询树形结构1.2.1 表自连接1.2.2 SQL递归 1.3 Mapper1.4 Service1.5 Controller1.6 效果图 二、添加课程2.1 需求分析2.2 数据表2.2.1 课程基础…

嵌入式科普(5)ARM GNU Toolchain相关概念和逻辑

一、目的/概述 二、资料来源 三、逻辑和包含关系 四、Arm GNU Toolchain最常用的命令 嵌入式科普(5)ARM GNU Toolchain相关概念和逻辑 一、目的/概述 对比高集成度的IDE(MDK、IAR等)&#xff0c;Linux开发需要自己写Makefile等多种脚本。eclipse、Visual Studio等需要了解预处…

Selenium框架的使用心得(一)

最近使用selenium框架实现业务前端的UI自动化&#xff0c;在使用selenium时&#xff0c;有一些心得想要和大家分享一下~ Selenium是一款用于web应用程序测试的工具&#xff0c;常用来实现稳定业务的UI自动化。这里&#xff0c;不想对其发展历史做介绍&#xff0c;也不想用官方…

vscode 文件目录栏缩进

一个好的开发IDE&#xff0c;一定是让人赏心悦目的&#xff0c;这个赏心悦目也一定是包含层级目录的清晰明了&#xff01;不能像感冒的鼻涕一样一擤一摊子&#xff01;就像。。。。嗯&#xff0c;算了&#xff0c;断子还是不讲了&#xff0c;怕有些妹子投诉 或发消息批评我。。…

【ppt密码】ppt的密码忘了,怎么破解

PPT文件设置了保护密码&#xff0c;但是密码忘记了&#xff0c;无法打开PPT文件、无法编辑PPT文件了该怎么办&#xff1f;PPT文件的两种保护密码该如何解密&#xff1f; 首先是打开密码 网上有一种解决方法&#xff1a; 1、重新命名PPT文件&#xff0c;将其后缀改为zip格式&…

Shell编程基础 – C语言风格的Bash for循环

Shell编程基础 – C语言风格的Bash for循环 Shell Programming Essentials - C Style For Loop in Bash By JacksonML 循环是编程语言的基本概念之一&#xff0c;同样也是Bash编程的核心。当用户需要一遍又一遍地运行一系列命令直到达到特定条件时&#xff0c;例如&#xff1…

优点和缺点(以及在求职过程中如何处理它们)

你知道你会感到紧张&#xff0c;因为你真的很想要这份工作。当人力资源人员提出这个普遍存在的问题“你的优势和劣势是什么&#xff1f;”时&#xff0c;他们在寻找什么&#xff1f; 有哪些突出的优点和缺点示例&#xff1f;您如何将这些示例个性化&#xff0c;以免听起来像人…

leecode题解Golang版本-3-无重复字符最长子串

题目 无重复字符最长子串 给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串 的长度。 题解 func lengthOfLongestSubstring(s string) int {m : make(map[uint8]int)res : 0for l, r : 0, 0; r < len(s); r {m[s[r]]if v, ok : m[s[r]]; !ok || v 1…

智能优化算法应用:基于世界杯算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于世界杯算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于世界杯算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.世界杯算法4.实验参数设定5.算法结果6.参考文…

小程序自定义轮播图样式

小程序自定义轮播图样式以下是各案例&#xff0c;仅供大家参考。 效果展示&#xff1a; index.wxml代码&#xff1a; <view><!-- 轮播 --><view><swiper indicator-dots"{{indicatorDots}}"autoplay"{{autoplay}}" interval"{{…

数据可视化的魅力你了解吗?

你真的了解数据可视化吗&#xff1f;它所具备的真正魅力可能远远超出我们想象。数据可视化扩展了我们对数字和信息的简单理解&#xff0c;为我们揭示了一个无限可能的世界。今天我就以可视化行业的多年工作经验出发&#xff0c;和大家简单聊聊数据可视化的魅力。 数据的故事化…

STM32——时钟树与滴答计时器

STM32——时钟树与滴答计时器 使用的开发板为stm32F407VET6的芯片,主要介绍stm32的时钟树与滴答计时器的一些理论和一个自己编写的delay函数。 时钟树的结构图可以在STM32F4xx中文参考手册.pdf中的时钟这块找到。而滴答计时器是内核资源&#xff0c;需要到Cortex M3与M4权威指南…

【VScode】设置语言为中文

1、下载安装好vscode 2、此时可看到页面为英文&#xff0c;为方便使用可切换为中文 3、键盘按下 ctrlshiftP 4、在输入框内输入configure display language 5、选择中文&#xff0c;restart即可&#xff08;首次会有install安装过程&#xff0c;等待安装成功后重启即可&am…

算法设计与分析2023秋-头歌客观题-张超(云南农业大学)

文章目录 第一章客观题练习关于算法描述正确的是&#xff08; &#xff09;算法的要素包括&#xff08; &#xff09;分析算法&#xff0c;最重要的是衡量算法哪两个方面的效率&#xff08; &#xff09;算法的表示方法有&#xff08; &#xff09; 第二章客观题练习关于算法分…

nodejs+vue+微信小程序+python+PHP国漫推荐系统-计算机毕业设计推荐

使得本系统的设计实现具有可使用的价。做出一个实用性好的国漫推荐系统&#xff0c;使其能满足用户的需求&#xff0c;并可以让用户更方便快捷地国漫推荐。这个系统的设计主要包括系统页面的设计和方便用户互动的后端数据库&#xff0c;在开发后需要良好的数据处理能力、友好的…