Я хочу создать масштабируемое сетевое решение с высокой доступностью, используя распределенную систему данных. Узел здесь описывает сеть, которая контролирует одну копию данных. Эти узлы могут содержать более одного компьютера, но имеют одну копию данных.
Узлы будут содержать записи данных, которые могут находиться в потраченном или неизрасходованном состоянии. Клиент может запросить переход записи из неизрасходованного состояния в потраченное (запрос на расходование). Если им удастся сделать это более одного раза, возникнет угроза безопасности.
Одиночный узел, если он имеет соединение со всеми другими узлами, может сообщить узлам, что были запрошены расходы, и может гарантировать, что другие узлы не хотят получать доступ к данным и что расходы еще не произошли. Узел может изменить состояние данных на потраченные, а другие узлы не будут этого делать, так как они знают, что один из узлов обновляет его и обрабатывает расходы. Все узлы изменят данные, поэтому запись будет в потраченном состоянии.
Если узел не может связаться с другим узлом, он может предположить, что другой узел не работает, и продолжит работу с другими узлами, пока другой узел не восстановится. В этом случае узел будет отправлять все обновления на узел, который вернулся. Если этот отказавший узел находился в процессе незавершенной в то время операции расходования, он может завершить ее. Это может вызвать незначительное время простоя для некоторых операций. Это было бы в том случае, когда узел сообщает другим узлам, что он потратит, а затем выходит из строя, прежде чем он сможет завершить процесс расходования. В этом случае другие узлы заблокированы для его обновления, поэтому отказавший узел должен вернуться в оперативный режим, прежде чем его можно будет завершить.
Проблема в том, что обработка расходов может происходить только один раз. Если сеть была разделена на разделы, злоумышленник, зная об этом, может запросить расходы на один раздел, а также на другой. Каждый раздел сети будет предполагать, что другой не работает, и поэтому будет работать независимо. Это может привести к тому, что расходы будут обработаны более одного раза.
Это не было бы проблемой, если бы запрос к двум сторонам сети не выполнялся в то время, когда они были разделены. Сеть станет в конечном итоге согласованной, когда соединения будут восстановлены. Если атака была успешной, узлы узнают об атаке, когда они повторно устанавливают соединения, потому что две стороны сети объявят об одном и том же изменении.
Итак, это обнаружимая атака, но возможно ли это практически?
Злоумышленник должен сознательно пытаться это сделать. Программа не предназначена для одновременной отправки нескольких запросов на расходование средств. Атака требует времени. Если злоумышленник потерпит неудачу, потребуется время, прежде чем он сможет воссоздать неизрасходованную запись. Создание неизрасходованных записей требует денег. И чтобы получить большую выгоду, нужно будет потратить больше денег на одну атаку. Причина, по которой есть временные затраты, заключается в том, что потребуется время, чтобы вернуть деньги и повторить попытку. Они могли позволить себе много меньших атак, и тогда польза для них была бы меньше, а нанесенный ущерб - тоже.
Несомненно, разделы настолько редки по своей природе, что злоумышленник должен быть смехотворно удачливым, чтобы выиграть, если попытается атаковать в любое время?
Если соединение естественно потеряно, узел может остановить все операции и попытаться восстановить соединение. Использование малого тайм-аута для подключения к узлу означает, что это не должно вызывать простоя (возможно, только в редких случаях увеличенная задержка). Если повторное подключение не удалось, попытка будет продолжена, но затем перезапущены операции (при условии, что узел не работает). Может ли что-нибудь подобное защитить от случайных ошибок подключения?
Так сможет ли злоумышленник обнаружить / вызвать раздел в сети? Насколько вероятно возникновение разделов и на какой срок? Какими способами можно решить проблемы, если это возможно?
Спасибо.
Имея дело с аналогичными проблемами в сценариях кластеризации, я знаком с описанной вами ситуацией. Такие системы часто имеют концепцию кворума, поэтому такие системы требуют нечетного числа узлов-членов. Кворум используется для определения разделов большинства и меньшинства.
Кворум - это число больше половины, которое определяет минимальное количество доступных узлов, которые должны присутствовать для предоставления услуг. Если возникает сетевой раздел, только один раздел будет иметь кворум, другой остановит службы, пока раздел не исчезнет. Если несколько разделов событие может привести к тому, что услуги не будут оказываться вообще. Однако это гарантирует, что обслуживается только один узел, и именно так обеспечивается согласованность.
Что касается вероятности раздела, это зависит от вашей инфраструктуры и того, как ваши узлы сообщают друг другу состояние доступности.
Что касается их способности обнаруживать событие раздела, это зависит от вашего кода. Главное, чтобы такая атака стала возможной, если оба раздела независимо адресуемый во время раздела, что может и не быть. По моему опыту, сетевые разделы часто исключают конечных пользователей как из одного раздела, так и из других узлов. Если разделы не адресуемы, то вероятность успеха этой атаки намного меньше.
Распределенное хранилище лучше всего работает с одним источником данных, реплицируемым каждые n секунд, например, с использованием Индекс SQL и правила репликации должны были его подтолкнуть. Также центральная память «SQL» для управления состояниями.
Проще говоря, когда вы изменяете состояние объекта, это передается на узел источника, и транзакция выполняется в SQL с блокировкой записи.
Если узел не может достичь источника в то время, операция должна завершиться неудачей, поскольку состояние источника находится только на сервере происхождения.
Это похоже на рабочий процесс origin-edge, где origin имеет «память» - состояния, а граничный «контент» - объекты.
Теоретически невозможно обойти описанную выше модель периферийной и центральной памяти с сохранением безопасности и сделать это простым способом. Вышеупомянутая модель является наиболее эффективной и правильной, и ее фаззинг только усложняет жизнь.
Если вы ищете практическое решение, позволяющее продолжать транзакции, пока есть раздел, у меня есть идея.
Для каждой новой записи данных, которая создается как неизрасходованная, присвойте ее одному узлу. Пока сеть разделена, записи данных, назначенные доступным узлам, - единственные, которые разрешено использовать клиентам. Когда раздел разрешен, все узлы повторно синхронизируют, какие записи данных расходуются. Поскольку только те режимы, которые были доступны клиентам, израсходовали записи, назначенные этим узлам, не должно быть избыточных записей.
Необходимо подумать о том, как записи назначаются узлам и что делать, когда на узле заканчиваются свои собственные записи во время как унифицированной, так и секционированной операции.