← К содержанию гайда

Эксплуатация и безопасность

35 минут
Раздел 9 из 9

Эксплуатация и безопасность — как биржа не падает и не теряет чужие деньги

Представьте вечер пятницы. Первый алерт: задержка matching engine на одной из торговых пар выросла с обычных 200 микросекунд до 4 миллисекунд. Через секунду приходит второй: спред на той же паре расширился с 2 базисных пунктов до 40, маркет-мейкеры снимают заявки. Третий алерт объясняет первые два: на основном хосте из зеркального RAID-массива выпал один из NVMe-дисков, куда пишется журнал событий. Теперь каждый fsync() идёт через единственный оставшийся диск и занимает три миллисекунды вместо привычных восьмидесяти микросекунд. Пока fsync() не завершён, ордер не считается применённым. Основной узел жив, торги продолжаются, но каждый ордер упирается в диск. У вас есть несколько минут, чтобы решить: сразу переключиться на резервный узел или работать в деградированном режиме, пока инженеры заменяют NVMe.

Это — реальная жизнь CEX. Все восемь предыдущих разделов рассказывали о том, как устроена биржа. Этот раздел — о том, как она продолжает работать, когда что-то идёт не по плану. А идёт не по плану всегда. Вопрос только — как часто, насколько публично и сколько это стоит клиентам.

Высокая доступность: живая биржа — это всегда две биржи

Биржа, работающая на одной машине, — это не биржа. Это демо. Как только первый реальный клиент доверил ей свои деньги, у вас появляется SLA: не ронять.

Мы уже видели в разделе про matching engine, что вся горячая часть биржи — matching, book state, order sequencing — работает в одном процессе, и это правильно. Но «один процесс» не означает «одна машина». Для высокой доступности биржа держит как минимум две копии matching engine: основную и резервную.

Как их синхронизировать? Ответ, как почти везде в этом гайде, — через журнал событий.

Active / passive HA matching engine
Основной узел (primary)ACTIVE
Принимает ордера, matching engine работает
  • — обрабатывает поток ордеров
  • — пишет каждое событие в журнал
  • — эмитит trade events наружу
Журнал событий
seq 1001 → NEW
seq 1002 → FILL
seq 1003 → CANCEL
seq 1004 → FILL
...
append-only, fsync для каждой записи
Резервный узел (replica)PASSIVE
Слушает журнал, повторяет шаги детерминированно
  • — читает журнал по порядку
  • — прогоняет те же операции
  • — держит идентичное состояние
!Основной узел недоступен — failover за секунды
Реплика уже имеет идентичное состояние книги и позиции в журнале. Оркестратор переключает трафик, реплика становится новым основным узлом, а поднятый узел начинает работать как реплика, начиная с последнего snapshot или с начала журнала.
Активная/пассивная пара matching engine: основной узел пишет в журнал, резервный читает его и прогоняет те же операции в том же порядке

Основной узел принимает все ордера и для каждого события — нового ордера, отмены, филла — создаёт детерминированную запись в append-only журнал: seq=..., type=..., payload=.... Только после fsync() журнала событие считается применённым. Резервный узел читает тот же журнал, прогоняет те же операции в той же последовательности и держит у себя идентичное состояние книги.

Ключевое слово здесь — детерминизм. Если основной узел на ордере seq=1002 взял блокировку на три микросекунды, а резервный — на семь, это нормально. Но если они расходятся в результате матчинга — скажем, основной дал событиям матчинга порядок A→B, а резервный B→A — всё, состояние разъезжается, и резервный узел превращается в тыкву. Чтобы этого не случилось, matching engine должен быть чистой функцией от журнала: на одном и том же входе — один и тот же выход, без обращения к системному времени, без генерации случайных чисел, без зависимости от порядка сетевых пакетов.

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

Почему активная/пассивная пара, а не две активные? Потому что две matching engine, одновременно принимающие ордера на одну и ту же пару, — это рассинхронизация, запрограммированная архитектурно. Если обе инстанции получают ордера параллельно, то с точки зрения одной копии первым приходит один ордер, а с точки зрения другой — другой. Согласовать два таких «первым пришёл» можно только через консенсус. А консенсус — это миллисекунды там, где биржа считает время в микросекундах.

Для леджера и market data fan-out ситуация проще: эти подсистемы читают журнал и могут реплицироваться параллельно без ограничений. Matching — только одно место, где ордера выстраиваются в очередь. Именно поэтому архитектура биржи — асимметричная: hot path (matching) живёт в активной/пассивной паре, всё остальное масштабируется горизонтально.

Несколько регионов. Если целый регион AWS становится недоступен, включается межрегиональный failover. В другом регионе работает «тёплый» резерв, который также читает журнал, но получает его с задержкой в несколько десятков миллисекунд. Переключение занимает минуты, поэтому такой резерв используют только при катастрофическом отказе. За него приходится платить хранением дополнительной копии данных и межрегиональным трафиком, но для серьёзной биржи зависимость от одного региона неприемлема.

Запас мощности: как готовиться к десятикратным всплескам

Биржа должна держать нормальную нагрузку в штатном режиме. Это — базовый минимум. Настоящий вопрос — что происходит, когда нагрузка внезапно становится в десять раз больше обычной.

Такие моменты случаются по двум причинам:

  • Листинг популярной монеты. Биржа объявляет в твиттере: «через 10 минут открываем торги новой монеты». У скрипт-ботов запускается обратный отсчёт, розничные трейдеры бросаются перестраивать балансы, маркет-мейкеры прогревают соединения. В момент открытия торгов нагрузка — и на публичный API, и на matching engine — подскакивает в разы.
  • Обвал рынка. Bitcoin летит вниз на 8% за час. Все хотят или выйти, или купить. Поток ордеров, поток отмен, поток WebSocket-подписок — всё растёт одновременно.
Нагрузка за сутки: обычный день + анонс листинга
Обычная нагрузкаСобытие (10x)
00
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
13:00 — анонс
Публикация «листинг через 10 минут». Боты прогревают соединения, пользователи открывают торговый интерфейс.
13:10 — торги открыты
Нагрузка в 9.2 раза выше обычной. Gateway и matching engine справляются благодаря заранее заложенному headroom.
15:00 — спад
Основная волна прошла, остаются алго-боты. Возвращаемся к обычному профилю.
Нагрузка биржи за обычные сутки плюс анонс листинга в 13:00 — десятикратный пик держится благодаря заранее заложенному headroom

Правильный ответ на такие события — заранее заложенный headroom. В обычный день биржа работает на 30–40% реальной ёмкости, чтобы во время пика подняться до 90%, а затем вернуться к нормальной нагрузке. Этот запас напрямую отражается в счёте за инфраструктуру: большую часть времени дополнительные экземпляры почти простаивают, зато в критические минуты принимают на себя всплеск трафика.

Есть ещё один источник сложности: подсистемы масштабируются по-разному. Gateway и market data fan-out — почти линейно: добавили ресурсы и обработали больше запросов. Matching engine для одной пары не масштабируется горизонтально: у него одна очередь ордеров и один активный экземпляр. Увеличить общую пропускную способность можно шардированием по символам (per-symbol sharding из третьего раздела), а ускорить отдельный символ — более мощной машиной. Для листинга популярной монеты ей часто заранее выделяют отдельный физический узел.

Что биржа делает перед анонсом, который она контролирует (листинг):

  1. Прогревает пулы соединений. Gateway заранее поднимает воркеры, WebSocket сервера открывают сокеты заранее.
  2. Изолирует новую пару. Поднимает отдельный matching engine instance, чтобы всплеск на BTC/NEW не затронул BTC/USDT.
  3. Отключает дорогие фичи. Временно отключает сложные отчёты, медленные административные выгрузки, всё, что не критично для торговли.
  4. Увеличивает лимиты на ряд подсистем и уменьшает лимиты на некоторые API, чтобы скрипт-боты не смогли сожрать весь rate limit.
  5. Собирает on-call-команду. Старшие SRE и инженеры matching engine вместе следят за дашбордами и готовы вмешаться.

То, что не контролируется (обвал рынка), — это проверка на то, правильно ли биржа заложила headroom за последние 12 месяцев. Биржа, которая падает под таким событием, рискует не только деньгами сегодня, но и клиентами навсегда: «она легла, когда мне надо было выйти» — это самое неприятное воспоминание, которое остаётся у пользователя о любой бирже.

Безопасность: defense in depth

Слова «безопасность CEX» обычно вызывают в голове одну ассоциацию — кошельки. Это правильно, но слишком узко. Настоящая модель безопасности биржи — это defense in depth: много слоёв, каждый защищает следующий, и атакующий должен пробить все, чтобы добраться до денег.

Defense in depth — слои защиты вокруг активов
Активы
1. Периметр сетиL1
WAF, DDoS-защита, сегментация VPC
2. АутентификацияL2
OAuth, WebAuthn, 2FA, подпись API-запросов
3. АвторизацияL3
Роли, scopes, rate limits, разрешения API-ключей
4. HSM / MPCL4
Приватные ключи не покидают защищённого устройства
5. Холодное хранениеL5
Ключи offline, подпись требует ручной процедуры
Принцип: один слой может не выдержать атаку, но остальные должны её остановить.
Defense in depth: концентрические слои защиты вокруг клиентских активов, от периметра сети до холодного хранения

Разберём слои изнутри наружу.

1. Холодное хранение. Основная масса клиентских активов — в кошельках, которые физически отключены от сети. Их ключи не хранятся на серверах биржи вообще; они лежат в сейфе в отдельной юрисдикции, и для подписания транзакции требуется ручная процедура с m-из-n подписантами. Это самый последний барьер: даже если взломали всё остальное, из холодного кошелька украсть нельзя без того, чтобы атакующий оказался физически у сейфа с нужным числом подписантов.

2. HSM или MPC для «рабочих» ключей. Для hot и warm кошельков, из которых биржа ежедневно платит выводы, приватные ключи не лежат в файле на сервере. Они живут либо в hardware security module (HSM) — выделенном устройстве, которое физически не отдаёт ключ наружу, только подпись, — либо в multi-party computation (MPC) схеме, где «ключ» разделён между несколькими серверами и никто в одиночку не может его восстановить. Это защита от компрометации одного сервера: взломали машину — ключа там всё равно нет.

3. Авторизация. Для каждого API-запроса система проверяет, разрешена ли пользователю нужная операция и не превышены ли лимиты. Здесь работают роли, scopes, права API-ключей и rate limits. Типичная ошибка уровня security 101 — забыть об авторизации на редко используемом административном endpoint, который затем открывает доступ к чужому аккаунту.

4. Аутентификация. Прежде чем что-то авторизовывать, нужно знать, кто пришёл. Для клиентского UI — OAuth, WebAuthn, обязательный 2FA. Для API — ключ плюс HMAC-подпись с timestamp (мы видели этот паттерн в разделе 8). Для сотрудников биржи — SSO, обязательные hardware-токены, короткие сессии. Пароли — только как один фактор из многих, и никогда единственный.

5. Периметр сети. Всё, что выше, защищается внешним слоем: WAF от типичных атак, DDoS-защита от объёмных атак, сегментация VPC — чтобы даже если атакующий пробился через frontend, он не смог дойти до matching engine по внутренней сети. Администраторские интерфейсы — вообще в отдельной сети, доступной только через VPN с hardware-токеном.

Главное в defense in depth — асимметрия в пользу защитника: чтобы добраться до денег, атакующему нужно пробить все слои подряд; защитнику достаточно, чтобы хотя бы один из них удержал. Но эта асимметрия работает только при одном условии: каждый класс атак реально перекрыт хотя бы одним слоем. Если в архитектуре пропущен слой, который должен был ловить конкретный вектор, — для этого вектора у вас просто нет защиты, сколько бы других слоёв вы ни выстроили вокруг. Поэтому пропущенный слой — это не «чуть хуже»; это потенциальная дыра на всю стоимость актива.

И ещё один момент, о котором часто забывают: observability — часть безопасности. Если вы не видите, что кто-то пробует подбирать ваши API-ключи по брутфорсу, вы не заметите саму попытку. Аудит-логи, SIEM, алерты на аномальный доступ, мониторинг outbound traffic — всё это не «фичи безопасности», это основа.

KYC и AML

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

KYC — Know Your Customer, «знай своего клиента». Набор процедур, которыми биржа удостоверяется, что за каждым аккаунтом стоит реальный человек или компания: паспорт, селфи, подтверждение адреса проживания, иногда — источник средств. Цель — не дать анонимам, подсанкционным лицам и подставным аккаунтам открыть счёт.

AML — Anti-Money Laundering, «противодействие отмыванию денег». Эти процедуры анализируют поведение клиента после регистрации: отслеживают транзакции, ищут подозрительные паттерны, проверяют связь адресов с криминальными источниками и передают данные в финансовую разведку. Если KYC отвечает на вопрос «кто», то AML — на вопрос «что этот клиент делает с деньгами».

Эти два слоя работают в связке: KYC даёт идентичность, AML наблюдает за действиями этой идентичности во времени. По отдельности они дырявы — KYC без AML пропускает легально открытый счёт, через который потом гонят грязные деньги; AML без KYC видит подозрительные транзакции, но не может никому их пришить.

Этот раздел не о юриспруденции. Он о том, что KYC и AML — это не про «правила комплаенса», а про реальный инженерный слой, через который проходит каждый клиент и каждая транзакция. И если он сломан — биржа в лучшем случае получит штраф, в худшем — лишится лицензии в юрисдикции и потеряет доступ к фиатной инфраструктуре.

На высоком уровне система состоит из трёх слоёв:

  1. Идентификация на входе. Регистрация аккаунта, сбор документов, верификация паспорта и селфи, проверка адреса проживания, связь с санкционными списками (OFAC, UN, EU). Это — воронка KYC, обычно разделённая на уровни (tiers), где каждый уровень открывает новые возможности.
  2. Непрерывный мониторинг транзакций. Каждый депозит, вывод, внутренний перевод проходит через transaction monitoring: на какой адрес отправляется, связан ли он с известными рисковыми адресами и организациями (миксеры, darknet-маркеты, известные кошельки санкционных стран), не похож ли паттерн на структурирование (разбивку крупной суммы на мелкие для обхода порогов), не меняется ли поведение клиента резко.
  3. Отчётность и взаимодействие с регуляторами. Подача SAR (suspicious activity reports), ответы на запросы правоохранительных органов, выполнение travel rule (FATF Recommendation 16) — передача данных об отправителе и получателе при межбиржевых переводах выше определённого порога.
Воронка KYC — каждый уровень открывает новые возможности
Tier 0 — регистрация
Требования: Только email и пароль
Лимиты: Вход, просмотр котировок. Ввод/вывод запрещён.
100%
Tier 1 — базовая верификация
Требования: Имя, дата рождения, страна, телефон
Лимиты: Крипто-депозиты, торговля до $1 000/день, лимитированный вывод.
~62%
Tier 2 — документ + селфи
Требования: Паспорт или ID, live-фото, адрес проживания
Лимиты: Фиатные операции, торговля до $50 000/день, стандартные выводы.
~38%
Tier 3 — proof of funds
Требования: Выписка со счёта, источник дохода, декларация
Лимиты: Институциональные лимиты, OTC, деривативы, sub-accounts.
~4%
Проценты — иллюстративные. Реальные распределения зависят от юрисдикции и маркетинга биржи, но общая форма воронки одинакова: до каждого следующего tier доходит меньше пользователей.
Воронка KYC: уровни верификации и возможности, которые каждый уровень открывает

Для инженера здесь важны две вещи.

Первое — KYC не делается один раз. Он переходит в continuous re-KYC: если клиент не обновлял документы три года, биржа обязана попросить их заново. Если клиент вдруг начал получать депозиты с адресов, которые появились в санкционном списке после его регистрации — его нужно ограничить автоматически, а не через месяц, когда комплаенс-команда прочтёт отчёт. Всё это — отдельная очередь событий с отдельными SLA.

Второе — tiered KYC влияет на всю остальную систему. Лимиты торговли, доступность фиатных рельс, доступ к деривативам, возможность открывать sub-accounts — всё зависит от KYC tier. Эта информация используется десятком других подсистем, и её консистентность важна не меньше, чем консистентность баланса. Если один сервис видит пользователя как tier 2, а другой — как tier 0, это прямая дыра, через которую кто-нибудь обязательно пролезет.

Travel rule, санкционные проверки, мониторинг — всё это стоит денег и замедляет UX. Соблазн «упростить» огромен. Уроки последних десяти лет единообразны: биржи, которые не соблюдают KYC и AML на серьёзном уровне, либо сами исчезают под санкциями (BitMEX, затем более мелкие), либо лишаются банковских партнёров и не могут работать с фиатом. Комплаенс — не «налог на скорость», это инженерное требование, без которого продукт не существует в юрисдикциях, где живёт большинство пользователей.

Incident response: биржа не лжёт, биржа чинится

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

Протокол incident response обычно состоит из четырёх фаз:

  1. Detection. Алерт пришёл. Кто на дежурстве — начинает работу. Первая задача — понять, что именно видно в мониторинге, и присвоить инциденту серьёзность (S1 — все клиенты не могут торговать, S2 — часть клиентов, S3 — деградация).
  2. Containment. Ограничить распространение сбоя. Для matching engine это может означать остановку торгов по одному символу, для wallet service — приостановку выводов в одну сеть, для API — более жёсткий rate limit. На этом этапе важнее сдержать ущерб, чем сразу найти первопричину.
  3. Remediation. Починить. Это может занять от минут до дней. Параллельно — коммуникация с клиентами: биржа, которая молчит во время инцидента, теряет доверие быстрее, чем биржа, которая честно пишет «работаем над проблемой». Статусная страница обновляется в реальном времени.
  4. Post-mortem. После закрытия инцидента команда публикует разбор: что произошло, почему и какие меры не дадут проблеме повториться. Хороший post-mortem содержит таймлайн, root cause analysis и список action items. Плохой ограничивается фразой «Dear customer, we experienced a technical issue».

Некоторые инциденты требуют особых действий, которые биржа должна иметь в арсенале заранее, а не придумывать на ходу:

  • Halt a symbol. Остановить торги по одной паре. Все существующие ордера — либо остаются, либо отменяются (зависит от политики). Новые не принимаются. Это делается, когда на символе «что-то не то» — аномальная цена, подозрение на манипуляцию, проблема с оракулом.
  • Trade bust. Отменить уже исполненные сделки и вернуть балансы. Это крайне спорная мера, допустимая только в вопиющих случаях — например, при fat-finger ошибке на порядок больше обычного объёма. Правила trade bust должны быть опубликованы заранее.
  • Disclose a breach. Если произошёл взлом кошелька или утечка персональных данных — раскрыть публично. Быстро, честно, с оценкой ущерба. Попытки «подождать и понять масштаб» почти всегда оборачиваются тем, что новость выходит не от биржи, а от злоумышленника или от журналиста.

Incident response зависит не только от процесса, но и от культуры. Если инженеры боятся говорить об ошибках из-за возможного наказания, следующий инцидент обнаружат позже и устранят медленнее. Открытый разбор без поиска виноватых помогает быстрее признать проблему и сократить время восстановления.

Регулирование как архитектурное требование

Инженер CEX быстро узнаёт, что регулирование — это не «то, о чём думают юристы». Это вторая половина технического задания.

  • Travel rule. При переводе между биржами выше определённой суммы (обычно $1 000 или $3 000 в зависимости от юрисдикции) отправляющая биржа должна передать получающей информацию об отправителе. Для этого биржа подключается к сетям вроде TRP, Sumsub, Notabene — и этот протокольный слой сидит в потоке вывода. Если он сломан — вывод заблокирован.
  • Record retention. Все ордера, все сделки, все сообщения поддержки, все изменения KYC — должны храниться минимум 5–7 лет (зависит от юрисдикции). Это — прямое влияние на архитектуру базы данных и на стратегию холодного хранилища.
  • Отчёты регуляторам. Ежедневные, ежемесячные, ежеквартальные выгрузки. Биржа должна уметь достоверно сформировать отчёт за любой период, и тот должен сходиться с внутренним леджером копейка в копейку.
  • MiCA в ЕС, CFTC и SEC в США, FCA в Великобритании, MAS в Сингапуре. Каждая юрисдикция добавляет свои правила. Одни требуют отдельного юридического лица, другие — отдельного леджера для местных клиентов или отдельного API-endpoint. Глобальной бирже нужна не одна универсальная архитектура, а набор изолированных контуров для разных рынков.

Это влияет на архитектуру намного глубже, чем кажется на первый взгляд. Простой пример: если MiCA требует, чтобы клиентские фиатные средства хранились на отдельном счёте в отдельном банке (обычно так и есть), это значит, что внутренний леджер биржи должен уметь для каждого пользователя отслеживать, в каком именно банке находятся его евро — и уметь это отразить в отчёте.

Короткая мораль: регулятор — один из стейкхолдеров архитектуры, не «внешний раздражитель». Чем раньше инженер это примет, тем меньше будет переписываний в будущем.

Собираем всё вместе — и смотрим вперёд

Мы прошли девять разделов, каждый — про один кусок биржи: блокчейн-основы, философия, архитектура, matching engine, жизненный цикл ордера, леджер, кастоди, market data, эксплуатация. Это не лестница, по которой нужно подниматься снизу вверх, и не башня, где первый этаж держит на себе остальные. Это контур одной системы, в которой подсистемы взаимно опираются друг на друга. Matching engine не имеет смысла без журнала событий; журнал — без двойной записи; двойная запись — без сверки с on-chain-резервами; сверка — без сканера депозитов; сканер — без понимания, как блокчейн договаривается о консенсусе. Слабость в одной точке не остаётся локально: она протекает наружу и делает уязвимым всё, что от этой точки зависит.

У крупных крахов бирж за последнее десятилетие есть общая черта: критические ограничения системы оставались без контроля. Где-то не учитывали инварианты блокчейн-протокола. Где-то отсутствие двойной записи считали проблемой отчётности, хотя без неё нельзя надёжно вести саму биржу. Где-то multi-party control работал через один канал верификации и фактически превращался в single-party-схему. Выживали те площадки, чьи команды замечали такие разрывы и правильно реагировали на инциденты.

Цель этого гайда — чтобы, когда вы (или ваш AI-агент) будете строить, поддерживать, отлаживать или проектировать биржу, у вас была не «насмотренность», а структурированная модель. Модель, в которой каждый термин — matching engine, hot path, cold storage, double-entry, snapshot+delta, активная/пассивная пара, defense in depth — имеет не расплывчатое значение, а конкретное. Модель, в которой, услышав «у нас гэпы в стакане», вы автоматически вспоминаете раздел 8 и знаете, куда смотреть. Модель, в которой, услышав «у нас расходится баланс на $47», вы автоматически вспоминаете раздел 6 и знаете, какие счета сверять.

Что осталось за кадром: деривативы

Всё, о чём мы говорили, — спотовая торговля. Клиент покупает актив по текущей цене и владеет им. У современных бирж есть ещё деривативы: фьючерсы, бессрочные контракты (perpetual swaps), опционы, с плечом, с ликвидациями, с индексами финансирования. По объёму деривативы на большинстве крупных CEX превышают спот в несколько раз.

Архитектура деривативов добавляет целый новый ряд подсистем: risk engine с постоянной переоценкой позиций и маржи, liquidation engine, funding rate calculator, insurance fund, index price oracle — и всё это должно работать в той же hot-path-парадигме, что и matching engine. И граница между типами отказов там размывается: операционный сбой на деривативной бирже может мгновенно превратиться в кризис платёжеспособности, потому что невыплаченные ликвидации накапливают системный риск гораздо быстрее, чем расходящийся на копейки спот.

Дополнительное чтение

  • FATF — Virtual assets and travel rule — основной регуляторный источник по AML-требованиям для CEX
  • Kraken engineering blog — один из немногих публично доступных блогов, где инженеры CEX честно пишут об архитектуре, отказах и масштабировании

Если хочется конкретики по тому, как биржи разоряются на практике, четыре документа закрывают весь спектр причин: