AWS VPC流量日志--概述和使用CloudWatch Logs Insights的例子

386 阅读7分钟

AWS VPC流量日志允许你记录VPC中网络接口之间的流量信息。此外,这些日志可以存储在AWS S3或发送到AWS CloudWatch Logs,而启用流量日志并不以任何方式影响网络接口的性能。

让我们简单回顾一下基本概念,以及可用的设置,并为VPC设置流量日志,将数据传输到CloduWatch Logs进行分析。

VPC流量日志概述

可以为整个VPC、一个子网或一个外部表面启用日志。如果为整个VPC启用 - 日志将为VPC的所有接口启用。

你可以使用流量日志的服务:

  • 弹性负载平衡
  • 亚马逊RDS
  • 亚马逊ElastiCache
  • 亚马逊Redshift
  • 亚马逊WorkSpaces
  • NAT网关
  • 转运网关

该数据被记录为一个 流量日志记录,并使用一个带有预定义字段的记录。

VPC流量日志的使用案例

用流量日志可以跟踪什么?

  • SecuirtyGroup/网络访问列表规则 - 被阻止的请求将被标记为REJECTED
  • 我们实施日志的目的是什么 - 了解VPC和服务之间的流量情况,以便了解谁消耗的流量最多,在哪里以及有多少跨A区的流量,等等
  • 监测系统的远程登录 - 监测端口22(SSH),3389(RDP)。
  • 端口扫描跟踪

流量日志记录--字段

日志中的每个条目都是关于聚合区间内收到的IP流量的数据,是一行用空格隔开的字段,每个字段都包含数据传输的信息,例如 - 源IP、目的IP和一个协议。

默认情况下,使用以下格式:

${version} ${account-id} ${interface-id} ${srcaddr} ${dstaddr} ${srcport} ${dstport} ${protocol} ${packets} ${bytes} ${start} ${end} ${action} ${log-status}

文档中的可用字段表,版本2栏中的所有内容都包含在默认格式中。

当创建流量日志时,我们可以使用默认格式,或者创建我们自己的格式--我们将在下面考虑。

VPC流量日志的局限性

  • 不能与EC2-Classic实例一起使用
  • 你不能为VPC对等物创建日志,如果它们通向不同账户的VPC。
  • 创建日志后,你不能改变其配置或记录格式

此外,请记住,。

  • 到亚马逊DNS的记录不被记录,但如果你自己的DNS被使用,就会被写入日志
  • 往返于169.254.169.254地址以获取EC2实例元数据的流量不被记录
  • EC2网络接口和AWS网络负载平衡器接口之间的流量不被记录。

请参阅流量日志限制中的所有限制。

创建VPC流量日志

要创建一个流量日志,我们需要指定:

  • 我们要写日志的资源 - VPC、子网或特定网络接口
  • 我们要记录的流量类型(接受的流量,拒绝的流量,或所有流量)
  • 我们将把数据写到哪里--写到S3桶,或者写到CloudWatch日志。

现在,让我们看看CloudWatch Logs发生了什么,下次我们将尝试在Kibana中进行可视化。

CloudWatch Logs日志组

创建一个日志组:

IAM策略和IAM角色

为了让Flow Logs服务能够写入我们的CloudWatch,我们需要配置其访问权限。

进入AWS IAM,并创建一个IAM策略和一个IAM角色。

从一个IAM策略开始:

添加规则:

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

保存:

现在,创建一个IAM角色。

进入IAM角色,创建一个新的角色,类型为EC2:

找到我们在上面创建的策略,并附加上它:

设置其名称,保存:

进入角色信任关系 (见AWS: IAM AssumeRole - описание, примеры),编辑它 - 对于Service 字段,设置vpc-flow-logs.amazonaws.com

设置:

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

保存:

VPC - 启用流量日志

最后,去VPC启用日志 - 点击流量日志>创建

设置其名称、过滤器间隔

目的地选择CloudWatch日志,指定日志组和IAM角色:

格式 - 保留默认

检查状态

几分钟后,我们将看到我们的数据:

在日志组中,你可以找到第一个由弹性网络接口命名的数据流,数据就是从那里来的:

CloudWatch Logs Insights

让我们快速浏览一下CloudWatch Logs Insights。

点击查询以获得一些提示:

例如,找到前15名的主机,这些主机提供了大部分的数据包:

或者按传输的数据量:

stats sum(bytes) as BytesSent by srcAddr, dstAddr
| sort BytesSent desc

好的,这很好。但是其他的形式呢?

例如,我想看到一个请求的方向(出口/出口),以及pkt-dstaddr 字段的值。

VPC流量日志 - 自定义格式

请看更多关于流量日志记录的例子

现在,我们可以设置以下格式:

region vpc-id az-id subnet-id instance-id interface-id flow-direction srcaddr dstaddr srcport dstport pkt-srcaddr pkt-dstaddr pkt-src-aws-service pkt-dst-aws-service traffic-path packets bytes action

在CloudWatch日志中创建一个新的日志组,将其称为bttrm-eks-dev-1-21-vpc-fl-custom,不要忘记保留:

回到VPC,创建一个新的流量日志,并将其称为bttrm-eks-dev-1-21-vpc-fl-custom

选择自定义格式和字段,这是我们想要看到的。在这样做的时候,要考虑到你在这里指定的字段的顺序将被用来排列日志中的记录。

也就是说,如果第一个字段是 "区域" - 那么在最终的日志中,它也将被设置为第一个字段:

结果是:

${region} ${vpc-id} ${az-id} ${subnet-id} ${instance-id} ${interface-id} ${flow-direction} ${srcaddr} ${dstaddr} ${srcport} ${dstport} ${pkt-srcaddr} ${pkt-dstaddr} ${pkt-src-aws-service} ${pkt-dst-aws-service} ${traffic-path} ${packets} ${bytes} ${action}

流量日志自定义格式和CloudWatch日志洞察力

但是,如果我们现在去CloudWatch Logs Insights,并尝试之前使用的任何查询,我们将不会得到我们设置的字段:

所以,我们可以看到数据,但我们如何将其分割成字段?

在我们的项目中,我认为我们不会经常使用CloudWatch Logs,很可能数据会被发送到S3桶,然后再发送到(logz.io),因此,我不会在这里深入讨论,但让我们看看操作原理--它在以后与ELK的工作中会很有用。

CloudWatch Logs默认创建了几个元字段,我们可以在请求中使用:

  • @message:"原始 "数据--文本中的整个消息
  • @timestamp: 事件发生的时间
  • @logStream: 一个sLog流的名称

为了让自定义格式看到这些字段,我们需要使用 parse并把@message ,这样它就会按我们指定的字段解析内容:

parse @message "* * * * * * * * * * * * * * * * * * *" 
| as region, vpc_id, az_id, subnet_id, instance_id, interface_id, 
| flow_direction, srcaddr, dstaddr, srcport, dstport, 
| pkt_srcaddr, pkt_dstaddr, pkt_src_aws_service, pkt_dst_aws_service, 
| traffic_path, packets, bytes, action 
| sort start desc

在这里,@message 中的星号 "*" 的数量必须是相同的,与我们设置的字段一样多 -${vpc-id} и т.д.

另外,字段的名称必须不包含破折号。例如,我们需要把${vpc-id} 的名称作为vpc_id (或vpcID - 随你喜欢)。

检查一下:

哇!现在,我们得到了所有的字段:

除了parse ,我们还可以使用filterdisplaystats 。请参阅CloudWatch Logs Insights查询语法中的所有内容。

Logs Insights例子

让我们试着做几个查询,例如 - 获取所有被SecuirtyGroup/Network Access List阻止的请求 - 它们将被标记为REJECTED。

让我们来看看我们之前的查询:

parse @message "* * * * * * * * * * * * * * * * * * * * * *" 
| as start, end, region, vpc_id, az_id, subnet_id, instance_id, interface_id, 
| flow_direction, srcaddr, dstaddr, srcport, dstport, protocol, 
| pkt_srcaddr, pkt_dstaddr, pkt_src_aws_service, pkt_dst_aws_service, 
| traffic_path, packets, bytes, action

并在那里添加:

  • filter action="REJECT"
  • stats count(action) as redjects by srcaddr
  • sort redjects desc

这里:

  • 通过应用于数据包的操作进行过滤 - 选择所有的REJECTED
  • 通过提交的动作计算事件的数量,通过源的IP地址选择,并在redjects 列中显示它
  • 并按拒绝数排序

因此,现在的完整查询将是:

parse @message "* * * * * * * * * * * * * * * * * * *" 
| as region, vpc_id, az_id, subnet_id, instance_id, interface_id, 
| flow_direction, srcaddr, dstaddr, srcport, dstport, 
| pkt_srcaddr, pkt_dstaddr, pkt_src_aws_service, pkt_dst_aws_service, 
| traffic_path, packets, bytes, action 
| filter action="REJECT" 
| stats count(action) as redjects by srcaddr 
| sort redjects desc

以及它的结果:

我们还可以使用负数过滤器,并将其与and/or 操作符相结合。

例如,要从输出中删除所有以162.142.125开头的IP - 添加一个过滤器filter (srcaddr not like "162.142.125.")

...
| filter action="REJECT"
| filter (srcaddr not like "162.142.125.")
| stats count(action) as redjects by srcaddr
| sort redjects desc

样本查询

并添加一个过滤器,只选择进入的请求 -flow_direction ==ingress

...
| filter action="REJECT"
| filter (srcaddr not like "162.142.125.") and (flow_direction like "ingress")
| stats count(action) as redjects by flow_direction, srcaddr, dstaddr, pkt_srcaddr, pkt_dstaddr
| sort redjects desc

现在,我们得到了被拒绝的请求的顶部,当安全组或VPC网络访问列表规则发挥作用时。

让我们检查一下dstaddr 中的IP是什么 - 谁是最终的目的地?

进入EC2 > 网络接口,通过私人IP找到:

找到 "Elastic IP地址所有者":

OK,是负载均衡器中的一个。

如果在AWS中找不到一个IP,它可能是一个Kubernetes端点,用以下方法检查它:

kubectl get endpoints --all-namespaces | grep 10.1.55.140

dev-ios-check-translation-nsios-check-translation-backend-svc 10.1.55.140:300058d

dev-ios-check-translation-nsios-check-translation-frontend-svc 10.1.55.140:8058d

实际上,这就是全部。