Lorsqu’un pipeline CI jusque-là stable commence soudainement à contacter des adresses inconnues, mieux vaut ne pas les bloquer immédiatement. Les outils de build, les gestionnaires de dépendances, les processus de test et les tâches de mise à jour en arrière-plan peuvent tous générer des connexions sortantes. Une méthode d’analyse efficace consiste à choisir un build reproductible et, pendant une période définie, à relever simultanément « quel processus s’exécute, où va la connexion et quand elle apparaît », puis à organiser ces résultats en une référence.
Définir d’abord une fenêtre d’observation comparable
Choisissez un créneau pendant lequel les dépendances sont déjà installées, l’espace de travail est propre et aucune autre tâche de l’équipe ne s’exécute. Consignez l’identifiant du commit, la commande de build, les versions de macOS et de Xcode, ainsi que l’heure de début. Pour la première collecte, n’exécutez qu’une seule tâche afin d’éviter que des processus partagés entre deux pipelines rendent l’attribution impossible.
Il est conseillé de préparer deux jeux de données : l’un pour un build minimal, l’autre pour la suite de tests complète. Le premier met en évidence les connexions liées à la résolution des dépendances et à la compilation ; le second couvre également les simulateurs, les services de test et l’envoi des artefacts. Répétez chaque scénario deux fois : le second passage permet généralement de distinguer les téléchargements initiaux du fonctionnement normal d’un build stabilisé.
Une référence des flux sortants n’est pas une liste d’adresses IP valable indéfiniment, mais un ensemble de preuves expliquant pourquoi une tâche connue contacte un type de service donné à une étape connue.
Observer les connexions à partir de trois niveaux de preuve
Processus et connexions actives
lsof permet de savoir quels processus maintiennent encore une connexion au moment de l’observation. L’utilisation d’adresses numériques évite que la résolution inverse ne génère du trafic DNS supplémentaire.
sudo lsof -nP -iTCP -sTCP:ESTABLISHED \
| awk 'NR == 1 || $1 ~ /xcode|swift|git|ruby|node|curl/'
Ne filtrez pas uniquement par nom de processus au risque de perdre les résultats bruts. Enregistrez d’abord un instantané complet, puis créez-en un sous-ensemble plus lisible. Un script de build peut télécharger des fichiers par l’intermédiaire d’un outil système dont le nom ne contient aucun mot-clé propre au projet.
Trafic et connexions de courte durée
nettop fournit une vue en temps réel agrégée par processus, tandis que tcpdump conserve la trace des négociations TCP qui se terminent en quelques dizaines de millisecondes. Lors d’une intervention à distance, ne capturez que les paquets SYN sortants, sans enregistrer leur charge utile, afin de limiter la présence de données métier dans les journaux.
nettop -P -L 1
sudo tcpdump -i any -nn -l \
'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack == 0'
Avant de lancer la capture, vérifiez l’adresse distante de la session SSH en cours. Une erreur dans le filtre peut produire beaucoup de bruit, mais les commandes d’observation elles-mêmes ne modifient aucune règle de pare-feu.
Produire un dossier de collecte archivable
Le script ci-dessous enregistre les informations système, le routage, les instantanés des connexions et 60 secondes de négociations TCP. Avant de l’exécuter, préparez le build jusqu’au point où il est prêt à démarrer. Une fois le script lancé, exécutez le build dans une autre session.
#!/bin/zsh
set -euo pipefail
OUT="${1:-$HOME/ci-egress-$(date -u +%Y%m%dT%H%M%SZ)}"
mkdir -p "$OUT"
date -u > "$OUT/time.txt"
sw_vers > "$OUT/system.txt"
xcodebuild -version > "$OUT/xcode.txt"
route -n get default > "$OUT/default-route.txt"
scutil --dns > "$OUT/dns.txt"
sudo lsof -nP -i > "$OUT/lsof-before.txt"
sudo tcpdump -i any -nn \
'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack == 0' \
-w "$OUT/outbound-syn.pcap" &
CAPTURE_PID=$!
sleep 60
sudo kill -INT "$CAPTURE_PID"
wait "$CAPTURE_PID" || true
sudo lsof -nP -i > "$OUT/lsof-after.txt"
nettop -P -L 1 > "$OUT/nettop.txt"
printf '%s
' "$OUT"
Si le build dure plus de 60 secondes, effectuez des captures distinctes pour les étapes « résolution des dépendances, compilation, tests et archivage » plutôt que de prolonger indéfiniment une seule capture. Des résultats segmentés par étape permettent d’identifier plus facilement l’origine de chaque nouvelle connexion.
Classer les destinations pour établir une référence des communications
Ne concluez pas à une anomalie dès qu’une adresse IP inconnue apparaît. Commencez par la classer en tenant compte du processus, du port, de l’étape concernée et de la configuration du projet. Les réseaux de diffusion dynamiques peuvent changer fréquemment d’adresse ; la référence doit donc privilégier l’usage et les noms de domaine vérifiables, tandis que l’adresse IP ne doit être conservée qu’en tant que preuve ponctuelle.
Pour tout processus inconnu, exécutez ensuite ps -o pid,ppid,user,start,command -p PID, puis examinez son processus parent. Si une connexion n’apparaît qu’une seule fois, convertissez l’heure de la capture et celle des journaux CI en UTC avant de les rapprocher, plutôt que de vous fier aux souvenirs de l’équipe.
Erreurs d’interprétation courantes et limites de sécurité
L’erreur la plus fréquente consiste à traiter une adresse IP dynamique comme un identifiant stable. La deuxième est de n’exécuter lsof qu’après la fin du build, lorsque les connexions brèves ont déjà disparu. La troisième consiste à activer directement des règles de blocage sur un nœud distant : sans validation depuis une console locale, ces règles peuvent interrompre simultanément SSH, DNS ou le téléchargement des dépendances.
L’ordre le plus sûr est d’observer, de classer, de reproduire et de faire valider les résultats avant d’appliquer la moindre restriction. S’il faut réellement limiter les flux sortants, préservez d’abord la connexion d’administration existante et le chemin DNS, préparez une commande de retour arrière, puis validez les règles sur une seule tâche non critique. Les règles de pare-feu, la configuration du proxy et les scripts de build doivent être placés sous gestion de versions, et non rester uniquement sur le nœud.
Intégrer la référence aux contrôles courants
Relancez la même collecte après chaque modification de la chaîne d’outils, des sources de dépendances ou du processus d’envoi. Lors des comparaisons, recherchez les nouvelles combinaisons « processus—destination—étape » plutôt que de compter les lignes d’adresses IP. Chaque autorisation doit préciser son responsable, son objectif et ses conditions de réexamen ; une simple note ne doit jamais servir à autoriser définitivement une connexion inexpliquée.
Conservez enfin le script de collecte, les fichiers bruts, le tableau de classification et l’identifiant du commit correspondant. En cas de téléchargement anormal, de ralentissement du build ou de suspicion d’exfiltration d’identifiants, l’équipe pourra ainsi partir des différences réellement observées au lieu de devoir redéfinir ce qui constitue un trafic normal.
Questions fréquentes
Peut-on placer directement les adresses IP observées dans une liste d’autorisation ?
Ce n’est pas conseillé. Les services de téléchargement utilisent souvent des adresses dynamiques ou partagées ; il faut d’abord classer les destinations par usage et domaine.
Pourquoi lsof et tcpdump ne montrent-ils pas le même nombre de connexions ?
lsof ne voit que les connexions encore ouvertes au moment du relevé, tandis que tcpdump conserve aussi les ouvertures brèves survenues pendant la fenêtre de capture.
Lancez vos builds sur des nœuds physiques Apple Silicon dédiés
Configurez votre nœud selon le modèle, la région et la durée de location. La disponibilité réelle est indiquée en temps réel dans le tableau de bord.