Логотип
Главная | Статьи | Distributed фаззинг на AWS Lambda: масштабируем до 10K ядер
Distributed фаззинг на AWS Lambda: масштабируем до 10K ядер

Distributed фаззинг на AWS Lambda: масштабируем до 10K ядер

2 июля, 2026

35

Забудь про выделенный кластер за $50к в месяц – можно поднять фаззинг-ферму на serverless-инфраструктуре, где 10 000 параллельных Lambda-инстансов молотят по таргету одновременно, а платишь только за реальное время выполнения.

Почему Lambda вообще подходит для фаззинга

Главный козырь AWS Lambda – это massively parallel invocation: множество инстансов одной и той же функции могут выполняться конкурентно без ручного управления инфраструктурой. AWS Step Functions Distributed Map официально поддерживает до 10 000 конкурентных выполнений Map-состояния, что и даёт то самое число “10K ядер” в заголовке – это не маркетинг, а конкретный технический лимит сервиса. По сути каждый Lambda-инвок – это изолированный контейнер с CPU и памятью, который отлично ложится на модель фаззинга: один воркер = один shard корпуса на короткую кампанию.

Академические и open-source прецеденты уже есть: LibAFL, написанный на Rust, изначально проектировался для superior scalability across multiple cores and machines и может выступать drop-in заменой libFuzzer именно ради горизонтального масштабирования. Google ClusterFuzz, кстати, использует похожую идею массового распределённого запуска fuzzer-джобов (libFuzzer, AFL++, honggfuzz) через job-очереди, просто на своей инфраструктуре, а не на AWS.google.

Архитектура пайплайна

Схема строится на четырёх компонентах: оркестрация, доставка полезной нагрузки, сами fuzzer-воркеры и агрегация результатов.

  • Оркестрация: Step Functions Distributed Map раздаёт джобы по shard’ам корпуса, поддерживая до 10 000 параллельных запусков
  • Буферизация нагрузки: SQS-очередь между оркестратором и Lambda с event source mapping – так контролируешь maximum concurrency и не убиваешь себя throttling’ом
  • Fuzzer-движок внутри инстанса: AFL++ или libFuzzer, скомпилированные в статическую библиотеку с ASan-инструментацией прямо в Lambda-рантайме
  • Общий корпус и краши: S3 как shared storage для seed-корпуса и найденных crash-инпутов, синхронизируемый между инвокациями

Практическая деталь: AFL++ имеет стабильную поддержку multi-core fuzzing кампаний из коробки, что упрощает шардинг корпуса между Lambda-инстансами – каждому воркеру просто нарезаешь свой независимый seed-набор.

Минимальный воркер на Python + boto3

Вот скелет диспетчера, который асинхронно бросает N инвокаций Lambda с разными shard’ами корпуса из S3:

InvocationType='Event' – ключевой момент: асинхронный вызов не блокирует диспетчер и позволяет забросить тысячи инвокаций за секунды, а Lambda сама распределит их по доступной ёмкости.

Ограничения, о которых молчат туториалы

Главный подводный камень – 15-минутный жёсткий лимит времени выполнения Lambda, из-за чего длинные fuzzing-кампании превращаются в цепочку коротких сессий с checkpoint’ами в S3, а не в один непрерывный прогон. Второй момент – concurrency limit аккаунта по умолчанию куда ниже 10 000, и его нужно поднимать через AWS Support заранее, иначе получишь throttling вместо фаззинга. Есть и трюк “cheating scalability” – traffic isolation и мультирегиональное дублирование функции под одной и той же логикой, что даёт N-кратный прирост параллелизма без переписывания кода.

Отдельная проблема – сама природа фаззинга: throughput одного и того же fuzzer на одном таргете может варьироваться в разы (до 20.9x) между запусками из-за стохастичности, поэтому 10 000 параллельных shard’ов – это не гарантия линейного прироста находок, а способ статистически “перебить” эту случайность объёмом.

Куда это движется

Свежие исследования вроде фреймворка Orion показывают тренд на комбинирование LLM-агентов с детерминированными фаззинг-инструментами: LLM берёт на себя семантический анализ кода и генерацию гипотез, а традиционный fuzzer – верификацию, что сокращает человеческие трудозатраты в 46–204 раза и уже нашло две 0-day в библиотеке clib. Логичный next step для твоей Lambda-фермы – прикрутить LLM-triage слой поверх найденных крашей, чтобы не разгребать тысячи дублирующихся stack trace вручную.