이 페이지에서

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절에 따르면 , 다음은 가장 흔한 두 가지 공격 유형입니다.

  • 공격자가 일련의 핸드셰이크 시작 요청을 전송하여 서버가 과도한 리소스를 할당하게 하고, 잠재적으로 비용이 많이 드는 암호화 작업을 수행하도록 만듭니다.
  • 공격자는 피해자의 소스를 위조하여 일련의 핸드셰이크 시작 요청을 전송함으로써, 서버가 증폭기 역할을 하도록 만듭니다. 일반적으로 서버는 피해자 시스템에 인증서(Certificate) 메시지로 응답하게 되는데, 이 메시지는 크기가 상당히 클 수 있어 피해자 시스템에 다타그램을 과도하게 쏟아붓게 됩니다.

이러한 공격에 대한 대응책으로, 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 를 가진 서버가 여러 DTLS 클라이언트를 동시에 처리할 수 있습니다:

  • 새로운 클라이언트가 실제 DTLS 지원 클라이언트인지 테스트합니다.
  • 검증된 클라이언트와 TLS 핸드셰이크를 완료합니다( QDtls 참조).
  • 연결된 클라이언트로부터 수신된 데이터그램을 복호화합니다( QDtls 참조).
  • 연결된 클라이언트에게 암호화된 데이터그램을 전송합니다( QDtls 참조).

이는 QDtlsClientVerifier가 소켓에서 직접 읽지 않고, 대신 애플리케이션이 수신 데이터그램을 읽고 발신자의 주소와 포트를 추출한 다음 이 데이터를 verifyClient()에 전달할 것을 기대함을 의미합니다. HelloVerifyRequest 메시지를 전송하려면, verifyClient()가 QUdpSocket 에 쓰기를 수행할 수 있습니다.

참고: QDtlsClientVerifier는 QUdpSocket 객체에 대한 소유권을 갖지 않습니다.

기본적으로 QDtlsClientVerifier는 암호학적으로 강력한 의사 난수 생성기에서 비밀 키를 얻습니다.

참고: 기본비밀키는 QDtlsClientVerifier 및 QDtls 클래스의 모든 객체가 공유합니다. 이는 보안 위험을 초래할 수 있으므로, RFC 6347에서는 서버의 비밀키를 자주 변경할 것을 권장합니다. 가능한 서버 구현에 대한 지침은 RFC 6347의 4.2.1절을 참조하십시오. 쿠키 생성기 매개변수는 ` 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 must be a valid pointer, dgram must be a non-empty datagram, address cannot be null, broadcast, or multicast. port is the remote peer’s 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.