生成VPC Flowlog并输出到CloudWatch用于分析VPC流量

一、背景

VPC Flowlog是用于采集VPC内四层网络流量的工具。其采集对象包括EC2、NLB、RDS等之间和外部网络之间的流量。VPC Flowlog是OSI模型第四层采集工具,会记录源地址、源端口、目标地址、目标端口、协议、传输数据量等信息,但不会记录OSI模型第七层定义的域名、网址等属于应用层定义的日志,也不会记录发送的数据本体。VPC Flowlog常用于排查EC2相关网络错误。

本文介绍如何开启VPC Flowlog并输出到CloudWatch用于查看VPC内流量。

根据官网文档,如下网络流量不被记录:

  • 实例与 Amazon DNS 服务器联系时生成的流量。如果您使用自己的 DNS 服务器,则将记录到该 DNS 服务器的所有流量。
  • Windows 实例为 Amazon Windows 许可证激活而生成的流量。
  • 实例元数据传入和传出 169.254.169.254 的流量。
  • Amazon Time Sync Service 的传入和传出 169.254.169.123 的流量。
  • DHCP 流量。
  • 镜像流量。
  • 到默认 VPC 路由器的预留 IP 地址的流量。
  • 在终端节点网络接口和 Network Load Balancer 网络接口之间的流量。

VPC Flowlog记录的字段信息,是遵循Flowlog的版本2、版本3、版本4、版本5等版本规范。在本文末尾的参考文档提供高了各版本记录的不同字段的说明。

下面开始配置。

二、配置

1、配置IAM Policy

进入IAM服务,点击左侧菜单Policy策略,点击右侧的创建按钮,然后选择自定义,点击JSON按钮。如下截图。

输入如下IAM Policy:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents",
        "logs:DescribeLogGroups",
        "logs:DescribeLogStreams"
      ],
      "Resource": "*"
    }
  ]
}   

以上Policy命名为flowlog即可。

2、配置IAM Role

进入IAM服务,点击左侧菜单Role角色,点击右侧创建角色按钮。

点击页面中央的Custom trust policy自定义信任策略按钮。然后在下方输入如下策略。如下截图。

策略如下:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "vpc-flow-logs.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
} 

输入信任策略后点击向导下一步。

在选择关联的策略位置,选择上一步创建的flowlog策略。如下截图。

最后设置IAM Role角色的名称是vpcflowlog。完成IAM Role创建。

3、配置CloudWatch Log Groups作为Flowlog的投递目标

进入CloudWatch服务,点击左侧的Log Grous日志组菜单,点击新建。如下截图。

在创建界面输入名称,然后选择数据保留时间为7天。因为当VPC内EC2较多的时候,Flowlog数据量大,如果原则长期保留会占用较大空间导致存储成本上升,因此这里选择较短的保留时间。

配置CloudWatch完成。

4、生成VPC Flowlog

进入VPC服务界面。有两个位置可以创建Flowlog,分别在选中VPC后的操作菜单,和下方的标签页。如下截图。

输入Flowlog的名字,例如my-flowlog。继续向下滚动页面。如下截图。

在时间聚合维度的位置,选择1分钟。在目标位置,选择上一步创建的CloudWatch Log Groups的名字。继续向下滚动页面。如下截图。

在IAM Role位置,选择上一步生成的IAM Role角色的名字。在日志格式位置,选择AWS默认格式。注意默认格式是所谓的版本2规范,如果需要版本3规范,请使用自定义格式。最后点击右下角创建按钮。如下截图。

创建完成,界面上可以看到日志已经输出到CloudWatch的日志组。

三、在CloudWatch上查看Flowlog

1、查看原始日志

进入CloudWatch服务。点击左侧的Log groups日志组按钮,搜索上一步创建的日志组的名称,例如输入关键字vpc,即可搜索出来。点击进入。如下截图。

在日志组中过,可以看到许多单条的Log stream,每一个日志流对应着一个ENI网卡,也就是EC2/RDS等服务的网卡。点击进入。如下截图。

进入单个日志流,即可看到本ENI网卡的4层的flowlog日志。如下截图。

这里简述以上字段分别是:日志规范版本,AWS账号,ENA网卡编号,源地址,目标地址,源端口,目标端口,协议,Package包数,传输字节数,起始时间戳(Unix日期),结束时间戳(Unix日期),放行还是通过,日志写入状态。

关于AWS默认的Flowlog的格式和字段说明,请参考本文末尾的官方文档。

2、使用Log Insight查询

由于原始日志格式不便于阅读,且原始日志是分成单个ENI网卡的,对于很多EC2的网络环境不便于查看。因此可使用Log Insight功能来查询。

进入Log Insight服务。

首先搜索Log groups,搜索出来上一步的名字,然后点击choose a sample query查看查询代码例子。如下截图。

在右侧弹出的对话框内,可以看到许多例子。这里选择VPC Flow Logs菜单下,找到Top 10 byte transfers by source and destination IP addresses也就是传输量最大的前十名排行的查询语句,点击下方的Apply按钮。这个查询语句就会自动复制到左侧的查询框内。然后点击Run query按钮运行查询。如下截图。

查询结果已经返回,这是在1小时时间段内,按传输流量排行的TOP10的IP。注意这个数据中间有一段没有查询出来,这是因为这个截图的测试期间,停止了VPC Flowlog功能,有一段时间没有生成日志。如下截图。

3、优化查询

以下查询字段基于VPC Flowlog的版本2规范来查询。如果您需要更多字段,那么请在上文的配置中,使用输入日志版本3规范自定义字段的方式来选择要打印到日志中的字段。具体字段定义参考本文末尾的文档。

(1) 修改查询时间范围

现在优化查询范围。将右上角的时间范围从1小时选择到1天。将图中的查询语句,查出来的传输字节数结果从Byte除以1000再除以1000,这样单位变成MB更直观。如下截图。

修改后的查询代码如下:

stats sum(bytes)/1000/1000 as MBTransferred by srcAddr, dstAddr
| sort bytesTransferred desc
| limit 10

再次查询即可获得一天内传输流量最高的源和目标地址。查询结果如下。

以上查询结果可看到,VPC与互联网IP通信(出站和入站)也会被记录。记录下来的互联网流量的原始地址和目标地址,主要看网络流量是经过Elastic IP直接去外网、还是经负载均衡的,此外负载均衡的网络和target group目标组的模式也不一样,由此记录下来的源地址访问也各不相同。

(2) 根据源地址/目标地址范围进行查询

如果希望查询本VPC与其他VPC,或者本VPC与IDC通过专线/VPN互联时候另一侧的流量,可以添加IP地址范围条件。

fields @timestamp, srcAddr, srcPort, dstAddr, dstPort, protocol, action
| stats sum(bytes)/1000/1000 as MBtransferred by srcAddr, srcPort, dstAddr, dstPort, protocol, action, bin(1m)
| filter srcAddr like "172.16."
| filter dstAddr like "172.31."
| sort MBtransferred desc
| limit 100

这个查询结果将返回在特定时间窗口内的特定来源地址和VPC之间传输的流量(单位是MB)的TOP10排行。查询信息将显示目标地址和源地址的端口号,并显示协议(1代表ICMP,6代表TCP,17代表UDP)。如下截图。

注意:具体协议代号的说明,请参考本文末尾IANA的官方定义。

另外需要注意,图中的纵轴是表示命中的日志条目数,不是流量例如。例如9:00-9:01的一分钟内,flowlog记录了2条符合这个查询结果的日志,这里就是显示2。如果记录了200条,这里就显示200个Record。

(3) 查询某时间段一分钟内流量最高的来源

首先查询近一段时间流量最高的时间是哪一分钟(具体到一分钟颗粒度),查询条件限定了地址范围,这样可用于特定方向流量的筛选。

fields @timestamp, srcAddr, srcPort, dstAddr, dstPort, protocol, action
| stats sum(bytes)/1000/1000 as MBtransferred by bin(1m)
| filter srcAddr like "172.16."
| filter dstAddr like "172.31."
| sort MBtransferred desc
| limit 100

由此可看到16:22这一分钟流量最高。如下截图。

那么去查询这一分钟内,谁的传输字节数最高。此时可以调整右上角的时间筛选范围,然后执行如下语句:

fields @timestamp, srcAddr, srcPort, dstAddr, dstPort, protocol, action
| stats sum(bytes)/1000/1000 as MBtransferred by srcAddr, srcPort, dstAddr, dstPort, protocol, action, bin(1m)
| filter srcAddr like "172.16."
| filter dstAddr like "172.31."
| sort MBtransferred desc
| limit 100

此时可以看到查询结果的数据是只显示这一分钟内的所有传输,即可看到谁占用带宽最高。如下截图。

由此就定位到了一分钟时间段内传输流量最高的IP地址。

(4) 查询向外流量最多的IP(定位通过NAT Gateway的流量)

如果本VPC内产生了大量的通过NAT Gateway的流量,那么可以用关键字来查询目标地址不是本VPC的流量。

fields @timestamp, srcAddr, srcPort, dstAddr, dstPort, protocol, action
| stats sum(bytes)/1000/1000 as MBtransferred by srcAddr, srcPort, dstAddr, dstPort, protocol, action, bin(1m)
| filter srcAddr like "172.31."
| filter dstAddr not like "172.31."
| sort MBtransferred desc
| limit 100

将其中的IP地址修改为本VPC的CIDR,即可看到去往本VPC之外的流量。

四、参考文档

如何将 CloudWatch Logs Insights 查询用于我的 VPC 流日志?

https://repost.aws/zh-Hans/knowledge-center/vpc-flow-logs-and-cloudwatch-logs-insights

VPC Flowlog 流日志记录的格式和字段说明

https://docs.aws.amazon.com/zh_cn/vpc/latest/userguide/flow-logs.html#flow-log-records

CloudWatch Logs Insights 支持的日志和发现的字段

https://docs.aws.amazon.com/zhcn/AmazonCloudWatch/latest/logs/CWLAnalyzeLogData-discoverable-fields.html

在VPC Flowlog中Protocol字段的定义

http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml

CloudWatch Log Insight查询语法

https://docs.aws.amazon.com/zh_cn/AmazonCloudWatch/latest/monitoring/cloudwatch-metrics-insights-querylanguage.html