Sur cette page

QDtlsClientVerifier Class

Cette classe implémente la génération et la vérification des cookies DTLS côté serveur. Plus d'informations...

En-tête : #include <QDtlsClientVerifier>
CMake : find_package(Qt6 REQUIRED COMPONENTS Network)
target_link_libraries(mytarget PRIVATE Qt6::Network)
qmake : QT += network
Héritages : QObject

Types publics

Fonctions publiques

QDtlsClientVerifier(QObject *parent = nullptr)
virtual ~QDtlsClientVerifier()
QDtlsClientVerifier::GeneratorParameters cookieGeneratorParameters() const
QDtlsError dtlsError() const
QString dtlsErrorString() const
bool setCookieGeneratorParameters(const QDtlsClientVerifier::GeneratorParameters &params)
QByteArray verifiedHello() const
bool verifyClient(QUdpSocket *socket, const QByteArray &dgram, const QHostAddress &address, quint16 port)

Description détaillée

La classe QDtlsClientVerifier implémente la génération et la vérification des cookies DTLS côté serveur. Les protocoles de sécurité des datagrammes sont très sensibles à une variété d'attaques par déni de service. Selon la RFC 6347, section 4.2.1, voici deux des types d'attaques les plus courants :

  • Un attaquant transmet une série de demandes d'initiation de la poignée de main, ce qui amène un serveur à allouer des ressources excessives et à effectuer des opérations cryptographiques potentiellement coûteuses.
  • Un attaquant transmet une série de demandes d'initiation de la poignée de main avec une source falsifiée de la victime, obligeant le serveur à agir comme un amplificateur. Normalement, le serveur répondrait à la machine victime par un message de certificat, qui peut être très volumineux, inondant ainsi la machine victime de datagrammes.

Pour contrer ces attaques, la section 4.2.1 du RFC 6347 propose une technique de cookie sans état qu'un serveur peut déployer :

  • En réponse au message initial ClientHello, le serveur envoie une requête HelloVerifyRequest, qui contient un cookie. Ce cookie est un hachage cryptographique généré à partir de l'adresse du client, du numéro de port et du secret du serveur (qui est une séquence pseudo-aléatoire d'octets forte sur le plan cryptographique).
  • Un client DTLS joignable est censé répondre par un nouveau message ClientHello contenant ce cookie.
  • Lorsque le serveur reçoit le message ClientHello avec un cookie, il génère un nouveau cookie comme décrit ci-dessus. Ce nouveau cookie est comparé à celui trouvé dans le message ClientHello.
  • Si les cookies sont égaux, le client est considéré comme réel et le serveur peut poursuivre la procédure de poignée de main TLS.

Remarque : un serveur DTLS n'est pas tenu d'utiliser les cookies DTLS.

QDtlsClientVerifier est conçu pour fonctionner en paire avec QUdpSocket, comme le montre l'extrait de code suivant :

class DtlsServer : public QObject
{
public:
    bool listen(const QHostAddress &address, quint16 port);
    // ...

private:
    void readyRead();
    // ...

    QUdpSocket serverSocket;
    QDtlsClientVerifier verifier;
    // ...
};

bool DtlsServer::listen(const QHostAddress &serverAddress, quint16 serverPort)
{
    if (serverSocket.bind(serverAddress, serverPort))
        connect(&serverSocket, &QUdpSocket::readyRead, this, &DtlsServer::readyRead);
    return serverSocket.state() == QAbstractSocket::BoundState;
}

void DtlsServer::readyRead()
{
    QByteArray dgram(serverSocket.pendingDatagramSize(), Qt::Uninitialized);
    QHostAddress address;
    quint16 port = {};
    serverSocket.readDatagram(dgram.data(), dgram.size(), &address, &port);
    if (verifiedClients.contains({address, port}) {
        // This client was verified previously, we either continue the
        // handshake or decrypt the incoming message.
    } else if (verifier.verifyClient(&serverSocket, dgram, address, port)) {
        // Apparently we have a real DTLS client who wants to send us
        // encrypted datagrams. Remember this client as verified
        // and proceed with a handshake.
    } else {
        // No matching cookie was found in the incoming datagram,
        // verifyClient() has sent a ClientVerify message.
        // We'll hear from the client again soon, if they're real.
    }
}

QDtlsClientVerifier n'impose aucune restriction sur la manière dont l'application utilise QUdpSocket. Par exemple, il est possible d'avoir un serveur avec un seul QUdpSocket dans l'état QAbstractSocket::BoundState, traitant plusieurs clients DTLS simultanément :

  • Tester si les nouveaux clients sont de vrais clients DTLS.
  • Terminer les échanges TLS avec les clients vérifiés (voir QDtls).
  • Décryptage des datagrammes provenant des clients connectés (voir QDtls).
  • Envoi de datagrammes chiffrés aux clients connectés (voir QDtls).

Cela implique que QDtlsClientVerifier ne lit pas directement à partir d'une socket, mais attend de l'application qu'elle lise un datagramme entrant, qu'elle en extraie l'adresse et le port de l'expéditeur, puis qu'elle transmette ces données à verifyClient(). Pour envoyer un message HelloVerifyRequest, verifyClient() peut écrire sur la socket QUdpSocket.

Remarque : QDtlsClientVerifier n'est pas propriétaire de l'objet QUdpSocket.

Par défaut, QDtlsClientVerifier obtient son secret à partir d'un générateur de nombres pseudo-aléatoires cryptographiquement fort.

Remarque : le secret par défaut est partagé par tous les objets des classes QDtlsClientVerifier et QDtls. Comme cela peut entraîner des risques pour la sécurité, la RFC 6347 recommande de modifier fréquemment le secret du serveur. Voir RFC 6347, section 4.2.1 pour des indications sur les implémentations possibles du serveur. Les paramètres du générateur de cookies peuvent être définis à l'aide des classes QDtlsClientVerifier::GeneratorParameters et setCookieGeneratorParameters() :

void DtlsServer::updateServerSecret()
{
    const QByteArray newSecret(generateCryptoStrongSecret());
    if (newSecret.size()) {
        usedCookies.append(newSecret);
        verifier.setCookieGeneratorParameters({QCryptographicHash::Sha1, newSecret});
    }
}

L'exemple du serveur DTLS illustre comment utiliser QDtlsClientVerifier dans une application serveur.

Voir aussi QUdpSocket, QAbstractSocket::BoundState, QDtls, verifyClient(), GeneratorParameters, setCookieGeneratorParameters(), cookieGeneratorParameters(), QDtls::setCookieGeneratorParameters(), QDtls::cookieGeneratorParameters(), QCryptographicHash::Algorithm, QDtlsError, dtlsError(), et dtlsErrorString().

Documentation des fonctions membres

[explicit] QDtlsClientVerifier::QDtlsClientVerifier(QObject *parent = nullptr)

Construit un objet QDtlsClientVerifier, parent est transmis au constructeur de QObject.

[virtual noexcept] QDtlsClientVerifier::~QDtlsClientVerifier()

Détruit l'objet QDtlsClientVerifier.

QDtlsClientVerifier::GeneratorParameters QDtlsClientVerifier::cookieGeneratorParameters() const

Renvoie le secret actuel et l'algorithme de hachage utilisé pour générer les cookies. L'algorithme de hachage par défaut est QCryptographicHash::Sha256 si Qt XML a été configuré pour le supporter, QCryptographicHash::Sha1 sinon. Le secret par défaut est obtenu à partir du générateur de nombres pseudo-aléatoires cryptographiquement fort spécifique au backend.

Voir aussi QCryptographicHash::Algorithm, QDtlsClientVerifier::GeneratorParameters, et setCookieGeneratorParameters().

QDtlsError QDtlsClientVerifier::dtlsError() const

Renvoie la dernière erreur survenue ou QDtlsError::NoError.

Voir aussi QDtlsError et dtlsErrorString().

QString QDtlsClientVerifier::dtlsErrorString() const

Renvoie une description textuelle de la dernière erreur, ou une chaîne vide.

Voir aussi dtlsError().

bool QDtlsClientVerifier::setCookieGeneratorParameters(const QDtlsClientVerifier::GeneratorParameters &params)

Définit le secret et l'algorithme de hachage cryptographique à partir de params. QDtlsClientVerifier les utilisera pour générer des cookies. Si le nouveau secret a une taille nulle, cette fonction renvoie false et ne modifie pas les paramètres du générateur de cookies.

Remarque : le secret est censé être une séquence d'octets cryptographiquement sûre.

Voir aussi QDtlsClientVerifier::GeneratorParameters, cookieGeneratorParameters(), et QCryptographicHash::Algorithm.

QByteArray QDtlsClientVerifier::verifiedHello() const

Fonction de commodité. Renvoie le dernier message ClientHello qui a été vérifié avec succès, ou un QByteArray vide si aucune vérification n'a été effectuée.

Voir aussi verifyClient().

bool QDtlsClientVerifier::verifyClient(QUdpSocket *socket, const QByteArray &dgram, const QHostAddress &address, quint16 port)

socket doit être un pointeur valide, dgram doit être un datagramme non vide, address ne peut pas être null, broadcast ou multicast. port est le port du pair distant. Cette fonction renvoie true si dgram contient un message ClientHello avec un cookie valide. Si aucun cookie correspondant n'est trouvé, verifyClient() envoie un message HelloVerifyRequest à l'aide de socket et renvoie false.

L'extrait suivant montre comment une application serveur peut vérifier les erreurs :

if (!verifier.verifyClient(&socket, message, address, port)) {
    switch (verifyClient.dtlsError()) {
    case QDtlsError::NoError:
        // Not verified yet, but no errors found and we have to wait for the next
        // message from this client.
        return;
    case QDtlsError::TlsInitializationError:
        // This error is fatal, nothing we can do about it.
        // Probably, quit the server after reporting the error.
        return;
    case QDtlsError::UnderlyingSocketError:
        // There is some problem in QUdpSocket, handle it (see QUdpSocket::error())
        return;
    case QDtlsError::InvalidInputParameters:
    default:
        Q_UNREACHABLE();
    }
}

Voir aussi QHostAddress::isNull(), QHostAddress::isBroadcast(), QHostAddress::isMulticast(), setCookieGeneratorParameters() et cookieGeneratorParameters().

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.