使用网络防火墙从出站流量的服务器名称指示 (SNI) 中捕获 DNS 域名 - AWS Prescriptive Guidance

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

使用网络防火墙从出站流量的服务器名称指示 (SNI) 中捕获 DNS 域名

由 Kirankumar Chandrashekar (AWS) 创建

环境:PoC 或试点

技术:安全、身份、合规;网络;Web 和移动应用程序

工作负载:所有其他工作负载

AWS 服务:AWS Lambda;AWS Network Firewall;亚马逊 VPC;亚马逊日志 CloudWatch

Summary

此模式向您展示如何使用 Amazon Web Services (AWS) 网络防火墙来收集出站网络流量的 HTTPS 标头中的服务器名称指示 (SNI) 提供的 DNS 域名。Network Firewall 是一项托管服务,可以轻松地为 Amazon Virtual Private Cloud (Amazon VPC) 部署关键网络保护,包括能够使用防火墙来保护出站流量,该防火墙可以阻止不符合某些安全要求的数据包。保护特定 DNS 域名的出站流量称为出口过滤,这是一种监视并可能限制从一个网络到另一个网络的出站信息流的做法。

捕获通过网络防火墙的 SNI 数据后,您可以使用亚马逊 CloudWatch 日志和 AWS Lambda 将数据发布到生成电子邮件通知的亚马逊简单通知服务 (Amazon SNS) Simple Notification Service 主题。电子邮件通知包括服务器名称和其他相关 SNI 信息。此外,您可使用此模式的输出通过防火墙规则在 SNI 中按域名允许或限制 SNI 中的出站流量。有关更多信息,请参阅 Network Firewall 文档中的在 AWS Network Firewall 中使用有状态规则组

先决条件和限制

先决条件

注意:Network Firewall 可以使用以下任何 VPC 配置:

架构

下图显示了如何使用 Network Firewall 从出站网络流量中收集 SNI 数据,然后使用 CloudWatch 日志和 Lambda 将这些数据发布到 SNS 主题。

Network Firewall、 CloudWatch Lambda 和 Amazon SNS 之间的工作流程。

图表显示了以下工作流:

  1. 网络防火墙从出站网络流量的 HTTPS 标头中的 SNI 数据收集域名。

  2. CloudWatch 日志监控 SNI 数据,并在出站网络流量通过 Network Firewall 时调用 Lambda 函数。

  3. Lambda 函数读取 CloudWatch 日志捕获的 SNI 数据,然后将该数据发布到 SNS 主题。

  4. SNS 主题会向您发送包含 SNI 数据的电子邮件通知。

自动化和扩缩

技术堆栈

  • 亚马逊 CloudWatch 日志

  • Amazon SNS

  • Amazon VPC

  • AWS Lambda 

  • AWS Network Firewall

工具

Amazon Web Services

  • 亚马逊 CloudWatch 日志 — 您可以使用亚马逊 CloudWatch 日志来监控、存储和访问来自亚马逊弹性计算云 (Amazon EC2) 实例、AW CloudTrail S、Amazon Route 53 和其他来源的日志文件。

  • Amazon SNS – Amazon Simple Notification Service (Amazon SNS) 是一项托管服务,提供从发布者到订阅用户(也称为创建者和使用者)的消息传输。

  • Amazon Virtual Private Cloud (Amazon VPC) 可预置 Amazon Web Services Cloud 的逻辑隔离部分,您可以在其中启动您定义的虚拟网络中的 AWS 资源。这个虚拟网络与您在数据中心中运行的传统网络极其相似,并会为您提供使用Amazon云科技可扩展基础设施的优势。

  • AWS Lambda — AWS Lambda 是一项计算服务,可帮助您运行代码,无需预置或管理服务器。

  • AWS Network Firewall — AWS Network Firewall 是一项托管服务,可助您更轻松地为所有 Amazon VPC 部署必要的网络保护。

操作说明

任务描述所需技能

创建 CloudWatch 日志组。

  1. 登录 AWS 管理控制台并打开CloudWatch 控制台

  2. 在导航窗格中,选择日志组

  3. 选择操作,然后选择创建日志组

  4. 输入日志组的名称,然后选择创建日志组

有关更多信息,请参阅 CloudWatch 文档中的使用日志组和日志流

云管理员
任务描述所需技能

创建 SNS 主题。

要创建 SNS 主题,请按照 Amazon SNS 文档中的说明进行操作。

云管理员

为端点订阅 SNS 主题。

要订阅电子邮件地址作为您创建的 SNS 主题的端点,请按照 Amazon SNS 文档中的说明进行操作。对于协议,选择电子邮件/电子邮件-JSON注意:您也可以根据自己的要求选择不同的端点。

云管理员
任务描述所需技能

启用防火墙日志记录。

  1. 登录 AWS 管理控制台,打开 Amazon VPC 控制台

  2. 在导航窗格中的 NETEWORK FIREWALL下,选择防火墙

  3. 防火墙部分,选择要从出站流量的 SNI 中捕获服务器名称的防火墙。

  4. 选择防火墙详细信息选项卡,然后在记录部分中选择编辑。 

  5. 对于日志类型,选择警报。 在警报的日志目标中,选择CloudWatch 日志组。 

  6. 对于CloudWatch 日志组,搜索并选择您之前创建的日志组,然后选择保存

有关使用 CloudWatch 日志作为网络防火墙日志目标的更多信息,请参阅网络防火墙文档中的 Amazon CloudWatch 日志。 

云管理员
任务描述所需技能

创建有状态规则。

  1. 登录 AWS 管理控制台,打开 Amazon VPC 控制台

  2. 在导航窗格中的网络防火墙下,选择网络防火墙规则组

  3. 选择创建 Network Firewall 规则组

  4. 创建 Network Firewall 规则页面上,对于规则组类型,选择状态规则组注意:有关更多信息,请参阅使用 AWS Network Firewall 中的有状态规则组

  5. 有状态规则组部分,输入规则组的名称和描述。

  6. 容量中,设置要允许有状态规则组的最大容量(最多 30,000)。:创建规则组之后,您无法再更改此设置。有关如何计算容量的信息,请参阅在 AWS Network Firewall 中设置规则组容量。有关最大设置的信息,请参见 AWS Network Firewall 配额

  7. 对于状态规则组选项,请选择 5 元组

  8. 状态规则顺序部分选择默认

  9. 规则变量部分下,请保留默认值。

  10. 添加规则部分,为协议选择 TLS对于来源,选择任意。对于源端口,选择任何端口对于目的地,选择任意对于目标端口,选择任何端口。对于流量方向,请选择向前。对于操作,选择警报。选择添加规则

  11. 选择创建有状态规则组

云管理员

将状态规则与 Network Firewall 关联。

  1. 登录 AWS 管理控制台,打开 Amazon VPC 控制台

  2. 在导航窗格中的 NETWORK FIREWALL 下,选择防火墙

  3. 选择要从 SNI 捕获出站流量的服务器名称的防火墙。

  4. 有状态规则组部分,选择操作,然后选择添加非托管状态规则组。 

  5. 添加非托管有状态规则组页面,选择您之前创建的有状态规则组,然后选择添加有状态规则组

云管理员
任务描述所需技能

为 Lambda 函数创建代码。

在可以从 Network Firewall 读取出站流量的 CloudWatch 日志事件的集成开发环境 (IDE) 中,粘贴以下 Python 3 代码并<SNS-topic-ARN>替换为你的值:

import json import gzip import base64 import boto3 sns_client = boto3.client('sns') def lambda_handler(event, context): decoded_event = json.loads(gzip.decompress(base64.b64decode(event['awslogs']['data']))) body = ''' {filtermatch} '''.format( loggroup=decoded_event['logGroup'], logstream=decoded_event['logStream'], filtermatch=decoded_event['logEvents'][0]['message'], ) print(body) filterMatch = json.loads(body) data = [] if 'http' in filterMatch['event']: data.append(filterMatch['event']['http']['hostname']) elif 'tls' in filterMatch['event']: data.append(filterMatch['event']['tls']['sni']) result = 'Domain accessed ' + 1*' ' + (data[0]) + 1*' ' 'via AWS Network Firewall ' + 1*' ' + (filterMatch['firewall_name']) print(result) message = {'ServerName': result} send_to_sns = sns_client.publish( TargetArn=<SNS-topic-ARN>, #Replace with the SNS topic ARN Message=json.dumps({'default': json.dumps(message), 'sms': json.dumps(message), 'email': json.dumps(message)}), Subject='Server Name passed through the Network Firewall', MessageStructure='json' )

此代码示例解析 CloudWatch 日志内容并在 HTTPS 标头中捕获 SNI 提供的服务器名称。

应用程序开发人员

创建 Lambda 函数。

若要创建 Lambda 函数,请按Lambda 文档中的说明,然后为选择 Python 3.9 作为运行时系统

云管理员

将代码添加到 Lambda 函数。

要将您的 Python 代码添加到您之前创建的 Lambda 函数中,请按照 Lambda 文档中的说明进行操作。

云管理员

将 CloudWatch 日志作为触发器添加到 Lambda 函数。

  1. 登录 AWS 管理控制台,然后打开 Lambda 控制台

  2. 在导航窗格中,选择函数,然后选择您之前创建的函数。

  3. 函数概述部分中,选择添加触发器

  4. 添加触发器页面的触发器配置部分,选择CloudWatch 日志,然后选择添加

  5. 对于日志组,选择您之前创建的 CloudWatch 日志组。

  6. 筛选条件名称中,输入筛选条件的名称。

  7. 选择添加

  8. 在函数页面的配置选项卡上,在触发器部分,选择刚刚添加的触发器,然后选择启用

有关更多信息,请参阅 Lambda 文档中的将 Lambda 与 CloudWatch 日志配合使用

云管理员

添加 SNS 发布权限。

向 Lambda 执行角色添加 sns:Publish 权限,这样 Lambda 就可以调用 API 将消息发布到 SNS。 

  1. 找到您之前创建的 Lambda 函数的执行角色

  2. 将以下策略添加至您的 AWS Identity and Access Management (IAM) 角色:

{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowSNSPublish", "Effect": "Allow", "Action": [ "sns:GetTopicAttributes", "sns:Subscribe", "sns:Unsubscribe", "sns:Publish" ], "Resource": "*" } ] }
云管理员
任务描述所需技能

通过 Network Firewall 发送流量。

  1. 发送或等待 HTTPS 流量通过网络防火墙。

  2. 检查当流量通过网络防火墙时您从 AWS 收到的 SNS 通知电子邮件。该电子邮件中包含出站流量的 SNI 详细信息。例如,如果访问的域名为 https://aws.amazon.com 且订阅协议为 EMAIL-JSON,则根据上述 Lambda 代码生成的电子邮件将包含以下内容:

{ "Type": "Notification", "MessageId": "<messageID>", "TopicArn": "arn:aws:sns:us-west-2:123456789:testSNSTopic", "Subject": "Server Name passed through the Network Firewall", "Message": "{\"ServerName\": \"Domain 'aws.amazon.com' accessed via AWS Network Firewall 'AWS-Network-Firewall-Multi-AZ-firewall\"}", "Timestamp": "2022-03-22T04:10:04.217Z", "SignatureVersion": "1", "Signature": "<Signature>", "SigningCertURL": "<SigningCertUrl>", "UnsubscribeURL": "<UnsubscribeURL>" }

然后,按照亚马逊 CloudWatch 文档中的说明查看亚马逊 CloudWatch 中的 Network Firewall 警报日志。警报日志显示以下输出:

{ "firewall_name": "AWS-Network-Firewall-Multi-AZ-firewall", "availability_zone": "us-east-2b", "event_timestamp": "<event timestamp>", "event": { "timestamp": "2021-03-22T04:10:04.214222+0000", "flow_id": <flow ID>, "event_type": "alert", "src_ip": "10.1.3.76", "src_port": 22761, "dest_ip": "99.86.59.73", "dest_port": 443, "proto": "TCP", "alert": { "action": "allowed", "signature_id": 2, "rev": 0, "signature": "", "category": "", "severity": 3 }, "tls": { "subject": "CN=aws.amazon.com", "issuerdn": "C=US, O=Amazon, OU=Server CA 1B, CN=Amazon", "serial": "<serial number>", "fingerprint": "<fingerprint ID>", "sni": "aws.amazon.com", "version": "TLS 1.2", "notbefore": "2020-09-30T00:00:00", "notafter": "2021-09-23T12:00:00", "ja3": {}, "ja3s": {} }, "app_proto": "tls" } }
测试工程师