Como impedir que um servidor invadido falsifique um servidor mestre?

8

Desejo configurar um modelo de jogo multicamada baseado em sala em que os jogadores possam hospedar partidas e servir como host (ou seja, o servidor com poder autoritário). Desejo hospedar um servidor mestre que rastreie os itens do jogador, classificação, dinheiro, exp, etc.

Nesse modelo, como posso impedir que alguém que hospeda um jogo (com um servidor modificado) falsifique o servidor mestre com resultados de correspondência inválidos, obtendo assim exp, dinheiro ou classificações.

Obrigado. -Cody

Cody Smith
fonte
4
Resposta genérica ainda mais curta: você não pode. Assim que o código é executado em um sistema que não está sob seu controle, alguém pode hacká-lo de alguma forma, como por exemplo, executando mil correspondências e relatando apenas aquelas com resultados favoráveis.
Jari Komppa
11
Eu concordo com @JariKomppa. Além disso, não há necessidade de assinar suas postagens.
Jcora
11
@ Cody: Eu dei duas respostas abaixo, com base em diferentes interpretações da sua pergunta. Poderia, por favor, me informar qual deles (se houver) está mais próximo do que você gostaria de perguntar?
Ilmari Karonen

Respostas:

4

Tem sido apontado que minha resposta anterior pode ter sido baseada em um mal-entendido do que você quis dizer com "falsificação". (Em caso afirmativo, informe-me e eu o excluirei.)

Se o que você deseja impedir são os servidores de jogos que enviam dados falsos para o servidor mestre, então - como Jari Komppa observa - geralmente é impossível impedir completamente. Na verdade, é simplesmente uma variante do problema clássico de prevenção de trapaça para vários jogadores , exceto nos servidores intermediários, e não nos clientes suspeitos de trapaça. Muitas das mesmas técnicas usadas para a prevenção tradicional de trapaça poderiam funcionar aqui também, mas, como sempre, nenhuma delas é completamente à prova de falhas.

Dito isto, há são algumas coisas que você poderia fazer que especificamente ajudam contra servidores batota. Um deles seria fazer com que cada jogador de uma partida contatasse separadamente o servidor mestre e confirmasse que estão participando dessa partida. (Você provavelmente desejará fazer isso antes do da partida, para garantir que todos concordem com quem são os participantes e que ninguém fique tentado a afirmar que não participou de uma partida que perdeu. Você pode usar assinaturas digitais para adie que, no entanto, essencialmente, você pode fazer com que todos os jogadores de uma partida assinem uma mensagem dizendo " Eu sou o jogador X e estou participando da partida M no servidor S no momento T com os jogadores Y, Z e W."e enviá-lo ao servidor do jogo, que posteriormente poderá retransmiti-lo ao servidor mestre.) Dessa forma, você pode pelo menos garantir que um servidor trapaceiro não possa afetar a classificação de qualquer jogador que não jogue naquele servidor .

Isso é particularmente útil se você estiver usando algo como classificações Elo, em que a classificação dos jogadores depende principalmente de seu desempenho relativo . Claro, alguém executando um servidor falso pode ainda criar um monte de contas falsas e enviar resultados dizendo que sua própria conta supera as falsas, mas com um sistema de classificação relativo, tudo o que fará é fazer com que a conta do trapaceiro fique ligeiramente acima das falsificações ( que por sua vez terá classificações inferiores).

Outra coisa óbvia a ser feita para desencorajar a trapaça é permitir que os jogadores verifiquem os resultados de suas partidas diretamente no servidor principal. Se um jogador vence uma partida em um novo servidor, mas os resultados enviados ao servidor mestre dizem que eles perderam (ou se os resultados nunca foram enviados), isso permitirá que eles saibam que algo suspeito está acontecendo. Felizmente, nesse ponto, eles denunciam o servidor por trapaça ou, pelo menos, votam com os pés e nunca mais jogam nesse servidor.

Na verdade, você pode fazer isso automaticamente: após cada jogo, depois que os resultados forem enviados ao servidor principal, os clientes os buscarão no servidor principal e compará-los com a forma como o cliente pensa que o jogo terminou. Se houver uma incompatibilidade, relate-a ao jogador (para que eles saibam que algo está errado) e ao servidor mestre (para que você possa detectar servidores trapaceiros). Obviamente, como operador do servidor principal, você precisará decidir quem está mentindo - o servidor ou o jogador - mas, na maioria dos casos, esperançosamente, na maioria dos casos, isso será bastante óbvio a partir do padrão dos relatórios.

Ilmari Karonen
fonte
Muito obrigado Ilmari, ambas as respostas foram fantásticas (por favor, mantenha-as por perto). Desculpe pelo atraso, fui desviado. -Cody
Cody Smith
5

Nota: Esta resposta pode ser baseada em um mal-entendido da pergunta - veja os comentários abaixo.


Resposta curta e genérica: use assinaturas digitais .

Especificamente, o servidor mestre deve ter uma chave privada para um esquema de assinatura digital adequado (RSA, DSA, ECDSA etc.) e deve, de alguma forma, retransmitir com segurança sua chave pública a todos os clientes. Em seguida, o servidor pode assinar todos os dados que envia aos clientes com a chave privada (ou possivelmente usá-los para negociar um segredo compartilhado utilizável para criptografar simetricamente e / ou autenticar as comunicações entre ele e esse cliente em particular) e o cliente pode usar a chave pública para verifique se a assinatura foi gerada pelo servidor.

Naturalmente, o seu próximo problema é distribuir a chave pública para que um servidor não autorizado não spoof pode que e substituir a sua própria chave pública. Isso pode não ser tão difícil se você puder fazer isso com antecedência (por exemplo, distribuir a chave junto com o executável do jogo), mas fica complicado se você precisar fazer isso mais tarde, por exemplo, porque a identidade do servidor mestre não é conhecida em avançar. Uma solução padrão é distribuir alguma outra chave pública (cuja chave privada correspondente é conhecida apenas por você) antecipadamente a todos os clientes e assinar a mensagem que contém a chave pública do servidor mestre com essa outra chave antes de transmiti-la.

De fato, você pode estender ainda mais essas cadeias de assinatura - digamos, ter uma chave privada mestre super-secreta, que é mantida bloqueada em algum lugar seguro e cuja chave pública é conhecida por todos os clientes, e outra chave privada de "uso diário" que é usado para realmente assinar as chaves do servidor e cuja chave pública é ela própria assinada com a chave mestra super-secreta antes de ser trancada no cofre. Isso não é tão útil por si só, mas se torna potencialmente muito útil se você também incluir algum mecanismo para revogar chaves comprometidas, de modo que, por exemplo, se sua chave de uso diário vazar, você pode revogá-la e gerar outra.

O que descrevi acima é um tipo rudimentar de infraestrutura de chave pública . Na verdade, implementar um com segurança pode ser bastante complicado, mas felizmente isso já foi feito antes. De fato, sempre que você se conecta a um site (como Wikipedia ) usando HTTPS , isso é exatamente o que o navegador faz: recebe um certificado de chave pública do servidor, verifica se o certificado corresponde ao nome do servidor na URL, não é listado como revogado e foi assinado por uma autoridade de certificação e, em seguida, usa-o para negociar uma chave de criptografia simétrica temporária conhecida e confiável , conhecida apenas por si e pelo proprietário da chave privada correspondente ao certificado. Essa chave simétrica é usada para criptografar e autenticar todos os dados enviados entre o cliente e o servidor.

Em particular, você realmente deve dar uma olhada nas bibliotecas SSL / TLS existentes (que geralmente vêm com uma implementação de PKI X.509 ), ou possivelmente na SPKI . Isso ainda é um pouco complicado, mas provavelmente mais fácil (e mais seguro) do que tentar criar o seu próprio.

Ilmari Karonen
fonte
Provavelmente, estou errado, por favor, corrija-me se for o caso, mas acho que você está perdendo o objetivo da pergunta. Ele quer permitir que as pessoas criem seus próprios servidores, que reportem estatísticas para um servidor mestre. Quando ele faz isso, não há como impedir os hackers (@Jari Kompppa está certo). -1 por enquanto.
Jcora #
11
@Bane: Você pode estar certo. Eu interpretei a frase "falsificando o servidor principal" na pergunta como " fingindo ser o servidor principal", mas depois de reler a pergunta, percebo que ele poderia ter significado " enviar dados falsos ao servidor principal". Você está certo de que as assinaturas digitais não ajudarão de forma alguma contra isso.
Ilmari Karonen
2

Isso depende da natureza do jogo e do motivo pelo qual você está descarregando a função de servidor.

Em certas circunstâncias, você pode conseguir isso principalmente com logs de auditoria criptográficos. Por exemplo, se for um jogo baseado em turnos para dois jogadores e você pode providenciar para que cada cliente tenha uma chave assimétrica privada para fins de assinatura, você pode ter um protocolo ao longo das linhas de

  • O estado inicial S0 inclui um identificador exclusivo para o jogo (para impedir ataques de repetição) e é assumido como constante. Se houver um elemento aleatório, ele deverá ser produzido pelo servidor central e armazenado em cache para comparação futura.
  • P1 faz o movimento m1; assina o estado resultante S1, produzindo a assinatura C1; e envia com sua jogada (S1, C1, m1) para P2.
  • P2 faz o movimento m2; assina o estado resultante S2, produzindo a assinatura C2; e envia com sua mudança (S2, C2, m2) para P1.
  • etc.

No final, os dois clientes enviam o resultado ao servidor central e, se discordam, enviam as trilhas de auditoria: (S1, C1, m1), (S2, C2, m2) etc. Como cada jogador assinou seus movimentos, eles estão comprometidos com eles.

Ainda é vulnerável que um jogador faça o DDOS do outro para impedir que eles enviem seus resultados, mas realmente não há muito que você possa fazer sobre isso.

Nota: este é apenas um esboço rápido - tenho certeza de que, se você publicá-lo no crypto.stackexchange.com, alguém fará buracos enormes nele - mas acho que o princípio é válido. Faça com que qualquer esquema que você design revise por alguém que conhece o material antes de começar a confiar nele.

Peter Taylor
fonte
Você pode evitar o problema de DoS exigindo que os logs de auditoria sejam enviados, a menos que todos os jogadores enviem um resultado e concordem com ele. No entanto, outra questão é que um jogador que percebeu que estava perdendo poderia simplesmente desistir do jogo. Você pode decidir que desistir significa perder, mas, em seguida, um jogador pode fazer parecer que foi seu oponente que desistiu, acrescentando um movimento extra à trilha de auditoria. Uma maneira de contornar isso seria permitir que os jogadores baixassem as trilhas de auditoria enviadas e depois alterassem suas próprias, mas isso poderia resultar em alguns jogos bastante prolongados.
Ilmari Karonen