L’équipe de sécurité transmet une liste d’IP indicateurs depuis un fil de threat intel et demande « est-ce que l’un de nos hôtes a parlé à ces IP ? ». La réponse intuitive est de greper les logs applicatifs, mais les logs applicatifs ne voient que HTTP — ils ratent les requêtes DNS, les appels S3 sortants, les tentatives SSH, tout ce qui n’est pas HTTP. La bonne source de log, ce sont les Flow Logs VPC. L’équipe les active sur le VPC de production, les pointe sur CloudWatch Logs, lance la recherche, trouve deux hôtes qui ont effectivement parlé à une IP signalée, puis reçoit en fin de mois une facture d’ingestion CloudWatch plus grosse que la flotte EC2 pour la même période. L’erreur n’est pas les flow logs — c’est de les envoyer vers CloudWatch sur un VPC qui bouge des téraoctets de trafic. La bonne architecture est S3 plus Athena, avec filtrage. Voici la mise en place qui marche.
Ce qui se passe
Les Flow Logs VPC capturent les métadonnées de chaque conversation au niveau IP à l’intérieur du VPC. Chaque enregistrement de log est une ligne au format fixe avec IP source, IP destination, port source, port destination, protocole, compte de paquets, compte d’octets, horodatages de début et de fin, action (ACCEPT ou REJECT) et l’interface réseau. Les flow logs ne capturent pas le contenu des paquets — ce sont des métadonnées de connexion, pas de la capture de paquets. Le format d’enregistrement est extensible ; vous pouvez ajouter des champs comme l’ID du VPC, l’ID du sous-réseau, l’ID de l’instance, l’attache TGW et les drapeaux TCP. Le format personnalisé vaut la peine d’être utilisé ; le format par défaut manque des champs dont vous avez besoin pour « quelle instance a parlé à cette IP ».
Les flow logs peuvent être configurés à trois portées :
- Niveau VPC — chaque ENI du VPC. C’est ce que vous voulez pour l’analyse de sécurité.
- Niveau sous-réseau — chaque ENI du sous-réseau. Utile pour cibler un tier spécifique.
- Niveau ENI — une seule interface réseau. Utile pour déboguer une instance spécifique.
Les flow logs peuvent être envoyés à trois destinations :
- CloudWatch Logs — pratique pour les requêtes Insights ad-hoc, coûteux à fort volume. Le coût d’ingestion au GB est la ligne qui surprend les équipes. Un VPC qui tire 50 TB/mois de trafic avec des flow logs aux paramètres par défaut peut générer une ligne d’ingestion CloudWatch plus grosse que le reste de la facture AWS combiné.
- S3 — bon marché (tarif de stockage S3, aucun frais d’ingestion au GB pour les flow logs). L’attrape est que les flow logs stockés en S3 ne sont pas directement requêtables ; il faut Athena ou un outil similaire par-dessus.
- Kinesis Data Firehose — pour streamer vers un SIEM ou une plateforme tierce d’analytique de logs. Utile pour les organisations qui ont un pipeline de logs existant ; le coût in-AWS est le débit Firehose.
Le piège de coût qui mord une fois : activer les flow logs vers CloudWatch sur un VPC à fort trafic sans filtrage produit des centaines de millions d’enregistrements par jour. La bonne architecture, ce sont les flow logs vers S3, partitionnés par date et compte, avec des tables Athena prêtes pour les requêtes que vous lancez réellement.
Comment vérifier
La mise en place, pour un VPC qui n’a pas encore de flow logs :
# 1. Créer le bucket S3 pour les flow logs (avec politique de cycle de vie)
aws s3api create-bucket --bucket org-flow-logs-us-east-1 --region us-east-1
aws s3api put-bucket-lifecycle-configuration --bucket org-flow-logs-us-east-1 \
--lifecycle-configuration file://lifecycle.json
# lifecycle.json :
# Transition vers S3 Standard-IA à 30 jours, Glacier à 90, expiration à 365.
# 2. Activer les flow logs sur le VPC, avec format personnalisé
aws ec2 create-flow-logs \
--resource-type VPC \
--resource-ids vpc-0123456789abcdef0 \
--traffic-type ALL \
--log-destination-type s3 \
--log-destination arn:aws:s3:::org-flow-logs-us-east-1/vpc/ \
--log-format '${version} ${account-id} ${interface-id} ${srcaddr} ${dstaddr} ${srcport} ${dstport} ${protocol} ${packets} ${bytes} ${start} ${end} ${action} ${log-status} ${vpc-id} ${subnet-id} ${instance-id} ${tcp-flags} ${type} ${pkt-srcaddr} ${pkt-dstaddr} ${region} ${az-id} ${flow-direction}'
Après environ 10 minutes les premiers lots de flow logs arrivent en S3, partitionnés par AWSLogs/<compte>/vpcflowlogs/<région>/<année>/<mois>/<jour>/.
Mettre en place Athena pour requêter :
CREATE EXTERNAL TABLE vpc_flow_logs (
version INT,
account_id STRING,
interface_id STRING,
srcaddr STRING,
dstaddr STRING,
srcport INT,
dstport INT,
protocol INT,
packets BIGINT,
bytes BIGINT,
start_ts BIGINT,
end_ts BIGINT,
action STRING,
log_status STRING,
vpc_id STRING,
subnet_id STRING,
instance_id STRING,
tcp_flags INT,
type STRING,
pkt_srcaddr STRING,
pkt_dstaddr STRING,
region STRING,
az_id STRING,
flow_direction STRING
)
PARTITIONED BY (year STRING, month STRING, day STRING)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ' '
LOCATION 's3://org-flow-logs-us-east-1/AWSLogs/111122223333/vpcflowlogs/us-east-1/'
TBLPROPERTIES (
'projection.enabled' = 'true',
'projection.year.type' = 'integer',
'projection.year.range' = '2024,2030',
'projection.month.type' = 'integer',
'projection.month.range' = '1,12',
'projection.day.type' = 'integer',
'projection.day.range' = '1,31',
'storage.location.template' = 's3://org-flow-logs-us-east-1/AWSLogs/111122223333/vpcflowlogs/us-east-1/${year}/${month}/${day}/'
);
La projection de partitions (pas de MSCK REPAIR nécessaire) garde les scans Athena bon marché — une requête ciblée sur un jour lit les partitions d’un jour, pas la table entière.
La requête pain-beurre, « qui a parlé à une IP fuitée dans les 7 derniers jours » :
SELECT
from_unixtime(start_ts) AS conn_time,
srcaddr,
dstaddr,
srcport,
dstport,
instance_id,
bytes,
action
FROM vpc_flow_logs
WHERE year = '2026' AND month = '5'
AND day BETWEEN '20' AND '26'
AND (dstaddr = '203.0.113.42' OR srcaddr = '203.0.113.42')
ORDER BY conn_time DESC
LIMIT 100;
Pour une liste d’IP fuitées dans un fichier, utilisez IN :
WHERE dstaddr IN ('203.0.113.42', '198.51.100.7', '192.0.2.99')
La deuxième requête à haute valeur, « principales destinations sortantes par octets » :
SELECT
dstaddr,
SUM(bytes) AS total_bytes,
COUNT(*) AS flow_count
FROM vpc_flow_logs
WHERE year = '2026' AND month = '5' AND day = '25'
AND flow_direction = 'egress'
AND NOT regexp_like(dstaddr, '^10\.')
GROUP BY dstaddr
ORDER BY total_bytes DESC
LIMIT 50;
C’est la requête qui diagnostique une facture sortante inattendue. Résolvez les principales IP avec dig -x pour identifier le service de destination.
La troisième requête, « trafic REJECTé par port destination » :
SELECT
dstport,
COUNT(*) AS reject_count,
COUNT(DISTINCT srcaddr) AS distinct_sources
FROM vpc_flow_logs
WHERE year = '2026' AND month = '5' AND day = '25'
AND action = 'REJECT'
AND flow_direction = 'ingress'
GROUP BY dstport
ORDER BY reject_count DESC
LIMIT 50;
Du trafic entrant REJECTé sur des ports bizarres, c’est le bruit d’Internet — des bots qui sondent des services ouverts. Du trafic entrant REJECTé dense sur un port sur lequel vos services écoutent vraiment est un signe qu’un groupe de sécurité bloque du trafic que vous pourriez vouloir.
La correction
La procédure pour mettre en place les flow logs d’une manière qui passe à l’échelle :
-
Choisir S3 d’abord, CloudWatch seulement pour du débogage à courte fenêtre. S3 est la destination bon marché, durable, requêtable pour la longue traîne. CloudWatch Logs Insights est la destination rapide et coûteuse pour les 24 prochaines heures. Si vous devez utiliser CloudWatch, ciblez un seul sous-réseau ou une seule ENI et utilisez une fenêtre de rétention courte.
-
Utiliser le format de log personnalisé avec instance_id et tcp_flags. Sans instance_id, chaque ligne de flow log référence un ID d’ENI, et il faut joindre ENI-vers-instance séparément. Avec lui, les requêtes sont autonomes.
tcp_flagspermet de voir si la conversation était une vraie connexion (SYN+ACK présents) ou une sonde (SYN seul, sans réponse). -
Partitionner par date avec projection. Une table de flow log sans partitions, requêtée sur un mois, scanne des dizaines de GB et coûte de l’argent réel par requête. Partitionnée avec projection, la même requête scanne 1 GB. La différence est un changement de schéma.
-
Définir une politique de cycle de vie S3. Les flow logs sont append-only. Après 30 jours ils devraient être sur Standard-IA ; après 90 jours sur Glacier ; après un an, expirer (ou plus longtemps, si la conformité l’exige). La politique de cycle de vie est la seule chose qui empêche le bucket de devenir le plus gros poste de dépense S3 de l’organisation.
-
Décider quoi logger. Le défaut est « all » — à la fois ACCEPT et REJECT. Pour la plupart des VPC en production, « all » est correct parce que les enregistrements REJECT sont le signal de sécurité. Pour les VPC avec un volume de trafic très élevé où le coût de logging est une vraie préoccupation, « ACCEPT seulement » ou « REJECT seulement » peut couper le volume en deux. Soyez conscient que « ACCEPT seulement » perd le côté constatation de sécurité.
-
Pour les organisations multi-comptes, centraliser le bucket de flow logs. Chaque compte envoie vers un bucket dans le compte sécurité/logging, partitionné par compte source. La table Athena est créée une fois dans le compte sécurité ; l’équipe sécurité requête à travers tous les comptes sans avoir besoin de credentials par compte.
L’erreur à éviter : activer les flow logs vers CloudWatch Logs à la portée VPC sur un VPC qui tire des dizaines de TB par mois. La ligne d’ingestion CloudWatch arrivera plus grosse que prévue. Passez à S3 d’abord, ou ciblez les flow logs CloudWatch à un seul sous-réseau, ou filtrez à REJECT seulement si la sécurité est le seul cas d’usage.
L’autre règle qu’on tient : les flow logs valent pour les requêtes dont vous ne savez pas encore que vous aurez besoin. Le biais est de les activer sur chaque VPC en production, vers S3, avec rétention. La première fois qu’une IP fuitée fait surface, vous voulez les données d’il y a un mois, pas « laissez-moi activer les flow logs et je reviens dans deux semaines ».
Pour la conception de sous-réseaux sous-jacente sur laquelle les flow logs opèrent, voir Conception de sous-réseaux multi-AZ. Pour la visibilité sur les sorties que révèlent les flow logs, voir NAT Gateway vs instance NAT.
Stack Harbor met en place les architectures de flow logs et les requêtes Athena qui opèrent dessus dans le cadre de Gestion AWS et des Environnements infogérés en continu. Si votre VPC n’a pas de flow logs ou les a au mauvais endroit coûteux, commencez par une consultation d’infrastructure.