diff -ru dnsdist-2.0.3.orig/dnsdist-concurrent-connections.cc dnsdist-2.0.3.CVE-2026-33254/dnsdist-concurrent-connections.cc
--- dnsdist-2.0.3.orig/dnsdist-concurrent-connections.cc	2026-03-12 16:00:00.000000000 +0100
+++ dnsdist-2.0.3.CVE-2026-33254/dnsdist-concurrent-connections.cc	2026-04-03 15:50:27.196759683 +0200
@@ -164,7 +164,7 @@
   return activity.front();
 }
 
-IncomingConcurrentTCPConnectionsManager::NewConnectionResult IncomingConcurrentTCPConnectionsManager::accountNewTCPConnection(const ComboAddress& from, bool isTLS)
+IncomingConcurrentTCPConnectionsManager::NewConnectionResult IncomingConcurrentTCPConnectionsManager::accountNewTCPConnection(const ComboAddress& from, bool isTLS, bool isQUIC)
 {
   const auto& immutable = dnsdist::configuration::getImmutableConfiguration();
   const auto maxConnsPerClient = immutable.d_maxTCPConnectionsPerClient;
@@ -185,18 +185,22 @@
     ++activity.tcpConnections;
   };
 
-  auto checkConnectionAllowed = [now, from, maxConnsPerClient, threshold, tcpRate, tlsNewRate, tlsResumedRate, interval, isTLS, &immutable](const ClientEntry& entry) {
+  auto getProtocol = [isQUIC]() -> std::string {
+    return isQUIC ? "QUIC" : "TCP";
+  };
+
+  auto checkConnectionAllowed = [now, from, maxConnsPerClient, threshold, tcpRate, tlsNewRate, tlsResumedRate, interval, isTLS, &immutable, &getProtocol](const ClientEntry& entry) {
     if (entry.d_bannedUntil != 0 && entry.d_bannedUntil >= now) {
-      vinfolog("Refusing TCP connection from %s: banned", from.toStringWithPort());
+      vinfolog("Refusing %s connection from %s: banned", getProtocol(), from.toStringWithPort());
       return NewConnectionResult::Denied;
     }
     if (maxConnsPerClient > 0 && entry.d_concurrentConnections >= maxConnsPerClient) {
-      vinfolog("Refusing TCP connection from %s: too many connections", from.toStringWithPort());
+      vinfolog("Refusing %s connection from %s: too many connections", getProtocol(), from.toStringWithPort());
       return NewConnectionResult::Denied;
     }
     if (!checkTCPConnectionsRate(entry.d_activity, now, tcpRate, tlsNewRate, tlsResumedRate, interval, isTLS)) {
       entry.d_bannedUntil = now + immutable.d_tcpBanDurationForExceedingTCPTLSRate;
-      vinfolog("Banning TCP connections from %s for %d seconds: too many new TCP/TLS connections per second", from.toStringWithPort(), immutable.d_tcpBanDurationForExceedingTCPTLSRate);
+      vinfolog("Banning connections from %s for %d seconds: too many new QUIC/TCP/TLS connections per second", from.toStringWithPort(), immutable.d_tcpBanDurationForExceedingTCPTLSRate);
       return NewConnectionResult::Denied;
     }
 
@@ -208,7 +212,7 @@
     if (current < threshold) {
       return NewConnectionResult::Allowed;
     }
-    vinfolog("Restricting TCP connection from %s: nearly reaching the maximum number of concurrent TCP connections", from.toStringWithPort());
+    vinfolog("Restricting %s connection from %s: nearly reaching the maximum number of concurrent TCP connections", getProtocol(), from.toStringWithPort());
     return NewConnectionResult::Restricted;
   };
 
diff -ru dnsdist-2.0.3.orig/dnsdist-concurrent-connections.hh dnsdist-2.0.3.CVE-2026-33254/dnsdist-concurrent-connections.hh
--- dnsdist-2.0.3.orig/dnsdist-concurrent-connections.hh	2026-03-12 16:00:00.000000000 +0100
+++ dnsdist-2.0.3.CVE-2026-33254/dnsdist-concurrent-connections.hh	2026-04-03 15:50:27.196813905 +0200
@@ -34,7 +34,7 @@
     Denied = 1,
     Restricted = 2,
   };
-  static NewConnectionResult accountNewTCPConnection(const ComboAddress& from, bool isTLS);
+  static NewConnectionResult accountNewTCPConnection(const ComboAddress& from, bool isTLS, bool isQUIC = false);
   static bool isClientOverThreshold(const ComboAddress& from);
   static void accountTLSNewSession(const ComboAddress& from);
   static void accountTLSResumedSession(const ComboAddress& from);
diff -ru dnsdist-2.0.3.orig/doh3.cc dnsdist-2.0.3.CVE-2026-33254/doh3.cc
--- dnsdist-2.0.3.orig/doh3.cc	2026-03-12 16:00:00.000000000 +0100
+++ dnsdist-2.0.3.CVE-2026-33254/doh3.cc	2026-04-03 15:50:27.196895069 +0200
@@ -30,13 +30,12 @@
 #include "misc.hh"
 #include "sstuff.hh"
 #include "threadname.hh"
-#include "base64.hh"
 
+#include "dnsdist-concurrent-connections.hh"
 #include "dnsdist-dnsparser.hh"
 #include "dnsdist-ecs.hh"
 #include "dnsdist-proxy-protocol.hh"
 #include "dnsdist-tcp.hh"
-#include "dnsdist-random.hh"
 
 #include "doq-common.hh"
 
@@ -60,7 +59,18 @@
   H3Connection(H3Connection&&) = default;
   H3Connection& operator=(const H3Connection&) = delete;
   H3Connection& operator=(H3Connection&&) = default;
-  ~H3Connection() = default;
+  ~H3Connection()
+  {
+    try {
+      /* do not account if we have been moved! */
+      if (d_conn) {
+        dnsdist::IncomingConcurrentTCPConnectionsManager::accountClosedTCPConnection(d_peer);
+      }
+    }
+    catch (...) {
+      /* in theory it might raise an exception, and we cannot allow it to be uncaught in a dtor */
+    }
+  }
 
   std::shared_ptr<const std::string> getSNI()
   {
@@ -962,6 +972,12 @@
         continue;
       }
 
+      auto connectionResult = dnsdist::IncomingConcurrentTCPConnectionsManager::accountNewTCPConnection(client, true, true);
+      if (connectionResult == dnsdist::IncomingConcurrentTCPConnectionsManager::NewConnectionResult::Denied) {
+        DEBUGLOG("Connection not allowed!");
+        continue;
+      }
+
       DEBUGLOG("Creating a new connection");
       conn = createConnection(*frontend.d_server_config, serverConnID, *originalDestinationID, localAddr, client);
       if (!conn) {
Only in dnsdist-2.0.3.CVE-2026-33254: doh3.cc.orig
diff -ru dnsdist-2.0.3.orig/doq.cc dnsdist-2.0.3.CVE-2026-33254/doq.cc
--- dnsdist-2.0.3.orig/doq.cc	2026-03-12 16:00:00.000000000 +0100
+++ dnsdist-2.0.3.CVE-2026-33254/doq.cc	2026-04-03 15:50:27.197002313 +0200
@@ -31,11 +31,11 @@
 #include "sstuff.hh"
 #include "threadname.hh"
 
+#include "dnsdist-concurrent-connections.hh"
 #include "dnsdist-dnsparser.hh"
 #include "dnsdist-ecs.hh"
 #include "dnsdist-proxy-protocol.hh"
 #include "dnsdist-tcp.hh"
-#include "dnsdist-random.hh"
 
 #include "doq-common.hh"
 
@@ -59,7 +59,18 @@
   Connection(Connection&&) = default;
   Connection& operator=(const Connection&) = delete;
   Connection& operator=(Connection&&) = default;
-  ~Connection() = default;
+  ~Connection()
+  {
+    try {
+      /* do not account if we have been moved! */
+      if (d_conn) {
+        dnsdist::IncomingConcurrentTCPConnectionsManager::accountClosedTCPConnection(d_peer);
+      }
+    }
+    catch (...) {
+      /* in theory it might raise an exception, and we cannot allow it to be uncaught in a dtor */
+    }
+  }
 
   std::shared_ptr<const std::string> getSNI()
   {
@@ -753,6 +764,12 @@
         continue;
       }
 
+      auto connectionResult = dnsdist::IncomingConcurrentTCPConnectionsManager::accountNewTCPConnection(client, true, true);
+      if (connectionResult == dnsdist::IncomingConcurrentTCPConnectionsManager::NewConnectionResult::Denied) {
+        DEBUGLOG("Connection not allowed!");
+        continue;
+      }
+
       DEBUGLOG("Creating a new connection");
       conn = createConnection(*frontend.d_server_config, serverConnID, *originalDestinationID, client, localAddr);
       if (!conn) {
Only in dnsdist-2.0.3.CVE-2026-33254: doq.cc.orig
