技术分享丨利用IP-ranges自动化通知

2023-05-30 11:00

当前,某客户对于安全较为看重,希望对于所有的进出站都通过IP控制,那对于亚马逊云科技来说,是有提供公有的IP池,同时会记录在一个ip-range (https://ip-ranges.amazonaws.com/ip-ranges.json)文件,但是对于这些IP不是永久不变的,在一些服务更新的情况下,IP可能会发生增加,那此时依靠人力去过滤是比较浪费时间,那可以通过以下方法,实现自动化通知的方式。

该方法的整体思路是将更改通知的SNS主题设定为AWS Lambda的触发器,Lambda获取到ip-range的链接发生变更时,会将其与存储在AWS S3上的文本文件中的IP进行对比,如果IP发生更改时,函数会使用新的IP更新S3文本文件,并发送SNS通知。



创建SNS

创建一个SNS设定邮箱可以接收发生变更的通知,在与后面相同的Lambda区域创建SNS,并设定邮箱,并验证。本次创建一个SNS-IP的主题并设定通知名称为IP-List。


创建Lambda

本次在弗吉尼亚区域创建lambda函数并使用Python 3.7版本,对于函数名称可以自定义,对于函数内容如下,对于这个函数,在函数的最后,可以设定SNS通知的样式,如本次是查看us-east-1区域API GATEWAY的公网IP段。

上下滑动阅读更多内容



  • from __future__ import print_functionimport osimport jsonimport botocore.vendored.requests as requestsimport boto3print('Loading function')def lambda_handler(event, context):    #print("Received event: " + json.dumps(event, indent=2))    #Read the json url key from the AWS SNS IP ranges notification.    #url = event['url']    #print("From SNS url: " + url)            url = 'https://ip-ranges.amazonaws.com/ip-ranges.json'    #Load the json content from the url    r = requests.get(url)    data = json.loads(r.content)    #print(data)    ipv4addresses = data["prefixes"]    newIps = []    # Iterate over the ip addresses and filter the required ip addresses.     # The region and service are supplied as environment variables to the lambda function    for item in ipv4addresses:        ip = item['ip_prefix']        region = item['region']        service = item['service']        if region == os.environ['region'] and service == os.environ['service'] :            print("ip:" + ip + "   Region:" + region + "   Service:" + service)            newIps.append(ip)                # Print the new IP ranges for S3 service    for ip in newIps:        print("New Ip: ", ip)            # Load the previous/current IPs stored in the S3 text file.    s3 = boto3.client('s3')    bucket = os.environ['bucket']    key = os.environ['key']    print("bucket: "+ bucket + " File: "+key)    data = s3.get_object(Bucket=bucket, Key=key)    contents = data['Body'].read().decode('utf-8')    currentIps = contents.split('\n')    for ip in currentIps:        print("Current Ip: ", ip)        #check if exisitngs ips in s3 file and current ips are same.    ifset(newIps) == set(currentIps) :        print("There are no changes in S3 IP Ranges")    else:        print("S3 IP Ranges changed")        newIpsLength = len(newIps)        index = 0        # Write the new IPS to a temporary file in Lambda.         with open('/tmp/awsips.txt', 'w') as data:            for ip in newIps:                if index == (newIpsLength - 1) :                    data.write(ip)                else:                    data.write(ip+ "\n")                index = index + 1                # Upload the temporary file to S3        with open('/tmp/awsips.txt', "rb") as f:            s3.upload_fileobj(f, bucket, key)        print("S3 File upload successful.")        # Send SNS notification to notify about the IP address changes.        publishToSNSTopic(newIps)    return urldef publishToSNSTopic(s3ips):    message = {"foo": "bar"}    arn = os.environ['snsarn']    client = boto3.client('sns')    response = client.publish(        TargetArn=arn,        Message=json.dumps({'default': json.dumps(message),'email': 'AWS API-GATEWAY IP Ranges Changed. New IPs are in "awss3ips" s3 bucket. New Ips: '+ ', '.join(s3ips)}),        Subject='AWS API-GATEWAY IPs Changed',        MessageStructure='json'    )



对于该Lambda所使用的权限,参考以下权限,其中S3是存放您存储了IP的txt文档的存储桶,Lambda函数需要调用这个桶中的txt文件进行对比,如果有差异,将新的IP写入桶中的这个文件,同时需要调用SNS服务。


上下滑动阅读更多内容


  • {    "Version": "2012-10-17",    "Statement": [        {            "Effect": "Allow",            "Action": [                "s3:ListAllMyBuckets",                "s3:GetBucketLocation"            ],            "Resource": "*"        },        {            "Effect": "Allow",            "Action": "s3:*",            "Resource": [                "arn:aws:s3:::awsapiips",                "arn:aws:s3:::awsapiips/*"            ]        },        {            "Action": [                "sns:Publish",                "sns:Subscribe"            ],            "Effect": "Allow",            "Resource": [                "*"            ]        }    ]}



配置Lambda

1 配置触发器

对于触发器,官方提供了一个SNS主题

“arn:aws:sns:us-east-1:806199016981:AmazonIpSpaceChanged”,当发生了更改时,可以借助这个SNS主题进行触发Lambda函数


参考链接:

https://docs.aws.amazon.com/vpc/latest/userguide/aws-ip-ranges.html#subscribe-notifications


配置环境变量

对于上述的Lambda函数,需要设定一些环境变量给与函数的引用,变量内容如下

bucket:存储着txt文件的存储桶

key:存放ip的txt文档

region:需要获取ip地址更新的区域

service:需要获取ip地址更新的服务

snsarn:需要进行接收通知的SNS,SNS为之前建立的SNS的arn

根据上述变量,在同名桶中上传同名文件,本次只上传空文件,txt文件中没有任何内容,可以通过大小0B判断这个txt是空的


1 验证

该代码可以直接进行测试,代码会获取ip range的链接“https://ip-ranges.amazonaws.com/ip-ranges.json”并将获取到需要的IP与txt文本中的内容进行对比

测试完成后会,会显示“执行结果:成功”,并且在日志输出会显示需要的IP段

这时查看S3桶中的文件,该文件大小发生改变,说明文件发生了更改,同时查看文件内容,发现已经将对应的IP填入其中

同时设定的接受通知的邮箱,可以发现已经接收到了更改的邮件


结论

通过以上方法,可以在ip-range发生更改时,做到及时通知,并可以获取到指定服务的公网IP,对于某一些特殊场景需要指定Public IP提供了一种通知的方式





云与应用现代化
——
扫描关注微信公众号
获取更多云端资讯
联系我们
——

模板表单-2(1)

  • 姓名*

  • 电话*

  • 邮箱*

  • 公司*

  • 职称*

  • 地址*

  • 需求*