AWS: VPC Flow Logs - знайомство та аналітика з CloudWatch Logs Insights
AWS VPC Flow Logs - сервіс Amazon, який дозволяє логувати інформацію про трафік між мережевими інтерфейсами у AWS VPC. Далі, ці логи можуть бути передані у AWS CloudWatch Logs для подальшого аналізу, при цьому логування трафіку ніяк не впливає на швидкість роботи мережі.
Коротко розглянемо основні поняття, доступні опції та налаштуємо Flow Logs для VPC з передачею даних для аналізу у CloduWatch Logs.
Зміст
- Опис VPC Flow Logs
- Use Cases — приклади використання
- Flow Log record — поля
- Обмеження VPC Flow Logs
- Створення VPC Flow Log
- CloudWatch Logs Log Group
- Створення IAM Policy та IAM Role
- VPC — включення Flow Logs
- CloudWatch Logs Insights
- VPC Flow Log — Custom format
- Flow Log Custom format та CloudWatch Logs Insights
- Приклади Logs Insights
- Посилання по темі
- VPC Flow Logs
- CloudWatch Logs
Опис VPC Flow Logs
Логи можуть бути включені для цілої VPC, підмережі, або конкретного інтерфейсу. При включенні для всієї VPC — логування буде включено для всіх мережевих інтерфейсів цієї мережі.
Сервіси, для яких можна використовувати Flow Logs:
- Elastic Load Balancing
- Amazon RDS
- Amazon ElastiCache
- Amazon Redshift
- Amazon WorkSpaces
- NAT gateways
- Transit gateways
Дані будуть записані у вигляді flow log records, які представляють собою текстовий запис з заданними полями.
Use Cases — приклади використання
Що можна відстежити за допомогою Flow logs?
- спрацьовування правил SecuirtyGroup/Network Access List — заблоковані запити будуть відмічені як REJECTED
- те, заради чого логі впроваджуємо ми — отримати картину трафіку між VPC та сервісами, щоб зрозуміти хто найбільше трафіку споживає, де і скільки cross-AZ трафіку тощо
- моніторинг віддалених логінів у систему — стежити за портами 22 (SSH), 3389 (RDP)
- відстеження сканування портів
Flow Log record — поля
Кожен запис у логах містить дані про IP-трафіку, отриманому за aggregation interval і є рядком з полями, розділені пробілами, де кожне поле містить інформацію про передачу даних, наприклад — Source IP, Destination IP і протокол.
За замовчуванням використовується такий формат:
${version} ${account-id} ${interface-id} ${srcaddr} ${dstaddr} ${srcport} ${dstport} ${protocol} ${packets} ${bytes} ${start} ${end} ${action} ${log-status}
Див. таблицю Available fields в документації — все у колонці Version 2 включено у default format. Інші версії доступні у Custom Format.
При створенні Flow Logs, ми можемо використовувати дефолтний формат або створити свій — розглянемо його трохи нижче:
Обмеження VPC Flow Logs
- не можна використовувати з інстансами EC2-Classic
- не можна створити логі для VPC-пірингів, якщо вони ведуть до VPC в іншому акаунті
- після створення лога — не можна змінити його конфігурацію чи формат записів
- якщо в інтерфейсу кілька IPv4-адрес, і траїфк відправляється до одного з secondary-адрес, то в полі
dstaddr
буде відображено primary-адресу; щоб отримати оригінальну адресу — використовуйте полеpkt-dstaddr
- якщо трафік відправлений з або на мережевий інтерфейс, поля
srcaddr
таdstaddr
будуть містити його primary private IPv4 адресу; щоб отримати оригінальну адресу — використовуйте поляpkt-dstaddr
таpkt-dstaddr
Також, враховуйте, що:
- не логуються записи до DNS Amazon, але пишуться, якщо використовується свій DNS
- не логується трафік на та з адреси 169.254.169.254 для отримання метаданих EC2-інстансу
- не логується трафік між мережевим інтерфейсом EC2 та інтерфейсом AWS Network Load Balancer
Див. всі обмеження на Flow log limitations.
Створення VPC Flow Log
Для створення нам потрібно вказати:
- ресурс, логи якого будемо писати — VPC, підмережа або конкретний мережевий інтерфейс
- тип трафіку, який логуємо (accepted traffic, rejected traffic або all traffic)
- і куди писатимемо дані — в кошик, або CloudWatch Logs
Поки подивимося, що вийде з CloudWatch Logs, а наступного разу — спробуємо візуалізувати у Kibana або Grafana.
CloudWatch Logs Log Group
Створюємо Log Group:
Створення IAM Policy та IAM Role
Для того, щоб сервіс Flow Logs міг писати в наш CloudWatch — налаштовуємо йому права доступу.
Переходимо в AWS IAM, створюємо IAM Policy та IAM Role.
Починаємо з Policy:
Додаємо саму політику:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
"logs:DescribeLogGroups",
"logs:DescribeLogStreams"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
Зберігаємо:
Створюємо роль.
Переходимо в IAM Roles, створюємо нову, вибираємо тип EC2:
Знаходимо створену вище політику, підключаємо:
Задаємо ім’я, зберігаємо:
Переходимо до Role Trust relationshitp (див. 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 — включення Flow Logs
І нарешті переходимо до включення логів — знаходимо потрібну VPC, клікаємо Flow Logs > Create:
Задаємо ім’я, Filter, Interval:
У Destination вибираємо CloudWatch Logs, вказуємо створені раніше Log Group та IAM Role:
Format — залишаємо Default.
Перевіряємо Status:
І за декілька хвилин — дані пішли:
У лог-групі з’явився перший стрим з ім’ям Elastic Network Interface, з якого знімаються дані:
CloudWatch Logs Insights
Швидко подивимося, що нам доступно в Logs Insights.
Клікаєм Queries для отримання підказки щодо синтаксису запитів:
Наприклад, отримаємо топ-15 хостів за кількістю пакетів:
Або за обсягом надісланих даних:
stats sum(bytes) as BytesSent by srcAddr, dstAddr
| sort BytesSent desc
Окей, а що з іншими форматами?
Наприклад, хочеться побачити напрямок запиту (egress/ingress) та значення поля pkt-dstaddr
.
VPC Flow Log — Custom format
Див. приклади на сторінціFlow log record examples.
Використовуємо такий формат:
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 Logs створюємо новий Log group, назвемо його bttrm-eks-dev-1–21-vpc-fl-custom, не забуваємо про retention, щоб дані не лежали вічно (ну і взагалі не забуваємо, що CloudWatch не самий дешевий сервіс):
Повертаємось до VPC, знаходимо потрібну мережу, створюємо новий Flow Log, назвемо його bttrm-eks-dev-1–21-vpc-fl-custom:
Вибираємо Custom Format та поля, які хочемо записувати. При цьому враховуйте, що порядок полів у логах буде такий, який ви використовуєте під час вибору полів.
Тобто, якщо першим клікнути на “region” — то й у логах він буде йти першим:
Виходить так:
${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}
Flow Log Custom format та CloudWatch Logs Insights
Але якщо ми тепер ми зайдемо в Logs Insights, і спробуємо будь-який із попередніх запитів — отримаємо зовсім не ті поля, які хотіли:
Тобто, дані бачимо, але як розбити поля по колонках?
Ми навряд чи будемо щільно користуватися CloudWatch Logs, швидше за все в продакшені дані підуть у S3 і потім в ELK (logz.io), тому докладно тут зупинятись не буду, проте принцип роботи подивимося.
CloudWatch Logs за замовчуванням створює кілька мета-полів, які ми можемо використовувати у запитах:
-
@message
: "сирі" дані - все повідомлення в text -
@timestamp
: час події -
@logStream
: ім'я стриму
Для Custom format, щоб сформувати поля, використовуємо команду 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, ми можемо використовувати такі команди, як filter
, display
, stats
. Див. усі в CloudWatch Logs Insights query syntax.
Приклади 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
- рахуємо кількість записів по полю action, вибираючи за IP-адресою джерела, виводимо в колонці redjects
- і сортуємо по колонці 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
.
Наприклад, прибрати з виводу всі IP, що починаються з 162.142.125 — додаємо 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
Див. Sample queries.
І додамо фільтр на вибірку тільки вхідних запитів — 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
Отримуємо топ відкинутих запитів — спрацювало правило SecurityGroup або VPC Network Access List.
І дивимося — що за IP у dstaddr
– кому йшов пакет, який був заблокований?
Переходимо в EC2 > Network Interfaces, шукаємо Private IP:
Знаходимо “Elastic IP address owner”:
LoadBalancer.
Якщо адреса не знаходиться в AWS — можливо, це якийсь ендпоінт у Kubernetes — шукаємо наприклад так:
$ kubectl get endpoints — all-namespaces | grep 10.1.55.140
dev-ios-check-translation-ns ios-check-translation-backend-svc 10.1.55.140:3000 58d
dev-ios-check-translation-ns ios-check-translation-frontend-svc 10.1.55.140:80 58d
Загалом на це все.
У наступній частині — налаштуємо збір логів в AWS S3, потім будемо їх звідти збирати в ELK, і там спробуємо зробити візуалізацію та алерти.
Посилання по темі
VPC Flow Logs
CloudWatch Logs
- AWS Security Logging Fundamentals — VPC Flow Logs
- Analyze Query And Visualize AWS Cloudwatch Logs Using Logs Insight
- How to Visualize and Refine Your Network’s Security by Adding Security Group IDs to Your VPC Flow Logs
- Visualizing log data in graphs
- Analyze CloudWatch Logs like a pro
- Filter, Parse & Group Log Data in AWS CloudWatch Logs Insights
- How can I analyze custom VPC Flow Logs using CloudWatch Logs Insights?
- How can I use CloudWatch Logs Insights queries with my VPC flow log?
- CloudWatch Logs Insights query syntax
- Triaging Networking Issues Using AWS CloudWatch Logs Insights
Originally published at RTFM: Linux, DevOps, and system administration.
Top comments (0)