feat(netcode): serveur DTLS-PSK (côté serveur) — franchit le mur du chiffrement
Build Game Server / build (push) Successful in 20s
Build Game Server / build (push) Successful in 20s
Implémente le pendant serveur du DTLSHandlerComponent d'UE (la pile client est
[DTLS, Stateless]) : le client exige un DTLS en mode PSK dont l'identité = user_id.
- DtlsPskStore : table user_id -> PSK 32o, chargée depuis l'env (PROSPECT_DTLS_PSKS,
rendu Vault) — aucune clé en dur ni commitée.
- DtlsPacketTransport : pont entre l'API bloquante DTLS de BouncyCastle et le modèle
paquet-par-paquet du PacketHandler (handshake sur thread dédié).
- ProspectPskTlsServer : serveur DTLS-PSK BouncyCastle (DTLS 1.2, identité=user_id).
- DTLSHandlerComponent : composant du pipeline (Incoming déchiffre / Outgoing chiffre),
activé au NMT_Hello portant un EncryptionToken.
- UWorld.NotifyControlMessage : sur NMT_Hello chiffré, si la PSK de l'identité est
connue -> NMT_EncryptionAck + BeginHandshake ; sinon warning (comme avant).
Compile (0 erreur, BouncyCastle 2.4). ⚠️ Le framing exact DTLS-sur-PacketHandler et
le routage des records de handshake demandent une ITÉRATION EN LIVE contre le vrai
client (invalidable hors client).
This commit is contained in:
@@ -4,6 +4,7 @@ using Prospect.Unreal.Core.Objects;
|
||||
using Prospect.Unreal.Exceptions;
|
||||
using Prospect.Unreal.Net;
|
||||
using Prospect.Unreal.Net.Actors;
|
||||
using Prospect.Unreal.Net.Dtls;
|
||||
using Prospect.Unreal.Net.Channels;
|
||||
using Prospect.Unreal.Net.Packets.Bunch;
|
||||
using Prospect.Unreal.Net.Packets.Control;
|
||||
@@ -15,6 +16,9 @@ public abstract partial class UWorld : FNetworkNotify, IAsyncDisposable
|
||||
{
|
||||
private static readonly ILogger Logger = Log.ForContext<UWorld>();
|
||||
|
||||
// Table user_id -> PSK DTLS, chargée depuis l'env (rendu Vault, jamais commité).
|
||||
private static readonly Lazy<DtlsPskStore> DtlsPsks = new(() => DtlsPskStore.FromEnvironment());
|
||||
|
||||
private UGameInstance? _owningGameInstance;
|
||||
private AGameModeBase? _authorityGameMode;
|
||||
|
||||
@@ -307,8 +311,25 @@ public abstract partial class UWorld : FNetworkNotify, IAsyncDisposable
|
||||
//
|
||||
// For now: log and proceed to the challenge so the flow is visible
|
||||
// in logs; the client will close afterwards.
|
||||
Logger.Warning("Client requires DTLS-PSK encryption (EncryptionToken={Token}); server-side DTLS not implemented — connection will be dropped by client", encryptionToken);
|
||||
connection.SendChallengeControlMessage();
|
||||
// Chiffrement DTLS-PSK requis par le client. Si on connaît la
|
||||
// PSK de cette identité (user_id), on répond NMT_EncryptionAck et
|
||||
// on établit le DTLS côté serveur (BouncyCastle). Cf. DTLSHandlerComponent.
|
||||
var psks = DtlsPsks.Value;
|
||||
if (psks.Get(encryptionToken) != null && connection.DtlsComponent != null)
|
||||
{
|
||||
Logger.Information("DTLS-PSK: identité {Token} connue -> EncryptionAck + handshake", encryptionToken);
|
||||
NMT_EncryptionAck.Send(connection);
|
||||
connection.FlushNet();
|
||||
connection.DtlsComponent.BeginHandshake(
|
||||
psks, encryptionToken,
|
||||
rec => connection.LowLevelSend(rec, rec.Length * 8, new FOutPacketTraits()));
|
||||
connection.SendChallengeControlMessage();
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Warning("DTLS-PSK requis mais aucune PSK pour {Token} (renseigner PROSPECT_DTLS_PSKS) — le client fermera la connexion", encryptionToken);
|
||||
connection.SendChallengeControlMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user