Инженерные статьи

Как проверить исходящие соединения Cloud Mac в CI

Как проверить исходящие соединения Cloud Mac в CI

Если ранее стабильный конвейер CI внезапно начал обращаться к незнакомым адресам, не спешите сразу блокировать соединения. Исходящий трафик могут создавать инструменты сборки, средства разрешения зависимостей, тестовые процессы и фоновые задачи обновления. Для эффективного расследования выберите воспроизводимую сборку и в течение ограниченного интервала одновременно фиксируйте, какой процесс работал, куда он подключался и когда возникло соединение. Затем оформите результаты как базовую линию.

Сначала задайте сопоставимое окно наблюдения

Выберите период, когда зависимости уже установлены, рабочая область чиста, а задачи других команд не выполняются. Зафиксируйте идентификатор коммита, команду сборки, версии macOS и Xcode, а также время начала. Во время первого сбора данных запускайте только одну задачу, чтобы общие процессы двух конвейеров не помешали определить источник соединений.

Рекомендуется подготовить два набора данных: один для минимальной сборки, другой — для полного набора тестов. Первый покажет соединения, возникающие при разрешении зависимостей и компиляции, а второй дополнительно охватит симуляторы, тестовые службы и загрузку артефактов. Повторите каждый запуск дважды: второй прогон обычно позволяет отличить первоначальные загрузки от стабильной сборки.

Базовая линия исходящего трафика — это не бессрочный список IP-адресов, а подтверждение того, почему известная задача на известном этапе обращается к определённому типу сервиса.

Наблюдайте за соединениями на трёх уровнях

Процессы и активные соединения

lsof помогает определить, какие процессы сохраняют соединения в момент наблюдения. Числовые адреса позволяют избежать дополнительного DNS-трафика, который мог бы возникнуть при обратном разрешении имён.

sudo lsof -nP -iTCP -sTCP:ESTABLISHED \
  | awk 'NR == 1 || $1 ~ /xcode|swift|git|ruby|node|curl/'

Не ограничивайтесь фильтрацией по имени процесса и не удаляйте исходные результаты. Сначала сохраните полный снимок, а затем создайте более удобную для чтения выборку. Скрипт сборки может загружать данные через системную утилиту, имя которой не содержит ключевых слов проекта.

Трафик и кратковременные соединения

nettop предоставляет сводное представление трафика по процессам в реальном времени, а tcpdump позволяет сохранить даже TCP-рукопожатия, завершившиеся за несколько десятков миллисекунд. При удалённом запуске перехватывайте только исходящие SYN-пакеты без полезной нагрузки, чтобы уменьшить объём рабочих данных в журнале.

nettop -P -L 1
sudo tcpdump -i any -nn -l \
  'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack == 0'

Перед захватом пакетов уточните удалённый адрес текущего сеанса SSH. Ошибка в фильтре может создать большой объём шума, однако сами команды наблюдения не изменяют правила межсетевого экрана.

Создайте архивируемый пакет данных

Приведённый ниже скрипт сохраняет сведения о системе, маршрутах, снимки соединений и записи рукопожатий за 60 секунд. Перед запуском подготовьте сборку так, чтобы её можно было начать немедленно. После запуска скрипта запустите сборку в другом сеансе.

#!/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"

Если сборка длится более 60 секунд, собирайте данные отдельно для этапов «разрешение зависимостей, компиляция, тестирование, архивирование», а не увеличивайте одно окно захвата без ограничений. Поэтапные результаты упрощают поиск шага, на котором появилось новое соединение.

Систематизируйте назначения в базовую линию трафика

Не считайте соединение аномальным только из-за незнакомого IP-адреса. Сначала классифицируйте его с учётом процесса, порта, этапа появления и конфигурации проекта. Сети динамической доставки могут часто менять адреса, поэтому базовую линию следует строить прежде всего на назначении соединения и проверяемых доменных именах. IP-адрес нужно сохранять лишь как свидетельство конкретного запуска.

| Категория | Какие данные фиксировать | Что делать | |---|---|---| | Исходный код и зависимости | Процесс, домен, этап сборки | Сверить с файлами блокировки и конфигурацией репозиториев | | Тестовые службы | Тестовый сценарий, порт, длительность | Убедиться, что это ожидаемый интеграционный тест | | Передача артефактов | Скрипт загрузки, назначение, тип файла | Проверить, что соединение возникает только на этапе архивирования | | Фоновый системный трафик | Системный процесс, время запуска | Отмечать отдельно от трафика сборки | | Неизвестные соединения | Полная командная строка, родительский процесс, время захвата | Приостановить слияние и воспроизвести соединение для сбора доказательств |

Для неизвестного процесса дополнительно выполните ps -o pid,ppid,user,start,command -p PID, а затем проверьте его родительский процесс. Если соединение возникло только один раз, приведите время захвата пакетов и журналы CI к UTC и сопоставьте их, не полагаясь на воспоминания.

Распространённые ошибки и границы безопасности

Самая распространённая ошибка — считать динамический IP-адрес постоянным идентификатором. Вторая ошибка — запускать lsof только после завершения сборки, когда кратковременные соединения уже исчезли. Третья — сразу включать запрещающие правила на удалённом узле. Если правило не проверено через локальную консоль, оно может одновременно разорвать SSH-соединение, нарушить работу DNS или заблокировать загрузку зависимостей.

Более безопасная последовательность действий: наблюдение, классификация, воспроизведение, проверка и только затем введение ограничений. Если исходящий трафик действительно требуется ограничить, сначала сохраните действующее административное соединение и доступ к DNS, подготовьте команду отката и проверьте изменения на одной некритичной задаче. Правила межсетевого экрана, настройки прокси и скрипты сборки должны храниться в системе управления версиями, а не только локально на узле.

Включите базовую линию в регулярные проверки

Повторяйте тот же сбор данных после каждого изменения инструментальной цепочки, источников зависимостей или процесса загрузки артефактов. При сравнении отслеживайте новые сочетания «процесс — назначение — этап», а не количество строк с IP-адресами. Для разрешённых соединений необходимо указывать ответственного, назначение и условия повторной проверки. Необъяснимые соединения нельзя разрешать бессрочно, ограничившись примечанием.

В итоге сохраните скрипт сбора, исходные файлы, классификационную таблицу и идентификатор соответствующего коммита. Тогда при подозрительных загрузках, замедлении сборки или возможной передаче учётных данных наружу команда сможет начать расследование с реальных отличий, а не заново выяснять, как выглядит нормальный трафик.

Часто задаваемые вопросы

Можно ли сразу добавить найденные IP-адреса в список разрешённых?

Не рекомендуется. Сервисы загрузки часто используют динамические или общие адреса, поэтому назначения сначала классифицируют по функции и домену.

Почему lsof и tcpdump показывают разное число соединений?

lsof видит только открытые в момент проверки соединения, а tcpdump сохраняет также короткие попытки подключения, завершившиеся во время захвата.

OrbVPS облачный Mac

Запускайте сборки на выделенных физических узлах Apple Silicon

Настройте узел по модели, региону и сроку аренды. Фактическая доступность отображается в панели управления в реальном времени.

Арендовать облачный Mac