QDtlsClientVerifier Class

Diese Klasse implementiert die serverseitige Erzeugung und Überprüfung von DTLS-Cookies. Mehr...

Kopfzeile: #include <QDtlsClientVerifier>
CMake: find_package(Qt6 REQUIRED COMPONENTS Network)
target_link_libraries(mytarget PRIVATE Qt6::Network)
qmake: QT += network
Vererbt: QObject

Öffentliche Typen

Öffentliche Funktionen

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)

Detaillierte Beschreibung

Die Klasse QDtlsClientVerifier implementiert die serverseitige Erzeugung und Überprüfung von DTLS-Cookies. Datagramm-Sicherheitsprotokolle sind sehr anfällig für eine Vielzahl von Denial-of-Service-Angriffen. Nach RFC 6347, Abschnitt 4.2.1, sind dies zwei der häufigsten Angriffsarten:

  • Ein Angreifer sendet eine Reihe von Handshake-Initiierungsanfragen, die einen Server dazu veranlassen, übermäßige Ressourcen zuzuweisen und möglicherweise teure kryptografische Operationen durchzuführen.
  • Ein Angreifer sendet eine Reihe von Handshake-Initiierungsanfragen mit einer gefälschten Quelle des Opfers, so dass der Server als Verstärker fungiert. Normalerweise würde der Server dem Opferrechner mit einer Zertifikatsnachricht antworten, die recht groß sein kann, so dass der Opferrechner mit Datagrammen überflutet wird.

Als Gegenmaßnahme zu diesen Angriffen wird in RFC 6347, Abschnitt 4.2.1 eine zustandslose Cookie-Technik vorgeschlagen, die ein Server einsetzen kann:

  • Als Antwort auf die erste ClientHello-Nachricht sendet der Server eine HelloVerifyRequest, die ein Cookie enthält. Dieser Cookie ist ein kryptographischer Hash und wird unter Verwendung der Adresse des Clients, der Portnummer und des Geheimnisses des Servers (einer kryptographisch starken Pseudo-Zufallsfolge von Bytes) erzeugt.
  • Von einem erreichbaren DTLS-Client wird erwartet, dass er mit einer neuen ClientHello-Nachricht antwortet, die dieses Cookie enthält.
  • Wenn der Server die ClientHello-Nachricht mit einem Cookie empfängt, erzeugt er ein neues Cookie wie oben beschrieben. Dieses neue Cookie wird mit dem in der ClientHello-Nachricht gefundenen Cookie verglichen.
  • Wenn die Cookies gleich sind, wird der Client als echt angesehen, und der Server kann mit dem TLS-Handshake-Verfahren fortfahren.

Anmerkung: Ein DTLS-Server ist nicht verpflichtet, DTLS-Cookies zu verwenden.

QDtlsClientVerifier wurde entwickelt, um zusammen mit QUdpSocket zu arbeiten, wie im folgenden Code-Auszug gezeigt wird:

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 erlegt der Anwendung keine Beschränkungen bei der Verwendung von QUdpSocket auf. Es ist zum Beispiel möglich, einen Server mit einem einzigen QUdpSocket im Zustand QAbstractSocket::BoundState zu haben, der mehrere DTLS-Clients gleichzeitig bedient:

  • Testen, ob neue Clients echte DTLS-fähige Clients sind.
  • Abschluss von TLS-Handshakes mit den verifizierten Clients (siehe QDtls).
  • Entschlüsselung von Datagrammen, die von den verbundenen Clients kommen (siehe QDtls).
  • Senden von verschlüsselten Datagrammen an die angeschlossenen Clients (siehe QDtls).

Dies bedeutet, dass QDtlsClientVerifier nicht direkt von einem Socket liest, sondern erwartet, dass die Anwendung ein eingehendes Datagramm liest, die Adresse und den Port des Absenders extrahiert und diese Daten dann an verifyClient() weitergibt. Um eine HelloVerifyRequest-Nachricht zu senden, kann verifyClient() in den QUdpSocket schreiben.

Hinweis: QDtlsClientVerifier übernimmt nicht das Eigentum an dem QUdpSocket Objekt.

Standardmäßig bezieht QDtlsClientVerifier sein Geheimnis von einem kryptographisch starken Pseudozufallszahlengenerator.

Hinweis: Das Standardgeheimnis wird von allen Objekten der Klassen QDtlsClientVerifier und QDtls gemeinsam genutzt. Da dies Sicherheitsrisiken mit sich bringen kann, empfiehlt RFC 6347, das Geheimnis des Servers häufig zu ändern. Hinweise zu möglichen Server-Implementierungen finden Sie in RFC 6347, Abschnitt 4.2.1. Die Parameter des Cookie-Generators können mit der Klasse QDtlsClientVerifier::GeneratorParameters und setCookieGeneratorParameters() gesetzt werden:

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

Das DTLS-Server-Beispiel veranschaulicht, wie QDtlsClientVerifier in einer Server-Anwendung verwendet werden kann.

Siehe auch QUdpSocket, QAbstractSocket::BoundState, QDtls, verifyClient(), GeneratorParameters, setCookieGeneratorParameters(), cookieGeneratorParameters(), QDtls::setCookieGeneratorParameters(), QDtls::cookieGeneratorParameters(), QCryptographicHash::Algorithm, QDtlsError, dtlsError() und dtlsErrorString().

Dokumentation der Mitgliedsfunktionen

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

Konstruiert ein QDtlsClientVerifier-Objekt, parent wird an den Konstruktor von QObject übergeben.

[virtual noexcept] QDtlsClientVerifier::~QDtlsClientVerifier()

Zerstört das Objekt QDtlsClientVerifier.

QDtlsClientVerifier::GeneratorParameters QDtlsClientVerifier::cookieGeneratorParameters() const

Gibt das aktuelle Geheimnis und den Hash-Algorithmus zurück, der zur Erzeugung von Cookies verwendet wird. Der Standard-Hash-Algorithmus ist QCryptographicHash::Sha256, wenn Qt so konfiguriert wurde, dass es ihn unterstützt, andernfalls QCryptographicHash::Sha1. Das Standardgeheimnis wird aus dem Backend-spezifischen kryptographisch starken Pseudozufallszahlengenerator gewonnen.

Siehe auch QCryptographicHash::Algorithm, QDtlsClientVerifier::GeneratorParameters, und setCookieGeneratorParameters().

QDtlsError QDtlsClientVerifier::dtlsError() const

Gibt den zuletzt aufgetretenen Fehler oder QDtlsError::NoError zurück.

Siehe auch QDtlsError und dtlsErrorString().

QString QDtlsClientVerifier::dtlsErrorString() const

Gibt eine textuelle Beschreibung des letzten Fehlers oder eine leere Zeichenkette zurück.

Siehe auch dtlsError().

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

Legt das Geheimnis und den kryptografischen Hash-Algorithmus von params fest. QDtlsClientVerifier verwendet diese zur Erzeugung von Cookies. Wenn das neue Geheimnis die Größe Null hat, gibt diese Funktion false zurück und ändert die Parameter des Cookie-Generators nicht.

Hinweis: Das Geheimnis sollte eine kryptografisch sichere Folge von Bytes sein.

Siehe auch QDtlsClientVerifier::GeneratorParameters, cookieGeneratorParameters(), und QCryptographicHash::Algorithm.

QByteArray QDtlsClientVerifier::verifiedHello() const

Bequemlichkeitsfunktion. Gibt die letzte ClientHello-Nachricht zurück, die erfolgreich verifiziert wurde, oder ein leeres QByteArray, wenn keine Verifizierung stattgefunden hat.

Siehe auch verifyClient().

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

socket muss ein gültiger Zeiger sein, dgram muss ein nicht leeres Datagramm sein, address darf nicht null, broadcast oder multicast sein. port ist der Port der Gegenstelle. Diese Funktion gibt true zurück, wenn dgram eine ClientHello-Nachricht mit einem gültigen Cookie enthält. Wird kein passendes Cookie gefunden, sendet verifyClient() eine HelloVerifyRequest-Nachricht mit socket und gibt false zurück.

Das folgende Snippet zeigt, wie eine Serveranwendung auf Fehler prüfen kann:

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();
    }
}

Siehe auch QHostAddress::isNull(), QHostAddress::isBroadcast(), QHostAddress::isMulticast(), setCookieGeneratorParameters(), und cookieGeneratorParameters().

© 2025 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.