3. VPC Flow Logs采集与解析实战
VPC Flow Logs 是 AWS 网络可观测性体系中最基础、也最容易被低估的数据源。它记录的是弹性网卡(ENI)层面的 IP 流量元数据——不是包内容,而是“谁在什么时间、通过哪个接口、以什么协议、向谁发了多少字节、结果是被接受还是被拒绝”。理解这一点非常关键:Flow Logs 回答的是“连接级事实”,而不是“应用级语义”。因此它最适合用来做安全排查、连通性验证、异常流量发现和成本归因,而不是直接判断某个 HTTP 请求返回了 500。
采集前必须先明确三个决策:采集范围、目标存储、字段格式。采集范围可以是 VPC、子网或单个 ENI;目标可以是 CloudWatch Logs 或 S3。二者定位不同:CloudWatch Logs 适合近实时查询与告警,保留期短、按摄取与存储计费;S3 适合长期归档与 Athena 批量分析,成本低、可对接分区与生命周期策略。字段格式则决定后续能查什么——默认格式只含版本、账户、接口、源/目的地址与端口、协议、包数、字节数、起止时间、动作、日志状态;自定义格式可追加 tcp-flags、pkt-srcaddr、flow-direction、traffic-path、region、az-id、sublocation-type 等字段,用于区分同区域/跨区域、入站/出站、以及流量是否经过中间设备。
tcp-flags、flow-direction、traffic-path、pkt-srcaddr、pkt-dstaddr。这些字段能把“被拒绝”进一步细化为“被安全组拒绝”还是“被 NACL 拒绝”,也能识别经过 NAT 或网关负载均衡器后的真实源地址。下面这张图展示了从 ENI 产生流记录,到 CloudWatch Logs 与 S3 两条消费路径,再到 Logs Insights 与 Athena 两类查询引擎的完整数据流关系。图中同时标注了关键字段在两条路径中的落点,便于对照理解。
字段解析是实战的核心。以一条典型记录为例:
2 123456789012 eni-0a1b2c3d 10.0.1.15 203.0.113.88 49152 443 6 12 840 1620000000 1620000060 ACCEPT OK
逐字段读:版本 2;账户 123456789012;接口 eni-0a1b2c3d;源地址 10.0.1.15(内网实例);目的地址 203.0.113.88(外部服务);源端口 49152(客户端临时端口);目的端口 443(HTTPS);协议 6(TCP);12 个包、840 字节;起止时间戳;动作 ACCEPT;日志状态 OK。若把 action 换成 REJECT,则说明流量到达了 ENI 但被安全组或 NACL 拒绝——此时要结合 flow-direction 判断是入站被拒还是出站被拒,再对照安全组规则定位。
在 CloudWatch Logs Insights 中,查询语法围绕 fields、filter、stats、sort、limit 展开。例如要找出最近一小时内被拒绝次数最多的目的端口:
fields @timestamp, dstport, action
| filter action = "REJECT"
| stats count(*) as rejectCount by dstport
| sort rejectCount desc
| limit 20
若要排查某台实例的出站异常,可先按源地址过滤,再按目的地址聚合字节数:
fields @timestamp, srcaddr, dstaddr, dstport, bytes
| filter srcaddr = "10.0.1.15" and action = "ACCEPT"
| stats sum(bytes) as totalBytes by dstaddr, dstport
| sort totalBytes desc
在 S3 + Athena 路径上,第一步是建表。Flow Logs 以空格分隔,需用 ROW FORMAT DELIMITED FIELDS TERMINATED BY ' ',并指定 LOCATION 指向 S3 前缀。若启用了分区,还需 MSCK REPAIR TABLE 或 ALTER TABLE ADD PARTITION 让 Athena 识别分区,否则会全量扫描,成本和延迟都会显著上升。
CREATE EXTERNAL TABLE vpc_flow_logs (
version int, account_id string, interface_id string,
srcaddr string, dstaddr string, srcport int, dstport int,
protocol bigint, packets bigint, bytes bigint,
start_time bigint, end_time bigint, action string, log_status string
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ' '
LOCATION 's3://my-flowlogs-bucket/AWSLogs/123456789012/vpcflowlogs/ap-southeast-1/';
建表后即可用标准 SQL 做趋势分析。例如统计每天被拒绝的独立源地址数量,用于识别扫描行为:
SELECT date_trunc('day', from_unixtime(start_time)) AS day,
count(DISTINCT srcaddr) AS distinct_src,
count(*) AS reject_records
FROM vpc_flow_logs
WHERE action = 'REJECT'
GROUP BY 1
ORDER BY 1 DESC;
实际排障中,有几类异常模式值得优先关注。第一类是 log-status 为 NODATA:表示采集窗口内该 ENI 没有流量,可能是实例已停止、安全组全封或采集配置未生效。第二类是大量 REJECT 集中在少数目的端口,常见于端口扫描或错误的安全组规则。第三类是 bytes 与 packets 比例异常,例如包数很多但字节数极小,可能是 SYN 重传或探测流量。第四类是同一对地址在短时间内反复出现 ACCEPT 与 REJECT 交替,通常意味着规则顺序或状态跟踪存在问题。
log-status 和采集范围综合判断。最后给出一个可直接套用的排查顺序:先确认采集范围是否覆盖目标 ENI,再确认 log-status 是否为 OK,然后按 action 分流——ACCEPT 看字节与端口分布,REJECT 看方向与规则匹配。CloudWatch Logs Insights 适合分钟级定位,Athena 适合天级趋势与跨账户汇总。两条路径共用同一份字段语义,掌握字段含义后,切换查询引擎只是语法差异,判断逻辑完全一致。