QDtlsClientVerifier Class
이 클래스는 서버 측 DTLS 쿠키 생성 및 확인을 구현합니다. 더 보기...
Header: | #include <QDtlsClientVerifier> |
CMake: | find_package(Qt6 REQUIRED COMPONENTS Network) target_link_libraries(mytarget PRIVATE Qt6::Network) |
qmake: | QT += network |
상속합니다: | QObject |
- 상속된 멤버를 포함한 모든 멤버 목록
- QDtlsClientVerifier는 네트워크 프로그래밍 API의 일부입니다.
공용 유형
struct | GeneratorParameters |
공용 함수
QDtlsClientVerifier(QObject *parent = nullptr) | |
virtual | ~QDtlsClientVerifier() |
QDtlsClientVerifier::GeneratorParameters | cookieGeneratorParameters() const |
QDtlsError | dtlsError() const |
QString | dtlsErrorString() const |
bool | setCookieGeneratorParameters(const QDtlsClientVerifier::GeneratorParameters ¶ms) |
QByteArray | verifiedHello() const |
bool | verifyClient(QUdpSocket *socket, const QByteArray &dgram, const QHostAddress &address, quint16 port) |
상세 설명
QDtlsClientVerifier 클래스는 서버 측 DTLS 쿠키 생성 및 검증을 구현합니다. 데이터그램 보안 프로토콜은 다양한 서비스 거부 공격에 매우 취약합니다. RFC 6347, 섹션 4.2.1에 따르면 다음은 가장 일반적인 공격 유형 중 두 가지입니다:
- 공격자가 일련의 핸드셰이크 시작 요청을 전송하여 서버가 과도한 리소스를 할당하고 잠재적으로 값비싼 암호화 작업을 수행하게 하는 경우.
- 공격자가 피해자의 소스를 위조한 일련의 핸드셰이크 시작 요청을 전송하여 서버가 증폭기 역할을 하도록 합니다. 일반적으로 서버는 상당히 큰 용량의 인증서 메시지로 피해 시스템에 응답하여 피해 시스템에 데이터그램을 넘치게 합니다.
이러한 공격에 대한 대응책으로 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 XML이 이를 지원하도록 구성된 경우 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 ¶ms)
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 은 널, 브로드캐스트 또는 멀티캐스트일 수 없습니다. 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()도 참조하세요 .
© 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.