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 クッキー生成と検証を実装します。データグラム・セキュリティ・プロトコルは、さまざまなサービス拒否攻撃の影響を非常に受けやすい。RFC 6347の4.2.1節によると、より一般的な攻撃のタイプは以下の2つである:

  • 攻撃者が一連のハンドシェイク開始リクエストを送信し、サーバーに過剰な リソースを割り当てさせ、高価な暗号処理を実行させる可能性がある。
  • 攻撃者が被害者のソースを偽造して一連のハンドシェイク開始リクエストを送信し、サーバーを増幅器として動作させる。通常、サーバーは被害者のマシンにCertificateメッセージを返信するが、このメッセージは非常に大きくなるため、被害者のマシンはデータグラムであふれかえる。

このような攻撃への対策として、RFC6347の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 を持つサーバーが、複数のDTLSクライアントを同時に処理することは可能である:

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

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

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

デフォルトでは、QDtlsClientVerifierは暗号的に強力な擬似乱数生成器から秘密を取得する。

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

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 オブジェクトを構築します。parentQObject のコンストラクタに渡されます。

[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::GeneratorParameterscookieGeneratorParameters()、QCryptographicHash::Algorithmも参照してください

QByteArray QDtlsClientVerifier::verifiedHello() const

便利な関数。検証に成功した最後の ClientHello メッセージか、 検証が完了していない場合は空のQByteArray を返します。

verifyClient()も参照のこと

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

socket は有効なポインタでなければならない。 は空でないデータグラムでなければならない。 はNULL、ブロードキャスト、またはマルチキャストであってはならない。 はリモートピアのポートである。この関数は、 に有効なクッキーを持つ ClientHelloメッセージが含まれていれば、 を返す。一致するクッキーが見つからない場合、 verifyClient() は を使用して HelloVerifyRequest メッセージを送信し、 を返す。dgram address port dgram true socket 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()も参照してください

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