Autenticação para um jogo multiplayer via soquetes
11
Estou implementando um protocolo binário personalizado para um novo jogo multiplayer em que estou trabalhando. É um jogo de estratégia baseado em turnos, então o tempo não importa. Atualmente, eu tenho a parte básica de sincronização de dados do sistema concluída e fiquei imaginando como o login / logout e a criptografia do usuário geralmente são feitos para jogos MMORPG ou similares.
Você pode recomendar um esquema para a transmissão de senha segura / secreta durante o login? (Troca de chaves Diffie-Hellman?)
Como implemento criptografia forte para pacotes de dados? (AES de 128 bits? .. ou qualquer esquema que esta publicação se refira como "criptografia mais forte do que você provavelmente trava")
Existem esquemas de formato de datagrama que ajudam a fortalecer o servidor do jogo para reproduzir ataques, pacotes de dados inválidos e similares?
SRP - Senha remota segura - Baseia-se no Diffie-Hellman. A ideia é que você possa fazer uma verificação de senha mútua sem nunca transferir a senha ou qualquer informação que possa ser usada para derivá-la. Embora seja seguro, você ainda deve usar hash e alterar suas senhas, pois o servidor nunca deve armazená-las em texto sem formatação .
A vantagem do SRP é que, uma vez concluído, também fornece uma chave de criptografia negociada mutuamente que um invasor não seria capaz de deduzir, considerando os dados transferidos. Isso significa que você pode usar um algoritmo de criptografia simétrica (como o AES) assim que o usuário for autenticado.
Supondo que você esteja usando o UDP com sua própria implementação confiável / ordenada (orientada à conexão): criptografe toda a carga de reprodução do UDP - incluindo seu 'número de sequência de pacotes'. Se o seu sistema for projetado corretamente, ele rejeitará automaticamente as mensagens reproduzidas e um invasor não poderá alterar o número da sequência de pacotes porque está criptografado (portanto, é possível uma repetição - mas seria automaticamente ignorada).
Pensamentos
Sua autenticação deve ser segura? Absolutamente. Não faça concessões em termos de segurança quando uma senha estiver em questão. Portanto, você definitivamente deveria considerar a primeira bala na minha resposta.
Seus dados devem estar seguros? Somente se for uma compra / micro transação no jogo - e por que não usar apenas algo testado e verdadeiro como HTTPS. Criptografar o tráfego do jogo provavelmente não é uma solução viável pelos seguintes motivos:
É paranóia completa.
Isso aumentará o tempo de CPU em seu servidor, a menos que você possa comprar módulos de criptografia de hardware (caros).
Não importa quanta segurança você fornece para seus dados por cabo - alguém pode seqüestrar o processo do cliente e interceptar mensagens no momento antes de serem criptografadas e enviadas. Essa não é apenas uma possibilidade, mas é infinitamente mais possível, pois é muito mais fácil injetar código em comparação aos pacotes de interceptação. Se você está fazendo isso para a prevenção de fraudes, está perdendo completamente e totalmente seu tempo.
Infelizmente, em termos de segurança de senha, não há nada que você possa razoavelmente fazer sobre um sistema seqüestrado; o cliente se tornou hostil. Os dongles Wizz da Blizzards foram projetados para lidar com isso - mas não tenho certeza de quão seguro é (especialmente se você o deixar conectado).
Por favor, se você estiver criptografando para evitar fraudes, abandone-o. Você vai ser breve - eu lhe dei as informações caso você não seja. Lembre-se de que você pode criptografar seletivamente os pacotes pelo primeiro byte do pacote e indicar se o restante está criptografado: embora, mais uma vez, eu continuaria com o HTTPS se precisar fazer coisas como transações com cartão de crédito: elas são extremamente raras e O HTTPS é projetado por especialistas - diferente de algo que você ou eu projetou.
Tudo isso dito, a Blizzard realmente criptografa seu tráfego WoW. A principal razão pela qual isso ocorreu foi porque alguém, provavelmente amador, decidiu que tentaria usar um algoritmo de criptografia caseiro; isso deu muito certo . Mesmo se você usar algoritmos padrão do setor, há uma boa chance de alguém fazer engenharia reversa do seu código e simular o código - depois que o cliente digita sua senha, não há como dizer que um sistema não suportado está conectado.
+1 por dizer que a criptografia de pacotes de dados para prevenção de trapaças é inútil. OP: verifique tudo o que você recebe do cliente, execute verificações de sanidade, verifique novamente se a ação solicitada pelo cliente é possível, verifique o alcance das armas, a velocidade de movimento etc. mas não perca tempo protegendo seu cliente, pois ele será hackeado se seu jogo vale a pena. Algumas empresas de MMO criptografam e ofuscam seus clientes / protocolos, mas isso não evita trapaças, mas torna mais difícil para, por exemplo, criadores de bots, obter bons resultados, e mesmo isso é feito por equipes dedicadas de especialistas.
Gilead
1
Uma pequena dúvida sobre sua terceira resposta: apenas criptografar os pacotes pode não ser suficiente para impedir a violação, pois muitos esquemas de criptografia são pelo menos um pouco maleáveis . Para proteger a integridade da mensagem, você precisa de um modo de criptografia MAC ou autenticado .
Ilmari Karonen
+1 Obrigado por uma resposta muito completa. Olhando para a implementação do SRP agora. Quais são as recomendações sobre a função hash usada para senhas? MD5? Como seria o protocolo OTR (Off the Record) para esse caso de uso? funcionaria bem para auth / crypto em vez de SRP? Caso eu use SRP, precisaria usar um dos seguintes modos de "criptografia autenticada"? (OCB 2,0, chave Wrap, CCM, EAX, cifra-depois-MAC e GCM)
Robinicks
1
@Jenko usa a família de algoritmos SHA (provavelmente SHA1) - você deve evitar o MD5 atualmente. O OTR não é realmente algo que você deva observar - não foi projetado para ser seguro / obscuro (na verdade, foi projetado para que alguém possa forjar pacotes com mais facilidade), também foi projetado para mensagens instantâneas e não para comunicação com a máquina. Nenhum desses modos é necessário, basta usar o SRP: quando você tiver uma chave simétrica negociada mutuamente, simplesmente poder criptografar algo é garantia suficiente para que você esteja conversando com o terceiro correto. Além disso, novamente, reli meus últimos dois parágrafos.
Jonathan Dickinson
1
Na verdade, tenho uma sugestão ainda melhor: use uma implementação DTLS sobre UDP existente e não tente criar sua própria. Isso economizará tempo e há muitos detalhes pequenos, mas críticos, que são fáceis de errar se você tentar criar sua própria camada de criptografia de datagrama.
Ilmari Karonen
2
Acho que meu último comentário à excelente resposta de Jonathan vale a pena expandir para uma resposta própria:
Se você não tem muita experiência em criptografia, não deve tentar criar sua própria camada de criptografia, se puder evitá-la. Se você fazer tem um monte de experiência de criptografia, você deve saber melhor do que para projetar sua própria camada de criptografia se você pode evitá-lo.
Em vez disso, tente encontrar uma biblioteca de criptografia existente, padronizada e bem testada que faça o que você precisa. No seu caso, eu recomendaria o GnuTLS , que, de acordo com a Wikipedia , fornece autenticação TLS-SRP ( RFC 5054 ) e comunicação UDP segura com DTLS ( RFC 6347 ). O primeiro cuida do logon, enquanto o último protege o canal seguro, formado assim, tanto contra a espionagem quanto contra ataques ativos, e pode até protegê-lo contra ataques de repetição .
Estou usando o TCP. Este é um tipo de jogo muito diferente para um cliente específico. Semelhante ao jogo / aposta, todas as informações que podem ser usadas para seqüestrar o processo aumentam as chances de perdas desnecessárias por parte da casa. Precisamos manter os dados extremamente seguros, porque informações são dinheiro neste caso.
Robinicks
OK, se você estiver usando TCP, é ainda mais fácil: você pode usar o TLS 1.2 normal em vez do DTLS, o que oferece mais opções para você escolher. Eu ainda recomendaria a biblioteca GnuTLS.
Ilmari Karonen
Vou fazer um pouco de pesquisa e ver se consigo consultar o código-fonte TLS nos lados do cliente e do servidor e basear meu protocolo em torno do que ele faz. Isso seria forte o suficiente? Essencialmente, é apenas a criptografia de pacotes com alguma cifra / modo, correto?
Robinicks
Não, há muito mais no protocolo TLS do que isso. É por isso que você deseja usar uma biblioteca padrão que a implementa, em vez de criar sua própria.
Acho que meu último comentário à excelente resposta de Jonathan vale a pena expandir para uma resposta própria:
Se você não tem muita experiência em criptografia, não deve tentar criar sua própria camada de criptografia, se puder evitá-la. Se você fazer tem um monte de experiência de criptografia, você deve saber melhor do que para projetar sua própria camada de criptografia se você pode evitá-lo.
Em vez disso, tente encontrar uma biblioteca de criptografia existente, padronizada e bem testada que faça o que você precisa. No seu caso, eu recomendaria o GnuTLS , que, de acordo com a Wikipedia , fornece autenticação TLS-SRP ( RFC 5054 ) e comunicação UDP segura com DTLS ( RFC 6347 ). O primeiro cuida do logon, enquanto o último protege o canal seguro, formado assim, tanto contra a espionagem quanto contra ataques ativos, e pode até protegê-lo contra ataques de repetição .
fonte