Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QTcpServer & DoS Attacks

QTcpServer & DoS Attacks

Scheduled Pinned Locked Moved General and Desktop
4 Posts 2 Posters 1.5k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P Offline
    P Offline
    Psychomax
    wrote on last edited by
    #1

    Hello together,

    i have a small problem and i really have no idea how to manage that. I have a async single threaded REST Http server based on QTcpServer with QSslSockets. Everything is based on Signal & Slot, so nothing like waitFor... is implemented. In the same Thread i have a REST resources which does stuff. For example changing a value every 500ms. Data size of each REST call is pretty low. Some JSON objects. Maybe 1kB up to 50 kB, round about that.

    So my problem is now, if there is a funny user who flood me with message (Just hold enter in the REST Browser) i can't hold the 500ms - i see that on the debug output. Is there any way to prevent on such an issue?

    Hope u guys can help me.

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

      First thing you can do is move the "resources" work in its own thread. Then you can also implement throttling so if a user does too many queries you stop responding to him

      Hope it helps

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      0
      • P Offline
        P Offline
        Psychomax
        wrote on last edited by
        #3

        What I've done until now is, that i put the SSL socket connection in a seperate thread and wait with the blocking methods until a valid connection is established. After that i give the established socket back to the main thread. So my main thread doesn't have to handle unestablished socket connects. This is in my opinion a hack but it give a bit of optimization.

        I although tried to use instead of the socket thread option the pendingConnection option of the QTcpSocket. See code below. The problem on this approach is, that in future i always get: "Start server encryption" - "Remove unestablished connection". And this in a loop. So i do not get a valid connection anymore. "Netstate" tells me, that there are a lot of CLOSE_WAIT socket connections. But i pretty sure i closed everything. If i do not call handleConnection(...) in sslSocketDisconnected the pendingConnection blocks any incoming connection. The QTcpSocket does not remove Unconnected Sockets out of its queue. So i have to call "nextPendingConnection". Independent if the connection is established or not.

        To the thread approach:
        I thought about that. But i can't make a decide if there is a real advantage. Because lets stay on the example above. There is a RestTimerResource with does something every 500ms. Now there are a lot of GETs on this resource. Isn't this one thread. Or do you mean to put the read/write operations (byte parsing) in one Thread and if there is a message receive, this will be handled by the main thread. So searching the right Resource, getting the information and send this information back in a seperat thread again?!

        One side info. When i run that on my PC i have less problems. If i run that on my embedded system or with valgrind on the PC then i have that problem.

        I'm now working a whole week on that problem with a lots of hours.... Very frustrating...

        @

        /****************************************************************************

        • Global
          */
          using namespace Core::Http::Internal;

        /****************************************************************************

        • Public
          */
          BHttpsServer::BHttpsServer(QObject *parent) :
          BHttpServer(parent)
          {
          #if (BTOOL_ARCHITECTURE == arm || BTOOL_ARCHITECTURE == linux-arm)
          QFile sslCertificate(":/certs/certificate.crt");
          QFile sslPrivateKey(":/certs/private.key");
          #else
          QFile sslCertificate("/opt/b/certs/certificate.crt");
          QFile sslPrivateKey("/opt/b/certs/private.key");
          #endif

          if(!sslCertificate.open(QIODevice::ReadOnly)) {
          bCritical() << "No certificate found";
          Q_ASSERT(false);
          return;
          }

          if(!sslPrivateKey.open(QIODevice::ReadOnly)) {
          bCritical() << "No private key found";
          Q_ASSERT(false);
          return;
          }

          QSslCertificate cert(&sslCertificate);
          QSslKey key(&sslPrivateKey, QSsl::Rsa);

          m_sslConfiguration = QSslConfiguration::defaultConfiguration();
          m_sslConfiguration.setLocalCertificate(cert);
          m_sslConfiguration.setPrivateKey(key);

          setMaxPendingConnections(1);
          }

        BHttpsServer::~BHttpsServer()
        {}

        void BHttpsServer::incomingConnection(qintptr socketDescriptor)
        {
        QSslSocket *sslSocket = new QSslSocket;
        if (sslSocket->setSocketDescriptor(socketDescriptor)) {
        QString peer = Core::Http::peerToString(*sslSocket);
        bDebug() << "Start SSL server encryption with " << peer;

            connect(sslSocket, SIGNAL(encrypted()),
                    this, SLOT(sslConnectionReady()));
            connect(sslSocket, SIGNAL(sslErrors(QList<QSslError>)),
                    this, SLOT(sslErrors(QList<QSslError>)));
            connect(sslSocket, SIGNAL(disconnected()),
                    this, SLOT(sslSocketDisconnected()));
        
            sslSocket->setSslConfiguration(m_sslConfiguration);
            sslSocket->setPeerVerifyMode(QSslSocket::VerifyNone);
        
            addPendingConnection(sslSocket);
            sslSocket->startServerEncryption();
        } else {
            bWarning() << "Unable to create SSL socket connection";
            delete sslSocket;
        }
        

        }

        void BHttpsServer::sslConnectionReady()
        {
        QSslSocket sslSocket = static_cast<QSslSocket>(QObject::sender());
        disconnect(sslSocket, SIGNAL(disconnected()),
        this, SLOT(sslSocketDisconnected()));
        QString peer = Core::Http::peerToString(*sslSocket);
        bDebug() << "Server encryption established with " << peer;

        handleSslConnection();
        

        }

        void BHttpsServer::sslErrors(QList<QSslError> errors)
        {
        bWarning() << "SSL socket errors detected: ";
        foreach(QSslError err, errors) {
        QSslError::SslError errorCode = err.error();
        QString sslErrorString = err.errorString();
        bWarning() << "SSL error #" << errorCode << ": "
        << sslErrorString;
        }
        }

        void BHttpsServer::sslSocketDisconnected()
        {
        QSslSocket sslSocket = static_cast<QSslSocket>(QObject::sender());
        QString peer = Core::Http::peerToString(*sslSocket);
        bDebug() << "Remove unestablished SSL socket from" << peer;

        //Workaround: QTcpServer does not remove unestabished connections by it self.
        m_unestablishedSockets.append(sslSocket);
        handleSslConnection();
        

        }

        void BHttpsServer::handleSslConnection()
        {
        while(hasPendingConnections()) {
        QSslSocket client = static_cast<QSslSocket>(nextPendingConnection());
        if(m_unestablishedSockets.contains(client)) {
        m_unestablishedSockets.removeAll(client);
        client->close();
        } else {
        BHttpMessageInfo *msgInfo = new BHttpMessageInfo(qMakePair(client, true));
        if(!m_httpHandler->receive(msgInfo, true)) {
        QString peer = Core::Http::peerToString(*client);
        bWarning() << "Failed to read data from " << peer;
        }
        }
        }
        }
        @

        1 Reply Last reply
        0
        • P Offline
          P Offline
          Psychomax
          wrote on last edited by
          #4

          maxPendingConnection is set to 1 because then i do not have to wait to long for that problem... :)

          1 Reply Last reply
          0

          • Login

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved