From: Vsevolod Stakhov Date: Fri, 24 Jul 2026 18:18:50 +0000 (+0100) Subject: [Feature] fuzzy: track unkeyed clients in fuzzystat X-Git-Tag: 4.1.3~23^2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=56157dc6b3da690dd8ad895246dee886c486f342;p=thirdparty%2Frspamd.git [Feature] fuzzy: track unkeyed clients in fuzzystat Traffic from clients without a key (e.g. permitted by allow_update) was invisible in the key statistics, which makes storage writers untraceable. Track such clients under a dedicated 'unkeyed' pseudo-key with the same aggregate and per-IP counters as regular keys. --- diff --git a/src/fuzzy_storage.c b/src/fuzzy_storage.c index 3d10b4ab19..2f69f7a54e 100644 --- a/src/fuzzy_storage.c +++ b/src/fuzzy_storage.c @@ -572,6 +572,11 @@ rspamd_fuzzy_update_stats(struct rspamd_fuzzy_storage_ctx *ctx, ctx->stat.delayed_hashes++; } + if (key == NULL && ip_stat != NULL && ctx->unkeyed_stat != NULL) { + /* Unkeyed client: update the aggregate bucket */ + rspamd_fuzzy_update_key_stat(matched, ctx->unkeyed_stat, cmd, res, timestamp); + } + if (key) { rspamd_fuzzy_update_key_stat(matched, key->stat, cmd, res, timestamp); @@ -1366,6 +1371,37 @@ rspamd_fuzzy_process_command(struct fuzzy_session *session) REF_RETAIN(ip_stat); session->ip_stat = ip_stat; } + else if (session->addr) { + /* + * Unkeyed client (e.g. allowed by IP): track its traffic under the + * dedicated bucket, otherwise such writers are invisible in the stats + */ + if (session->ctx->unkeyed_stat == NULL) { + struct fuzzy_key_stat *unkeyed = g_malloc0(sizeof(*unkeyed)); + + REF_INIT_RETAIN(unkeyed, fuzzy_key_stat_dtor); + unkeyed->last_ips = rspamd_lru_hash_new_full(1024, + (GDestroyNotify) rspamd_inet_address_free, + fuzzy_key_stat_unref, + rspamd_inet_address_hash, + rspamd_inet_address_equal); + session->ctx->unkeyed_stat = unkeyed; + } + + ip_stat = rspamd_lru_hash_lookup(session->ctx->unkeyed_stat->last_ips, + session->addr, -1); + + if (ip_stat == NULL) { + naddr = rspamd_inet_address_copy(session->addr, NULL); + ip_stat = g_malloc0(sizeof(*ip_stat)); + REF_INIT_RETAIN(ip_stat, fuzzy_key_stat_dtor); + rspamd_lru_hash_insert(session->ctx->unkeyed_stat->last_ips, + naddr, ip_stat, -1, 0); + } + + REF_RETAIN(ip_stat); + session->ip_stat = ip_stat; + } if (cmd->cmd == FUZZY_CHECK) { bool is_rate_allowed = true; @@ -3276,6 +3312,8 @@ start_fuzzy(struct rspamd_worker *worker) rspamd_fuzzy_storage_reload, ctx); rspamd_control_worker_add_cmd_handler(worker, RSPAMD_CONTROL_FUZZY_STAT, rspamd_fuzzy_storage_stat, ctx); + rspamd_control_worker_add_cmd_handler(worker, RSPAMD_CONTROL_FUZZY_HASH, + rspamd_fuzzy_storage_hash_info, ctx); rspamd_control_worker_add_cmd_handler(worker, RSPAMD_CONTROL_FUZZY_SYNC, rspamd_fuzzy_storage_sync, ctx); rspamd_control_worker_add_cmd_handler(worker, RSPAMD_CONTROL_FUZZY_BLOCKED,