このページでは

QDtlsClientVerifier Class

このクラスは、サーバーサイドでのDTLSクッキーの生成と検証を実装しています。詳細...

ヘッダー: #include <QDtlsClientVerifier>
CMake: find_package(Qt6 REQUIRED COMPONENTS Network)
target_link_libraries(mytarget PRIVATE Qt6::Network)
qmake: QT += network
継承元: QObject

パブリック型

パブリック関数

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)

詳細な説明

QDtlsClientVerifier クラスは、サーバー側での DTLS クッキーの生成および検証を実装しています。データグラムセキュリティプロトコルは、さまざまなサービス拒否 (DoS) 攻撃に対して非常に脆弱です。RFC 6347 のセクション 4.2.1 によると、以下はより一般的な 2 種類の攻撃です。

  • 攻撃者が一連のハンドシェイク開始リクエストを送信し、サーバーに過剰なリソースを割り当てさせ、場合によっては負荷の高い暗号処理を実行させる。
  • 攻撃者が、被害者の送信元を偽装した一連のハンドシェイク開始リクエストを送信し、サーバーを増幅器として機能させます。通常、サーバーは被害者のマシンに対して証明書メッセージで応答しますが、このメッセージはかなりのサイズになる可能性があるため、被害者のマシンにデータグラムが殺到することになります。

これらの攻撃に対する対策として、RFC 6347のセクション4.2.1では、サーバーが導入可能なステートレス・クッキーの手法が提案されている:

  • 最初の ClientHello メッセージへの応答として、サーバーはクッキーを含む HelloVerifyRequest を送信します。このクッキーは暗号ハッシュであり、クライアントのアドレス、ポート番号、およびサーバーの秘密鍵(暗号的に強固な擬似ランダムなバイト列)を使用して生成されます。
  • 到達可能なDTLSクライアントは、このクッキーを含む新しいClientHelloメッセージで応答することが期待されます。
  • サーバーがクッキーを含む ClientHello メッセージを受信すると、前述の方法で新しいクッキーを生成します。この新しいクッキーは、ClientHello メッセージに含まれるクッキーと比較されます。
  • クッキーが一致する場合、クライアントは本物であるとみなされ、サーバーは TLS ハンドシェイク手順を続行できます。

注: DTLSサーバーは 、DTLS クッキーを使用する必要はありません。

QDtlsClientVerifierは、以下のコード抜粋に示すように、QUdpSocket と組み合わせて動作するように設計されています。

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 は、アプリケーションによる `QUdpSocket` の使用方法に何の制限も課しません。たとえば、QAbstractSocket::BoundState 状態の `QUdpSocket ` を 1 つだけ持つサーバーが、複数の DTLS クライアントを同時に処理することも可能です:

  • 新しいクライアントが真の DTLS 対応クライアントであるかどうかをテストする。
  • 検証済みのクライアントとの TLS ハンドシェイクを完了する(QDtls を参照)。
  • 接続されたクライアントから送信されるデータグラムの復号(QDtls を参照)。
  • 接続されたクライアントへ暗号化されたデータグラムを送信する(QDtls を参照)。

これは、QDtlsClientVerifier がソケットから直接読み取るのではなく、アプリケーションが着信データグラムを読み取り、送信者のアドレスとポートを抽出し、そのデータをverifyClient() に渡すことを想定していることを意味します。HelloVerifyRequest メッセージを送信するには、verifyClient() がQUdpSocket に書き込みを行います。

注:QDtlsClientVerifier は QUdpSocket オブジェクトの所有権を取得しません。

デフォルトでは、QDtlsClientVerifier は、暗号的に強力な擬似乱数生成器からシークレットを取得します。

注: デフォルトのシークレットは 、QDtlsClientVerifier クラスとQDtls クラスのすべてのオブジェクトで共有されます。これはセキュリティ上のリスクをもたらす可能性があるため、RFC 6347 では、サーバーのシークレットを頻繁に変更することを推奨しています。 サーバーの実装に関するヒントについては、RFC 6347のセクション4.2.1を参照してください。Cookie生成器のパラメータは、QDtlsClientVerifier::GeneratorParameters およびsetCookieGeneratorParameters()クラスを使用して設定できます:

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

DTLS サーバーの例では、サーバーアプリケーションで QDtlsClientVerifier を使用する方法を示しています。

QUdpSocket 、QAbstractSocket::BoundState 、QDtls 、verifyClient()、GeneratorParameters 、setCookieGeneratorParameters()、cookieGeneratorParameters()、QDtls::setCookieGeneratorParameters()、QDtls::cookieGeneratorParameters()、QCryptographicHash::Algorithm 、QDtlsError 、dtlsError()、およびdtlsErrorString()も参照してください。

メンバー関数のドキュメント

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

QDtlsClientVerifier オブジェクトを生成し、parent をQObject のコンストラクタに渡します。

[virtual noexcept] QDtlsClientVerifier::~QDtlsClientVerifier()

QDtlsClientVerifier オブジェクトを破棄します。

QDtlsClientVerifier::GeneratorParameters QDtlsClientVerifier::cookieGeneratorParameters() const

クッキーの生成に使用されている現在のシークレットおよびハッシュアルゴリズムを返します。デフォルトのハッシュアルゴリズムは、Qtがそれをサポートするように構成されている場合はQCryptographicHash::Sha256 、そうでない場合はQCryptographicHash::Sha1 です。デフォルトのシークレットは、バックエンド固有の暗号的に強固な擬似乱数生成器から取得されます。

QCryptographicHash::Algorithm 、QDtlsClientVerifier::GeneratorParameters 、およびsetCookieGeneratorParameters()も参照してください 。

QDtlsError QDtlsClientVerifier::dtlsError() const

最後に発生したエラー、またはQDtlsError::NoError を返します。

QDtlsError およびdtlsErrorString()も参照してください 。

QString QDtlsClientVerifier::dtlsErrorString() const

直近のエラーに関する説明文、または空の文字列を返します。

dtlsError()も参照してください 。

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

params からシークレットと暗号ハッシュアルゴリズムを設定します。このQDtlsClientVerifier は、これらを使用してクッキーを生成します。新しいシークレットのサイズが 0 の場合、この関数はfalse を返し、クッキー生成器のパラメータは変更されません。

注:シークレットは 、暗号学的に安全なバイト列である必要があります。

関連項目: QDtlsClientVerifier::GeneratorParameters 、cookieGeneratorParameters()、およびQCryptographicHash::Algorithm 。

QByteArray QDtlsClientVerifier::verifiedHello() const

便利関数。正常に検証された最新の ClientHello メッセージを返します。検証が完了していない場合は、空の `QByteArray ` を返します。

verifyClient()も参照してください 。

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

socket は有効なポインタでなければなりません。dgram は空ではないデータグラムでなければなりません。address はnull、ブロードキャスト、またはマルチキャストであってはなりません。port はリモート側のポートです。この関数は、dgram に有効なクッキーを含むClientHelloメッセージが含まれている場合、true を返します。一致するクッキーが見つからない場合、verifyClient()はsocket を使用してHelloVerifyRequestメッセージを送信し、false を返します。

以下のスニペットは、サーバーアプリケーションがエラーをチェックする方法を示しています:

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

QHostAddress::isNull()、QHostAddress::isBroadcast()、QHostAddress::isMulticast()、setCookieGeneratorParameters()、および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.