- class QDtlsClientVerifier#
此类实现了服务器端 DTLS 曲奇生成和验证。 更多信息...
简介#
方法#
def
__init__()
def
dtlsError()
def
verifiedHello()
def
verifyClient()
注
本文档可能包含自动从C++翻译到Python的代码片段。我们始终欢迎对片段翻译的贡献。如果您发现翻译问题,也可以通过在https:/bugreports.qt.io/projects/PYSIDE上创建工单来通知我们
详细描述#
注意
本节包含自动从C++翻译到Python的代码片段,可能存在错误。
QDtlsClientVerifier
类实现了服务器端DTLS cookie的生成和验证。数据报安全协议容易受到各种拒绝服务攻击。根据RFC 6347,第4.2.1节,以下是两种更常见的攻击类型攻击者发送一系列握手初始化请求,导致服务器分配过多的资源,并可能执行昂贵的加密操作。
攻击者使用受害者的伪造源发送一系列握手初始化请求,使服务器充当放大器。通常,服务器会向受害者机器回复证书消息,这可能相当大,因此会向受害者机器发送大量数据报。
作为一种对抗这些攻击的对策,RFC 6347第4.2.1节提出了一种服务器可能部署的无状态cookie技术
针对初始的ClientHello消息,服务器发送包含cookie的HelloVerifyRequest。这个cookie是一个加密散列,使用客户端的地址、端口号和服务器私钥(这是一个字节的加密强伪随机序列)生成。
可到达的DTLS客户端应回复包含此cookie的新ClientHello消息。
当服务器收到包含cookie的ClientHello消息时,它将按照上述方式生成一个新的cookie。这个新cookie与ClientHello消息中找到的cookie进行比较。
如果cookie相同,则认为客户端是真实的,服务器可以继续使用TLS握手进程。
注
DTLS服务器不必要使用DTLS cookies。
QDtlsClientVerifier
设计为与QUdpSocket
配对工作,如下面的代码示例所示class DtlsServer(QObject): # public listen = bool(QHostAddress address, quint16 port) # ... # private def readyRead(): # ... serverSocket = QUdpSocket() verifier = QDtlsClientVerifier() # ... def listen(self, QHostAddress serverAddress, quint16 serverPort): if serverSocket.bind(serverAddress, serverPort): serverSocket.readyRead.connect(self.readyRead) return serverSocket.state() == QAbstractSocket.BoundState def readyRead(self): dgram = QByteArray(serverSocket.pendingDatagramSize(), Qt.Uninitialized) address = QHostAddress() 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. elif 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
没有任何限制。例如,可以有一个服务器,它有一个处于BoundState
状态的单个QUdpSocket
处理多个同时连接的 DTLS 客户端。这意味着
QDtlsClientVerifier
不会直接从套接字读取,相反它期望应用程序读取进入的数据报,提取发送者的地址和端口,然后将这些数据传递给verifyClient()
方法。要发送 HelloVerifyRequest 消息,verifyClient()
可以写入QUdpSocket
。注
QDtlsClientVerifier
不会获取QUdpSocket
对象的所有权。默认情况下,
QDtlsClientVerifier
从加密强伪随机数生成器获取其密钥。注
默认密钥在
QDtlsClientVerifier
和QDtls
类的所有对象中共享。由于这可能会带来安全风险,RFC 6347 建议频繁更改服务器的密钥。请参阅 RFC 6347 第 4.2.1 节中有关可能的实现方法。可以使用GeneratorParameters
类和setCookieGeneratorParameters()
方法设置 Cookie 生成器参数。def updateServerSecret(self): newSecret = QByteArray(generateCryptoStrongSecret()) if newSecret.size(): usedCookies.append(newSecret) verifier.setCookieGeneratorParameters({QCryptographicHash.Sha1, newSecret})
DTLS 服务器 示例说明了如何在一个服务器应用程序中使用
QDtlsClientVerifier
。另请参阅
QUdpSocket
与BoundState
结合QDtls
使用verifyClient()
,包括GeneratorParameters
、setCookieGeneratorParameters()
、cookieGeneratorParameters()
、cookieGeneratorParameters()
、QDtlsError
和dtlsError()
、dtlsErrorString()
构造
QDtlsClientVerifier
对象,parent
传递给 QObject 构造函数。- dtlsError()#
- 返回类型:
QDtlsError
返回最近发生的错误,或
NoError
。另请参阅
QDtlsError
dtlsErrorString()
- dtlsErrorString()#
- 返回类型:
str
返回最后错误的文本描述,或者空字符串。
另请参阅
- verifiedHello()#
- 返回类型:
便捷函数。返回最后成功验证的 ClientHello 消息,或者在未完成验证的情况下返回空的 QByteArray。
另请参阅
- verifyClient(socket, dgram, address, port)#
- 参数:
套接字 –
QUdpSocket
数据报 –
QByteArray
地址 –
QHostAddress
端口 – int
- 返回类型:
bool
注意
本节包含自动从C++翻译到Python的代码片段,可能存在错误。
socket
必须是一个有效的指针,dgram
必须是一个非空的报文,address
不能为空、广播或多播。port
是远程对等机的端口。此函数返回true
,如果dgram
包含有效cookie的ClientHello消息。如果没有找到匹配的cookie,verifyClient()会使用socket
发送HelloVerifyRequest消息,并返回false
。以下代码片段展示了服务器程序如何检查错误
if not verifier.verifyClient(socket, message, address, port): switch (verifyClient.dtlsError()) { elif ret == QDtlsError.NoError: # Not verified yet, but no errors found and we have to wait for the next # message from this client. return elif ret == QDtlsError.TlsInitializationError: # This error is fatal, nothing we can do about it. # Probably, quit the server after reporting the error. return elif ret == QDtlsError.UnderlyingSocketError: # There is some problem in QUdpSocket, handle it (see QUdpSocket::error()) return elif ret == QDtlsError.InvalidInputParameters: else: Q_UNREACHABLE()
另请参阅
isNull()
isBroadcast()
isMulticast()
setCookieGeneratorParameters()
cookieGeneratorParameters()