如何处理 QTcpServer 中的 TLS 握手超时?

Posted

技术标签:

【中文标题】如何处理 QTcpServer 中的 TLS 握手超时?【英文标题】:How to handle TLS handshake timeout in QTcpServer? 【发布时间】:2021-06-04 13:33:37 【问题描述】:

我正在尝试弄清楚如何在 QTcpServer 中的 TLS 连接中为握手过程创建超时。

我在覆盖的incomingConnection 函数中尝试了类似的操作:

QSslSocket * const tlsSocket = static_cast<QSslSocket*>(socket);
    connect(tlsSocket, &QSslSocket::encrypted, this, [this, tlsSocket]() addPendingConnection(tlsSocket); );
    tlsSocket->setLocalCertificate(m_serverCertificate);
    tlsSocket->setPrivateKey(m_serverPrivateKey);
    tlsSocket->setProtocol(QSsl::SecureProtocols);
    tlsSocket->startServerEncryption();

    // We will have a handshake timeout of 30 seconds
    QTimer::singleShot(30*1000, this, [this, tlsSocket]() 
        if(!tlsSocket->isEncrypted()) 
            // If no handshake initialized from the client close the connection
            delete tlsSocket;
        
    );

但这似乎不起作用,因为我没有直接调用 addPendingConnection 函数(它在 slot/lamdba 中被调用,这似乎打破了 pendingConnection 链。

有人知道如何在 Qt 中实现这个超时吗?目前的问题是客户端可以打开与服务器的连接,但它永远不会响应 TLS 握手,这会导致无用的打开连接(即永远不会关闭)。

【问题讨论】:

【参考方案1】:

我以这种方式结束了 TLS 握手超时:

// We will have a handshake timeout of 30 seconds (same as firefox today)
QTimer::singleShot(30*1000, this, [this]() 

    // we use dynamic_cast because this may be or not an encrypted socket
    QSslSocket * const tlsSocket = dynamic_cast<QSslSocket*>(m_socket);

    if(tlsSocket != nullptr && !tlsSocket->isEncrypted()) 
        qWarning() << "TLS Handshake timeout for connection from " <<
                      tlsSocket->peerAddress().toString() << ":" << tlsSocket->peerPort();
        tlsSocket->close();
    
);

此代码可以添加到对您的项目更实用的任何地方。我将它添加到我们拥有的会话类中(它拥有创建的套接字),这个类是在 newConnection 插槽的末尾创建的。我已经测试过了,效果很好。

【讨论】:

以上是关于如何处理 QTcpServer 中的 TLS 握手超时?的主要内容,如果未能解决你的问题,请参考以下文章

未设置 set_tls_init_handler 时 websocketpp 如何处理连接?

带有 Smack 4.1.8 客户端库的 Apache Vysper - 如何处理 TLS 证书?

如何处理mysql数据库并发更新问题

多时域设计中,如何处理信号跨时域

WebSocket 服务器如何处理多个传入的连接请求?

如何处理c#中的错误代码