

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

# 使用网络防火墙从出站流量的服务器名称指示（SNI）中捕获 DNS 域名
<a name="use-network-firewall-to-capture-the-dns-domain-names-from-the-server-name-indication-sni-for-outbound-traffic"></a>

*Kirankumar Chandrashekar，Amazon Web Services*

## Summary
<a name="use-network-firewall-to-capture-the-dns-domain-names-from-the-server-name-indication-sni-for-outbound-traffic-summary"></a>

此模式向您展示如何使用 AWS Network Firewall 来收集出站网络流量的 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 中使用有状态规则组](https://docs.aws.amazon.com/network-firewall/latest/developerguide/stateful-rule-groups-ips.html)

## 先决条件和限制
<a name="use-network-firewall-to-capture-the-dns-domain-names-from-the-server-name-indication-sni-for-outbound-traffic-prereqs"></a>

**先决条件**
+ 一个活跃的 AWS 账户。
+ 已在 Linux、macOS 或 Windows 上安装并配置 [AWS 命令行界面（AWS CLI）](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html)版本 2。
+ 已在 Amazon VPC 中设置并配置 [Network Firewall](https://docs.aws.amazon.com/network-firewall/latest/developerguide/getting-started.html)，用于检查出站流量。您可以将 Network Firewall 配置为使用以下任何 VPC 配置：
  + [带有互联网网关的简单单区域架构](https://docs.aws.amazon.com/network-firewall/latest/developerguide/arch-single-zone-igw.html)
  + [带互联网网关的多区域架构](https://docs.aws.amazon.com/network-firewall/latest/developerguide/arch-two-zone-igw.html)
  + [带互联网网关和 NAT 网关的架构](https://docs.aws.amazon.com/network-firewall/latest/developerguide/arch-igw-ngw.html)

## 架构
<a name="use-network-firewall-to-capture-the-dns-domain-names-from-the-server-name-indication-sni-for-outbound-traffic-architecture"></a>

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

![\[Network Firewall、 CloudWatch Lambda 和 Amazon SNS 之间的工作流程。\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/patterns/images/pattern-img/9eb1e9e3-f459-4ea3-8e6d-60fec6b7ea98/images/1094b5f6-33e3-42bc-8fb8-7409b5b826b0.png)


下图显示了如下工作流：

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

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

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

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

**自动化和扩展**
+ 您可以使用 [AWS](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html) 通过使用[基础设施即代码 CloudFormation](https://docs.aws.amazon.com/whitepapers/latest/introduction-devops-aws/infrastructure-as-code.html)来创建此模式。

**技术堆栈**
+ Amazon CloudWatch 日志
+ Amazon SNS
+ Amazon VPC
+ AWS Lambda 
+ AWS Network Firewall

## 工具
<a name="use-network-firewall-to-capture-the-dns-domain-names-from-the-server-name-indication-sni-for-outbound-traffic-tools"></a>

**AWS 服务**
+ [亚马逊 CloudWatch 日志](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/WhatIsCloudWatchLogs.html) — 您可以使用亚马逊 CloudWatch 日志来监控、存储和访问来自亚马逊弹性计算云 (Amazon EC2) 实例、AWS CloudTrail、Amazon Route 53 和其他来源的日志文件。
+ [Amazon SNS](https://docs.aws.amazon.com/sns/latest/dg/welcome.html) – Amazon Simple Notiﬁcation Service (Amazon SNS) 是一项托管服务，提供从发布者到订阅用户（也称为创建者和使用者）的消息传输。
+ [Amazon Virtual Private Cloud（Amazon VPC）](https://docs.aws.amazon.com/vpc/latest/userguide/what-is-amazon-vpc.html)可预调配 AWS 云的逻辑隔离部分，您可以在其中启动您定义的虚拟网络中的 AWS 资源。此虚拟网络与您在自己的数据中心中运营的传统网络极其相似，您将获得使用 AWS 可扩展基础设施的优势。
+ [AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/welcome.html) — AWS Lambda 是一项计算服务，可帮助您运行代码，无需预置或管理服务器。
+ [AWS Networ](https://docs.aws.amazon.com/network-firewall/latest/developerguide/what-is-aws-network-firewall.html) k Firewall — AWS Network Firewall 是一项托管服务，可让您轻松地为所有亚马逊部署基本的网络保护 VPCs。

## 操作说明
<a name="use-network-firewall-to-capture-the-dns-domain-names-from-the-server-name-indication-sni-for-outbound-traffic-epics"></a>

### 为 Network Firewall 创建 CloudWatch 日志组
<a name="create-a-cloudwatch-log-group-for-network-firewall"></a>


| Task | 说明 | 所需技能 | 
| --- | --- | --- | 
| 创建 CloudWatch 日志组。 | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/patterns/use-network-firewall-to-capture-the-dns-domain-names-from-the-server-name-indication-sni-for-outbound-traffic.html)有关更多信息，请参阅 CloudWatch 文档中的[使用日志组和日志流](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/Working-with-log-groups-and-streams.html)。 | 云管理员 | 

### 创建 SNS 主题和订阅
<a name="create-an-sns-topic-and-subscription"></a>


| Task | 说明 | 所需技能 | 
| --- | --- | --- | 
| 创建一个 SNS 主题。 | 要创建 SNS 主题，请按照 [Amazon SNS 文档](https://docs.aws.amazon.com/sns/latest/dg/sns-create-topic.html#create-topic-aws-console)中的说明进行操作。 | 云管理员 | 
| 为端点订阅 SNS 主题。 | 要订阅电子邮件地址作为您创建的 SNS 主题的端点，请按照 [Amazon SNS 文档](https://docs.aws.amazon.com/sns/latest/dg/sns-create-subscribe-endpoint-to-topic.html)中的说明进行操作。对于**协议**，选择 [Email/Email-JSON](https://docs.aws.amazon.com/sns/latest/dg/sns-email-notifications.html)。您也可以根据自己的需求，选择另一个端点。 | 云管理员 | 

### 在 Network Firewall 中设置登录
<a name="set-up-logging-in-network-firewall"></a>


| Task | 说明 | 所需技能 | 
| --- | --- | --- | 
| 启用防火墙日志记录。 | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/patterns/use-network-firewall-to-capture-the-dns-domain-names-from-the-server-name-indication-sni-for-outbound-traffic.html)有关使用 CloudWatch 日志作为网络防火墙日志目标的更多信息，请参阅网络防火墙文档中的 [Amazon CloudWatch 日志](https://docs.aws.amazon.com/network-firewall/latest/developerguide/logging-cw-logs.html)。  | 云管理员 | 

### 在 Network Firewall 中设置状态规则
<a name="set-up-a-stateful-rule-in-network-firewall"></a>


| Task | 说明 | 所需技能 | 
| --- | --- | --- | 
| 创建有状态规则。 | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/patterns/use-network-firewall-to-capture-the-dns-domain-names-from-the-server-name-indication-sni-for-outbound-traffic.html) | 云管理员 | 
| 将状态规则与 Network Firewall 关联。 | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/patterns/use-network-firewall-to-capture-the-dns-domain-names-from-the-server-name-indication-sni-for-outbound-traffic.html) | 云管理员 | 

### 创建 Lambda 函数以读取日志记录
<a name="create-a-lambda-function-to-read-the-logs"></a>


| Task | 说明 | 所需技能 | 
| --- | --- | --- | 
| 为 Lambda 函数创建代码。 | 在可以从 Network Firewall 读取出站流量的 CloudWatch 日志事件的集成开发环境 (IDE) 中，粘贴以下 Python 3 代码并`<SNS-topic-ARN>`替换为你的值：<pre>import json<br />import gzip<br />import base64<br />import boto3<br />sns_client = boto3.client('sns')<br />def lambda_handler(event, context):<br />    decoded_event = json.loads(gzip.decompress(base64.b64decode(event['awslogs']['data'])))<br />    body = '''<br />    {filtermatch}<br />    '''.format(<br />        loggroup=decoded_event['logGroup'],<br />        logstream=decoded_event['logStream'],<br />        filtermatch=decoded_event['logEvents'][0]['message'],<br />    )<br />    print(body)<br />    filterMatch = json.loads(body)<br />    data = []<br />    if 'http' in filterMatch['event']:<br />        data.append(filterMatch['event']['http']['hostname'])<br />    elif 'tls' in filterMatch['event']:<br />        data.append(filterMatch['event']['tls']['sni'])<br />    result = 'Domain accessed ' + 1*' ' + (data[0]) + 1*' ' 'via AWS Network Firewall ' + 1*' '  + (filterMatch['firewall_name'])<br />    print(result)<br />    message = {'ServerName': result}<br />    send_to_sns = sns_client.publish(<br />        TargetArn=<SNS-topic-ARN>,          #Replace with the SNS topic ARN<br />        Message=json.dumps({'default': json.dumps(message),<br />                        'sms': json.dumps(message),<br />                        'email': json.dumps(message)}),<br />        Subject='Server Name passed through the Network Firewall',<br />        MessageStructure='json'<br />    )</pre>此代码示例解析 CloudWatch 日志内容并在 HTTPS 标头中捕获 SNI 提供的服务器名称。 | 应用程序开发人员 | 
| 创建 Lambda 函数。 | 若要创建 Lambda 函数，请按[Lambda 文档](https://docs.aws.amazon.com/lambda/latest/dg/getting-started.html#getting-started-create-function)中的说明，然后为选择 **Python 3.9** 作为**运行时系统**。 | 云管理员 | 
| 将代码添加到 Lambda 函数。 | 要将您的 Python 代码添加到您之前创建的 Lambda 函数中，请按照 [Lambda 文档](https://docs.aws.amazon.com/lambda/latest/dg/configuration-function-zip.html#configuration-function-update)中的说明进行操作。 | 云管理员 | 
| 将 CloudWatch 日志作为触发器添加到 Lambda 函数。 | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/patterns/use-network-firewall-to-capture-the-dns-domain-names-from-the-server-name-indication-sni-for-outbound-traffic.html)有关更多信息，请参阅 Lambda 文档中的[将 Lambda 与 CloudWatch 日志配合使用](https://docs.aws.amazon.com/lambda/latest/dg/services-cloudwatchlogs.html)。 | 云管理员 | 
| 添加 SNS 发布权限。 | 向 Lambda 执行角色添加 **sns:Publish** 权限，这样 Lambda 就可以调用 API 将消息发布到 SNS。 [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/patterns/use-network-firewall-to-capture-the-dns-domain-names-from-the-server-name-indication-sni-for-outbound-traffic.html)<pre>{<br />    "Version": "2012-10-17",		 	 	 <br />    "Statement": [<br />        {<br />            "Sid": "AllowSNSPublish",<br />            "Effect": "Allow",<br />            "Action": [<br />                "sns:GetTopicAttributes",<br />                "sns:Subscribe",<br />                "sns:Unsubscribe",<br />                "sns:Publish"<br />            ],<br />            "Resource": "*"<br />        }<br />    ]<br />}</pre> | 云管理员 | 

### 测试您的 SNS 通知功能
<a name="test-the-functionality-of-your-sns-notification"></a>


| Task | 说明 | 所需技能 | 
| --- | --- | --- | 
| 通过 Network Firewall 发送流量。 | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/patterns/use-network-firewall-to-capture-the-dns-domain-names-from-the-server-name-indication-sni-for-outbound-traffic.html)<pre>{<br />    "Type": "Notification",<br />    "MessageId": "<messageID>",<br />    "TopicArn": "arn:aws:sns:us-west-2:123456789:testSNSTopic",<br />    "Subject": "Server Name passed through the Network Firewall",<br />    "Message": "{\"ServerName\": \"Domain 'aws.amazon.com' accessed via AWS Network Firewall 'AWS-Network-Firewall-Multi-AZ-firewall\"}",<br />    "Timestamp": "2022-03-22T04:10:04.217Z",<br />    "SignatureVersion": "1",<br />    "Signature": "<Signature>",<br />    "SigningCertURL": "<SigningCertUrl>",<br />    "UnsubscribeURL": "<UnsubscribeURL>"<br />}</pre>然后，按照亚马逊[ CloudWatch 文档](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/SearchDataFilterPattern.html)中的说明查看亚马逊 CloudWatch 中的 Network Firewall 警报日志。警报日志显示以下输出：<pre>{<br />    "firewall_name": "AWS-Network-Firewall-Multi-AZ-firewall",<br />    "availability_zone": "us-east-2b",<br />    "event_timestamp": "<event timestamp>",<br />    "event": {<br />        "timestamp": "2021-03-22T04:10:04.214222+0000",<br />        "flow_id": <flow ID>,<br />        "event_type": "alert",<br />        "src_ip": "10.1.3.76",<br />        "src_port": 22761,<br />        "dest_ip": "99.86.59.73",<br />        "dest_port": 443,<br />        "proto": "TCP",<br />        "alert": {<br />            "action": "allowed",<br />            "signature_id": 2,<br />            "rev": 0,<br />            "signature": "",<br />            "category": "",<br />            "severity": 3<br />        },<br />        "tls": {<br />            "subject": "CN=aws.amazon.com",<br />            "issuerdn": "C=US, O=Amazon, OU=Server CA 1B, CN=Amazon",<br />            "serial": "<serial number>",<br />            "fingerprint": "<fingerprint ID>",<br />            "sni": "aws.amazon.com",<br />            "version": "TLS 1.2",<br />            "notbefore": "2020-09-30T00:00:00",<br />            "notafter": "2021-09-23T12:00:00",<br />            "ja3": {},<br />            "ja3s": {}<br />        },<br />        "app_proto": "tls"<br />    }<br />}</pre> | 测试工程师 | 