Riscos do particionamento em rede quando um cérebro dividido cria uma falha de segurança

4

Estou procurando criar uma solução de rede escalonável e de alta disponibilidade usando um sistema distribuído de dados. Um nó aqui descreve uma rede que possui controle sobre uma cópia dos dados. Esses nós podem conter mais de uma máquina, mas possuem uma cópia dos dados.

Os nós conterão registros de dados que podem estar em estado gasto ou não gasto. Um cliente pode solicitar uma transição para que um registro passe de um estado não gasto para um estado gasto (uma solicitação para gastar). Existe um risco de segurança se eles conseguirem fazer isso mais de uma vez.

Um único nó, se tiver uma conexão com todos os outros nós, pode informar aos nós que um gasto foi solicitado e pode garantir que nenhum outro nó deseje acessar os dados e que o gasto ainda não tenha ocorrido. O nó pode alterar o estado dos dados para gasto e outros nós não farão isso, pois sabem que um dos nós está atualizando-o e processando o gasto. Todos os nós alterarão os dados, portanto, o registro estará no estado gasto.

Se um nó não puder alcançar outro nó, ele poderá assumir que o outro nó está inativo e continuará operando com os outros nós até que o outro nó seja ativado novamente. Nesse caso, o nó enviará todas as atualizações para o nó que retornou. Se esse nó com falha estivesse no meio de uma operação de gasto incompleta no momento, ele poderá ser concluído. Isso causaria menor tempo de inatividade para algumas operações. Isso seria no caso em que um nó informa aos outros nós que serão gastos e, em seguida, falha antes de concluir o processo de gasto. Nesse caso, os outros nós são impedidos de atualizá-lo, portanto, o nó com falha precisa ficar on-line antes de poder ser concluído.

O problema é que o processamento para o gasto só pode acontecer uma vez. Se a rede foi particionada, um invasor sabendo disso pode solicitar o gasto em uma partição e também no outro. Cada partição da rede assumiria que a outra estava inativa e, portanto, operaria de forma independente. Isso pode fazer com que os gastos sejam processados mais de uma vez.

Isso não seria um problema se a solicitação para os dois lados da rede não estivesse sendo feita durante o tempo em que eles foram particionados. A rede se tornaria eventualmente consistente quando as conexões fossem restabelecidas. Se um ataque tiver êxito, os nós aprenderão sobre o ataque quando restabelecerem conexões, porque os dois lados da rede anunciariam a mesma alteração.

Portanto, é um ataque detectável, mas é praticamente possível?

Um invasor precisa deliberadamente tentar fazer isso. O software não foi projetado para fazer várias solicitações de gastos de uma só vez. Há um custo de tempo para o ataque. Se o invasor falhar, levará algum tempo até que ele possa recriar um registro não gasto. Criar registros não gastos requer dinheiro. E mais dinheiro precisará ser usado em um único ataque para obter um benefício maior. A razão pela qual há um custo de tempo, é que levaria tempo para receber o dinheiro de volta para tentar novamente. Eles poderiam pagar muitos ataques menores e, em seguida, o benefício para eles seria menor e os danos causados, menos também.

Certamente partições são tão raras naturalmente, que um atacante teria que ser ridiculamente sortudo de ganhar, se tentasse atacar a qualquer momento?

Se uma conexão é naturalmente perdida, um nó pode parar todas as operações e tentar uma reconexão. Usar um tempo limite baixo para a conexão com o nó significa que ele não precisa causar nenhum tempo de inatividade (talvez apenas uma latência maior rara). Se a reconexão falhar, ela continuará tentando, mas, em seguida, reiniciará as operações (supondo que o nó esteja inativo). Alguma coisa desse tipo protegeria contra erros ocasionais de conexão?

Então um atacante seria capaz de detectar / causar uma partição na rede? Qual a probabilidade de ocorrerem partições e por quanto tempo? De que maneiras as questões podem ser resolvidas, se possível?

Obrigado.

    
por Matthew Mitchell 18.08.2012 / 17:28

3 respostas

5

Tendo lidado com problemas semelhantes em cenários de Cluster, estou familiarizado com a situação descrita por você. Tais sistemas freqüentemente têm o conceito de quorum, razão pela qual tais sistemas requerem um número ímpar de nós membros. O quorum é usado para determinar as partições majoritárias e minoritárias.

O quorum é o número, maior que a metade, que define qual é o número mínimo de nós disponíveis que precisam estar presentes para fornecer serviços. Se uma partição de rede ocorrer, apenas uma partição terá quorum, a outra interromperá os serviços até que a partição desapareça. Se um evento partição múltipla acontecer, isso pode levar a que nenhum serviço seja fornecido. No entanto, isso garante que apenas um nó está sendo veiculado e é assim que a consistência é fornecida.

Quanto à probabilidade de uma partição, isso depende da sua infraestrutura e de como os nós estão se comunicando com o estado de disponibilidade entre eles.

Quanto à capacidade de detectar um evento de partição, isso depende do seu código. A principal coisa que tornaria tal ataque possível é se ambas as partições forem independentemente endereçáveis durante uma partição, o que pode não ser o caso. Na minha experiência, as partições de rede freqüentemente excluem os usuários finais de uma partição, assim como os outros nós. Se as partições não forem endereçáveis, então é muito menos provável que esse ataque tenha sucesso.

    
por 18.08.2012 / 18:23
1

O armazenamento distribuído funciona melhor com a origem única dos dados sendo replicados a cada n segundos, usando, por exemplo, Índice SQL e usando regras de replicação, foram para empurrá-lo. Também memória central "SQL" para controlar os estados.

Assim, quando você altera o estado do objeto, isso está sendo comunicado ao nó de origem e a transação é executada em SQL com o bloqueio no registro.

Se o nó não puder alcançar a origem no momento, a operação deverá falhar, pois o estado de origem é apenas no servidor de origem.

É como o fluxo de trabalho de origem, onde a origem tem "memória" - estados e borda "conteúdo" - objetos.

É teoricamente impossível ignorar o modelo acima da borda e da memória central, preservando a segurança e fazendo isso de uma maneira simples. O modelo acima é o mais eficiente e mais correto, e a distorção dificulta a vida.

    
por 18.08.2012 / 17:56
0

Se você está procurando uma solução prática para permitir que as transações continuem enquanto houver uma partição, tenho uma ideia.

Para cada novo registro de dados criado como não gasto, atribua-o a um único nó. Enquanto a rede é particionada, os registros de dados atribuídos aos nós alcançáveis são os únicos que podem ser gastos pelos clientes. Quando a partição é resolvida, todos os nós ressincronizam quais registros de dados são gastos. Como somente os modos acessíveis pelos clientes gastaram registros atribuídos a esses nós, não deve haver registros sobre-gastos.

O pensamento terá que ser colocado em como os registros são atribuídos aos nós e o que fazer quando um nó ficar sem seus próprios registros durante a operação unificada e particionada.

    
por 18.08.2012 / 19:44