diff --git a/src/knot/modules/rrl/functions.c b/src/knot/modules/rrl/functions.c
index 01d89cb66949eedc8486a284eb2a6c62592b1887..5534b44377cc83c3c8dd0e381a9657a60c1c07c3 100644
--- a/src/knot/modules/rrl/functions.c
+++ b/src/knot/modules/rrl/functions.c
@@ -68,18 +68,35 @@ static void addr_tostr(char *dst, size_t maxlen, const struct sockaddr_storage *
 	}
 }
 
-static void rrl_log_limited(knotd_mod_t *mod, const struct sockaddr_storage *ss,
+static void rrl_log_limited(rrl_log_params_t *params, const struct sockaddr_storage *ss,
                             const uint8_t prefix, bool rate)
 {
-	if (mod == NULL) {
+	if (params == NULL) {
 		return;
 	}
 
 	char addr_str[SOCKADDR_STRLEN];
 	addr_tostr(addr_str, sizeof(addr_str), ss);
 
-	knotd_mod_log(mod, LOG_NOTICE, "address %s limited on /%d by %s",
-	              addr_str, prefix, rate ? "rate" : "time");
+	const char *proto_str = "UDP";
+	const char *qname_str = NULL;
+	knot_dname_txt_storage_t buf;
+	if (params->qdata != NULL) {
+		qname_str = knot_dname_to_str(buf, knot_pkt_qname(params->qdata->query),
+		                              sizeof(buf));
+	} else {
+		switch (params->proto) {
+		case KNOTD_QUERY_PROTO_TCP:  proto_str = "TCP"; break;
+		case KNOTD_QUERY_PROTO_QUIC: proto_str = "QUIC"; break;
+		case KNOTD_QUERY_PROTO_TLS:  proto_str = "TLS"; break;
+		default:                     break;
+		}
+	}
+
+	knotd_mod_log(params->mod, LOG_NOTICE, "address %s %s limited on /%d by %s%s%s",
+	              addr_str, proto_str, prefix, rate ? "rate" : "time",
+	              (qname_str != NULL ? ", qname " : ""),
+	              (qname_str != NULL ? qname_str : ""));
 }
 
 rrl_table_t *rrl_create(size_t size, uint32_t instant_limit, uint32_t rate_limit,
@@ -131,7 +148,7 @@ rrl_table_t *rrl_create(size_t size, uint32_t instant_limit, uint32_t rate_limit
 	return rrl;
 }
 
-int rrl_query(rrl_table_t *rrl, const struct sockaddr_storage *remote, knotd_mod_t *mod)
+int rrl_query(rrl_table_t *rrl, const struct sockaddr_storage *remote, rrl_log_params_t *log)
 {
 	assert(rrl);
 	assert(remote);
@@ -186,7 +203,7 @@ int rrl_query(rrl_table_t *rrl, const struct sockaddr_storage *remote, knotd_mod
 		do {
 			if (atomic_compare_exchange_weak_explicit(&rrl->log_time, &log_time_orig, now,
 			                                          memory_order_relaxed, memory_order_relaxed)) {
-				rrl_log_limited(mod, remote, prefix, rrl->rw_mode);
+				rrl_log_limited(log, remote, prefix, rrl->rw_mode);
 				break;
 			}
 		} while (now - log_time_orig + 1024 >= rrl->log_period + 1024);
diff --git a/src/knot/modules/rrl/functions.h b/src/knot/modules/rrl/functions.h
index 0941c8378f057651aaff91d5ee1dbd4f5be0aefb..8fe1383c5f019b8aac15506b8693fb1a5600b7ce 100644
--- a/src/knot/modules/rrl/functions.h
+++ b/src/knot/modules/rrl/functions.h
@@ -37,6 +37,12 @@ typedef struct rrl_table rrl_table_t;
 rrl_table_t *rrl_create(size_t size, uint32_t instant_limit, uint32_t rate_limit,
                         bool rw_mode, uint32_t log_period);
 
+typedef struct {
+	knotd_mod_t *mod;
+	knotd_qdata_t *qdata;      // For rate limiting.
+	knotd_query_proto_t proto; // For time limiting.
+} rrl_log_params_t;
+
 /*!
  * \brief Query the RRL table for accept or deny, when the rate limit is reached.
  *
@@ -44,12 +50,12 @@ rrl_table_t *rrl_create(size_t size, uint32_t instant_limit, uint32_t rate_limit
  *
  * \param rrl RRL table.
  * \param remote Source address.
- * \param mod Query module (needed for logging).
+ * \param log Logging parameters (can be NULL).
  *
  * \retval KNOT_EOK if passed.
  * \retval KNOT_ELIMIT when the limit is reached.
  */
-int rrl_query(rrl_table_t *rrl, const struct sockaddr_storage *remote, knotd_mod_t *mod);
+int rrl_query(rrl_table_t *rrl, const struct sockaddr_storage *remote, rrl_log_params_t *log);
 
 /*!
  * \brief Update the RRL table.
diff --git a/src/knot/modules/rrl/rrl.c b/src/knot/modules/rrl/rrl.c
index 17e77381254d7ee516e7b1e50ff32f3916816eb7..162eb8875fbaeac5cb01ece58659c464aedcb625 100644
--- a/src/knot/modules/rrl/rrl.c
+++ b/src/knot/modules/rrl/rrl.c
@@ -30,10 +30,10 @@
 #define MOD_DRY_RUN		"\x07""dry-run"
 
 const yp_item_t rrl_conf[] = {
-	{ MOD_INST_LIMIT,    YP_TINT, YP_VINT = { 1,  (1ll << 32) / 768 - 1, 50 } },
-	{ MOD_RATE_LIMIT,    YP_TINT, YP_VINT = { 0, ((1ll << 32) / 768 - 1) * 1000, 20 } },
+	{ MOD_INST_LIMIT,    YP_TINT, YP_VINT = { 1,  (1ll << 32) / 768 - 1, 125 } },
+	{ MOD_RATE_LIMIT,    YP_TINT, YP_VINT = { 0, ((1ll << 32) / 768 - 1) * 1000, 50 } },
 	{ MOD_T_INST_LIMIT,  YP_TINT, YP_VINT = { 1, 1000000, 5000 } },
-	{ MOD_T_RATE_LIMIT,  YP_TINT, YP_VINT = { 0, 1000000000, 4000 } },
+	{ MOD_T_RATE_LIMIT,  YP_TINT, YP_VINT = { 0, 1000000000, 5000 } },
 	{ MOD_SLIP,          YP_TINT, YP_VINT = { 0, 100, 1 } },
 	{ MOD_TBL_SIZE,      YP_TINT, YP_VINT = { 1, INT32_MAX, 524288 } },
 	{ MOD_WHITELIST,     YP_TNET, YP_VNONE, YP_FMULTI },
@@ -64,8 +64,7 @@ int rrl_conf_check(knotd_conf_check_args_t *args)
 typedef struct {
 	ALIGNED_CPU_CACHE // Ensures that one thread context occupies one cache line.
 	struct timespec start_time; // Start time of the measurement.
-	bool whitelist_checked; // Indication whether whitelist check took place.
-	bool skip; // Skip the rest of the module callbacks.
+	bool skip; // Skip the time table update.
 } thrd_ctx_t;
 
 typedef struct {
@@ -87,24 +86,26 @@ static knotd_proto_state_t protolimit_start(knotd_proto_state_t state,
                                             knotd_qdata_params_t *params,
                                             knotd_mod_t *mod)
 {
+	assert(params && mod);
+
 	rrl_ctx_t *ctx = knotd_mod_ctx(mod);
 	thrd_ctx_t *thrd = &ctx->thrd_ctx[params->thread_id];
 	thrd->skip = false;
 
-	// Check if a whitelisted client.
-	thrd->whitelist_checked = true;
-	if (knotd_conf_addr_range_match(&ctx->whitelist, params->remote)) {
-		thrd->skip = true;
+	// Time limiting not supported for UDP (source address can be forged).
+	if (params->proto == KNOTD_QUERY_PROTO_UDP) {
 		return state;
 	}
 
-	// UDP time limiting not implemented (source address can be forged).
-	if (params->proto == KNOTD_QUERY_PROTO_UDP) {
+	// Check if a whitelisted client.
+	if (knotd_conf_addr_range_match(&ctx->whitelist, params->remote)) {
+		thrd->skip = true;
 		return state;
 	}
 
 	// Check if the packet is limited.
-	if (rrl_query(ctx->time_table, params->remote, mod) != KNOT_EOK) {
+	rrl_log_params_t log = { .mod = mod, .proto = params->proto };
+	if (rrl_query(ctx->time_table, params->remote, &log) != KNOT_EOK) {
 		thrd->skip = true;
 		knotd_mod_stats_incr(mod, params->thread_id, 2, 0, 1);
 		return ctx->dry_run ? state : KNOTD_PROTO_STATE_BLOCK;
@@ -118,13 +119,21 @@ static knotd_proto_state_t protolimit_end(knotd_proto_state_t state,
                                           knotd_qdata_params_t *params,
                                           knotd_mod_t *mod)
 {
+	assert(params && mod);
+
 	rrl_ctx_t *ctx = knotd_mod_ctx(mod);
 	thrd_ctx_t *thrd = &ctx->thrd_ctx[params->thread_id];
 
+	// Time rate limit is applied to non-UDP.
 	if (thrd->skip || params->proto == KNOTD_QUERY_PROTO_UDP) {
 		return state;
 	}
 
+	// Don't limit authorized operations.
+	if (params->flags & KNOTD_QUERY_FLAG_AUTHORIZED) {
+		return state;
+	}
+
 	// Update the time table.
 	struct timespec end_time;
 	clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end_time);
@@ -142,36 +151,26 @@ static knotd_state_t ratelimit_apply(knotd_state_t state, knot_pkt_t *pkt,
 	assert(pkt && qdata && mod);
 
 	rrl_ctx_t *ctx = knotd_mod_ctx(mod);
-	thrd_ctx_t *thrd = &ctx->thrd_ctx[qdata->params->thread_id];
-
-	if (thrd->skip) {
-		return state;
-	}
-
-	// Don't limit authorized operations.
-	if (qdata->params->flags & KNOTD_QUERY_FLAG_AUTHORIZED) {
-		thrd->skip = true;
-		return state;
-	}
 
-	// Rate limit is applied to UDP only.
+	// Rate limiting is applied only to UDP.
 	if (qdata->params->proto != KNOTD_QUERY_PROTO_UDP) {
 		return state;
 	}
 
-	// Check for whitelisted client IF PER-ZONE module (no proto callbacks).
-	if (!thrd->whitelist_checked &&
-	    knotd_conf_addr_range_match(&ctx->whitelist, qdata->params->remote)) {
-		thrd->skip = true;
+	// NOTE: (qdata->params->flags & KNOTD_QUERY_FLAG_AUTHORIZED) can't be true here.
+
+	// Check for whitelisted client.
+	if (knotd_conf_addr_range_match(&ctx->whitelist, qdata->params->remote)) {
 		return state;
 	}
 
-	// Rate limit is not applied to responses with a valid cookie.
+	// Rate limiting is not applied to responses with a valid cookie.
 	if (qdata->params->flags & KNOTD_QUERY_FLAG_COOKIE) {
 		return state;
 	}
 
-	if (rrl_query(ctx->rate_table, knotd_qdata_remote_addr(qdata), mod) == KNOT_EOK) {
+	rrl_log_params_t log = { .mod = mod, .qdata = qdata };
+	if (rrl_query(ctx->rate_table, knotd_qdata_remote_addr(qdata), &log) == KNOT_EOK) {
 		// Rate limiting not applied.
 		return state;
 	}
diff --git a/src/knot/modules/rrl/rrl.rst b/src/knot/modules/rrl/rrl.rst
index 2b558d6c71f6aad1f9637e72fc0a39a025a434f8..04c37edaddf34ecb4b66c74afe4ee246c77b5d65 100644
--- a/src/knot/modules/rrl/rrl.rst
+++ b/src/knot/modules/rrl/rrl.rst
@@ -15,7 +15,8 @@ responses as truncated or by dropping them altogether.
 This module can also help protect the server from excessive utilization by
 limiting incoming packets (including handshakes) based on consumed time.
 If a packet is time rate limited, it's dropped. This function works with
-all supported non-UDP transport protocols and cannot be configured per zone.
+all supported non-UDP transport protocols (TCP, TLS, and QUIC) and cannot
+be configured per zone.
 
 .. NOTE::
    This module introduces three statistics counters:
@@ -28,6 +29,12 @@ all supported non-UDP transport protocols and cannot be configured per zone.
    If the :ref:`Cookies<mod-cookies>` module is active, RRL is not applied
    to UDP responses with a valid DNS cookie.
 
+.. NOTE::
+   The time limiting applies even to handshakes of incoming authorized requests
+   (e.g. NOTIFY, AXFR). In such cases, setting :ref:`mod-rrl_whitelist` or reusing
+   already established connections (e.g. :ref:`server_remote-pool-timeout` on
+   the remote server) can mitigate this issue.
+
 Example
 -------
 
@@ -96,7 +103,9 @@ i.e. they are lowered by a constant fraction of their value each millisecond.
 The specified rate limit is reached, when the number of queries is the same every millisecond;
 sending many queries once a second or even a larger timespan leads to a more strict limiting.
 
-*Default:* ``20``
+Set to 0 to disable the rate limiting.
+
+*Default:* ``50``
 
 .. _mod-rrl_instant-limit:
 
@@ -115,7 +124,7 @@ is periodically lowered.
 The :ref:`mod-rrl_instant-limit` may be at least :ref:`mod-rrl_rate-limit` **/ 1000**, at which point the
 counters are zeroed each millisecond.
 
-*Default:* ``50``
+*Default:* ``125``
 
 .. _mod-rrl_slip:
 
@@ -161,7 +170,9 @@ time-rate-limit
 This limit works similarly to :ref:`mod-rrl_rate-limit` but considers the time
 consumed (in microseconds) by the remote over non-UDP transport protocols.
 
-*Default:* ``4000`` (microseconds)
+Set to 0 to disable the time limiting.
+
+*Default:* ``5000`` (microseconds)
 
 .. _mod-rrl_time-instant-limit:
 
diff --git a/src/knot/nameserver/internet.h b/src/knot/nameserver/internet.h
index bb6927ddc0c48d2e3f661afde4e0a44f024fe19c..594631ed7474d1c3422f76b738de45584fa2cea5 100644
--- a/src/knot/nameserver/internet.h
+++ b/src/knot/nameserver/internet.h
@@ -64,6 +64,7 @@ knot_layer_state_t internet_process_query(knot_pkt_t *pkt, knotd_qdata_t *qdata)
 #define NS_NEED_AUTH(qdata, action) \
 	if (!process_query_acl_check(conf(), (action), (qdata)) || \
 	    process_query_verify(qdata) != KNOT_EOK) { \
+		qdata->params->flags &= ~KNOTD_QUERY_FLAG_AUTHORIZED; \
 		return KNOT_STATE_FAIL; \
 	} else { \
 		qdata->params->flags |= KNOTD_QUERY_FLAG_AUTHORIZED; \
diff --git a/src/knot/server/handler.c b/src/knot/server/handler.c
index bcd0ec56086e46f22945b80cc69db7d2b2e10f1b..2bc27da81d1b8d9e0f792d4d45799bd9fbf90bb5 100644
--- a/src/knot/server/handler.c
+++ b/src/knot/server/handler.c
@@ -94,6 +94,13 @@ static void handle_quic_stream(knot_quic_conn_t *conn, int64_t stream_id, struct
 	}
 
 	handle_finish(layer);
+
+	// Store the qdata params AUTH flag to the connection.
+	if (params->flags & KNOTD_QUERY_FLAG_AUTHORIZED) {
+		conn->flags |= KNOT_QUIC_CONN_AUTHORIZED;
+	} else {
+		conn->flags &= ~KNOT_QUIC_CONN_AUTHORIZED;
+	}
 }
 
 void handle_quic_streams(knot_quic_conn_t *conn, knotd_qdata_params_t *params,
@@ -101,14 +108,15 @@ void handle_quic_streams(knot_quic_conn_t *conn, knotd_qdata_params_t *params,
 {
 	uint8_t ans_buf[KNOT_WIRE_MAX_PKTSIZE];
 
+	params_update_quic(params, conn);
+
 	int64_t stream_id;
 	knot_quic_stream_t *stream;
-
 	while (conn != NULL && (stream = knot_quic_stream_get_process(conn, &stream_id)) != NULL) {
 		assert(stream->inbufs != NULL);
 		assert(stream->inbufs->n_inbufs > 0);
 		struct iovec *inbufs = stream->inbufs->inbufs;
-		params_update_quic(params, knot_quic_conn_rtt(conn), conn, stream_id);
+		params_update_quic_stream(params, stream_id);
 		// NOTE: only the first msg in the stream is used, the rest is dropped.
 		handle_quic_stream(conn, stream_id, &inbufs[0], layer, params,
 		                   ans_buf, sizeof(ans_buf));
diff --git a/src/knot/server/handler.h b/src/knot/server/handler.h
index 4b63a0c16b42c8b656515f2fffb0858108490bc7..23dbcf7e8aeafe8157ed66cc1e81526385e71962 100644
--- a/src/knot/server/handler.h
+++ b/src/knot/server/handler.h
@@ -53,18 +53,30 @@ inline static knotd_qdata_params_t params_init(knotd_query_proto_t proto,
 	return params;
 }
 
-inline static void params_update_tcp(knotd_qdata_params_t *params, uint32_t rtt)
+inline static void params_update_tcp(knotd_qdata_params_t *params,
+                                     knot_tcp_conn_t *conn)
 {
-	params->measured_rtt = rtt;
+	params->measured_rtt = conn->establish_rtt;
+	if (conn->flags & KNOT_TCP_CONN_AUTHORIZED) {
+		params->flags |= KNOTD_QUERY_FLAG_AUTHORIZED;
+	}
 }
 
 #ifdef ENABLE_QUIC
-inline static void params_update_quic(knotd_qdata_params_t *params, uint32_t rtt,
-                                      knot_quic_conn_t *conn, int64_t stream_id)
+inline static void params_update_quic(knotd_qdata_params_t *params,
+                                      knot_quic_conn_t *conn)
 {
 	params->quic_conn = conn;
+	if (conn->flags & KNOT_QUIC_CONN_AUTHORIZED) {
+		params->flags |= KNOTD_QUERY_FLAG_AUTHORIZED;
+	}
+}
+
+inline static void params_update_quic_stream(knotd_qdata_params_t *params,
+                                             int64_t stream_id)
+{
 	params->quic_stream = stream_id;
-	params->measured_rtt = rtt;
+	params->measured_rtt = knot_quic_conn_rtt(params->quic_conn);
 }
 #endif // ENABLE_QUIC
 
@@ -72,6 +84,9 @@ inline static void params_update_tls(knotd_qdata_params_t *params,
                                      knot_tls_conn_t *conn)
 {
 	params->tls_conn = conn;
+	if (params->tls_conn->flags & KNOT_TLS_CONN_AUTHORIZED) {
+		params->flags |= KNOTD_QUERY_FLAG_AUTHORIZED;
+	}
 }
 
 #ifdef ENABLE_XDP
diff --git a/src/knot/server/tcp-handler.c b/src/knot/server/tcp-handler.c
index 54bc3a27a566f11cef92c3f71693f78aa585b4bd..455dafc452b6a540bf35f75b2f96242c03499326 100644
--- a/src/knot/server/tcp-handler.c
+++ b/src/knot/server/tcp-handler.c
@@ -175,7 +175,9 @@ static int tcp_handle(tcp_context_t *tcp, knotd_qdata_params_t *params,
 			recv = knot_tls_recv_dns(params->tls_conn, rx->iov_base, rx->iov_len);
 			break;
 		default: // E.g. handshake timeout.
-			return ret;
+			assert(ret < 0);
+			recv = ret;
+			break;
 		}
 	} else {
 		recv = net_dns_tcp_recv(params->socket, rx->iov_base, rx->iov_len, tcp->io_timeout);
@@ -212,6 +214,15 @@ static int tcp_handle(tcp_context_t *tcp, knotd_qdata_params_t *params,
 
 	handle_finish(&tcp->layer);
 
+	if (params->tls_conn != NULL) {
+		// Store the qdata params AUTH flag to the connection.
+		if (params->flags & KNOTD_QUERY_FLAG_AUTHORIZED) {
+			params->tls_conn->flags |= KNOT_TLS_CONN_AUTHORIZED;
+		} else {
+			params->tls_conn->flags &= ~KNOT_TLS_CONN_AUTHORIZED;
+		}
+	}
+
 	return KNOT_EOK;
 }
 
diff --git a/src/knot/server/xdp-handler.c b/src/knot/server/xdp-handler.c
index 403bb70cac4a917484995adf542ea572ecff2ad0..8e83d1936be9c7500b4b49621fe3d86b801bf4f8 100644
--- a/src/knot/server/xdp-handler.c
+++ b/src/knot/server/xdp-handler.c
@@ -223,7 +223,6 @@ static void handle_udp(xdp_handle_ctx_t *ctx, knot_layer_t *layer,
 static void handle_tcp(xdp_handle_ctx_t *ctx, knot_layer_t *layer,
                        knotd_qdata_params_t *params)
 {
-
 	uint8_t ans_buf[KNOT_WIRE_MAX_PKTSIZE];
 
 	for (uint32_t i = 0; i < ctx->msg_recv_count; i++) {
@@ -251,8 +250,7 @@ static void handle_tcp(xdp_handle_ctx_t *ctx, knot_layer_t *layer,
 		} else if (knot_tcp_relay_empty(rl)) {
 			continue;
 		}
-
-		params_update_tcp(params, rl->conn->establish_rtt);
+		params_update_tcp(params, rl->conn);
 
 		// Process all complete DNS queries in one TCP stream.
 		for (size_t j = 0; rl->inbf != NULL && j < rl->inbf->n_inbufs; j++) {
@@ -273,6 +271,12 @@ static void handle_tcp(xdp_handle_ctx_t *ctx, knot_layer_t *layer,
 			}
 
 			handle_finish(layer);
+
+			if (params->flags & KNOTD_QUERY_FLAG_AUTHORIZED) {
+				rl->conn->flags |= KNOT_TCP_CONN_AUTHORIZED;
+			} else {
+				rl->conn->flags &= ~KNOT_TCP_CONN_AUTHORIZED;
+			}
 		}
 
 		(void)process_query_proto(params, KNOTD_STAGE_PROTO_END);
diff --git a/src/libknot/quic/quic_conn.h b/src/libknot/quic/quic_conn.h
index b19d50e0bd8f5aa62f0d335859f789f449c46fb2..bab15c2fa9e0e73379d9cb2bbc12690a5730c941 100644
--- a/src/libknot/quic/quic_conn.h
+++ b/src/libknot/quic/quic_conn.h
@@ -74,6 +74,7 @@ typedef enum {
 	KNOT_QUIC_CONN_HANDSHAKE_DONE = (1 << 0),
 	KNOT_QUIC_CONN_SESSION_TAKEN  = (1 << 1),
 	KNOT_QUIC_CONN_BLOCKED        = (1 << 2),
+	KNOT_QUIC_CONN_AUTHORIZED     = (1 << 3),
 } knot_quic_conn_flag_t;
 
 typedef struct knot_quic_conn {
diff --git a/src/libknot/quic/tls.h b/src/libknot/quic/tls.h
index 2acced1a9c937b873a2d6ba92daee589a72b95ba..db7182ed06a692f296445ed0741ae56759f9650b 100644
--- a/src/libknot/quic/tls.h
+++ b/src/libknot/quic/tls.h
@@ -35,6 +35,7 @@ typedef enum {
 	KNOT_TLS_CONN_HANDSHAKE_DONE = (1 << 0),
 	KNOT_TLS_CONN_SESSION_TAKEN  = (1 << 1), // unused, to be implemeted later
 	KNOT_TLS_CONN_BLOCKED        = (1 << 2),
+	KNOT_TLS_CONN_AUTHORIZED     = (1 << 3),
 } knot_tls_conn_flag_t;
 
 typedef struct knot_tls_ctx {
diff --git a/src/libknot/xdp/tcp.c b/src/libknot/xdp/tcp.c
index d219db97749d2f1b67a2b062c6ee3f450976aa4a..2374953a429aeabf34ecb7424008312cdb56da72 100644
--- a/src/libknot/xdp/tcp.c
+++ b/src/libknot/xdp/tcp.c
@@ -227,6 +227,7 @@ static void conn_init_from_msg(knot_tcp_conn_t *conn, knot_xdp_msg_t *msg)
 	conn->last_active = get_timestamp();
 	conn->state = XDP_TCP_NORMAL;
 	conn->establish_rtt = 0;
+	conn->flags = 0;
 
 	memset(&conn->inbuf, 0, sizeof(conn->inbuf));
 	memset(&conn->outbufs, 0, sizeof(conn->outbufs));
diff --git a/src/libknot/xdp/tcp.h b/src/libknot/xdp/tcp.h
index 39a30fd41ff04a14a43c951245fae848ce4b33f1..bad28498e1d1811fff77b9623257f400037b9373 100644
--- a/src/libknot/xdp/tcp.h
+++ b/src/libknot/xdp/tcp.h
@@ -61,6 +61,10 @@ typedef enum {
 	XDP_TCP_IGNORE_FIN         = (1 << 2),
 } knot_tcp_ignore_t;
 
+typedef enum {
+	KNOT_TCP_CONN_AUTHORIZED = (1 << 0),
+} knot_tcp_conn_flag_t;
+
 typedef struct knot_tcp_conn {
 	struct {
 		struct knot_tcp_conn *list_node_next;
@@ -79,6 +83,7 @@ typedef struct knot_tcp_conn {
 	uint32_t last_active;
 	uint32_t establish_rtt; // in microseconds
 	knot_tcp_state_t state;
+	knot_tcp_conn_flag_t flags;
 	struct iovec inbuf;
 	struct knot_tcp_outbuf *outbufs;
 	struct knot_tcp_conn *next;