From f28552fc6ff5d247fd3e324c547c205d82063695 Mon Sep 17 00:00:00 2001 From: Vladimir Dubrovin <3proxy@3proxy.ru> Date: Sun, 18 Oct 2026 16:32:49 +0300 Subject: [PATCH] UDP loop: a session found by hash is checked against the client's address The sessions of a keyed UDP service were found by a hash of the client's address with a fixed seed, so an address crafted to collide with another client's would have its datagrams taken as that client's. The hash is now seeded with the table's random entropy, and a session found is used only if its client's address, port and family are the datagram's; otherwise the datagram is a new client's. Co-Authored-By: Claude Opus 5.5 --- src/mainudp.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/mainudp.c b/src/mainudp.c index 028d1fa..5b5682d 100644 --- a/src/mainudp.c +++ b/src/mainudp.c @@ -30,7 +30,8 @@ static void udpkey2hash(const struct hashtable *ht, void *index, uint8_t *hash){ PROXYSOCKADDRTYPE *sa = (PROXYSOCKADDRTYPE *)index; uint32_t m1, m2; - m1 = murmurhash3(SAADDR(sa), SAADDRLEN(sa), 0x3a3a3a3a); + /* seeded at random per table: an address is not chosen to collide */ + m1 = murmurhash3(SAADDR(sa), SAADDRLEN(sa), ht->entropy); m2 = murmurhash3(SAPORT(sa), 2, m1); memcpy(hash, &m1, 4); memcpy(hash+4, &m2, 4); @@ -279,7 +280,11 @@ static void udpclients(struct udpstate *st, time_t now){ #endif break; } - if(st->svc->keyed && hashresolv(&st->keys, &defparam->sincr, &ss, NULL)){ + /* the hash found is checked against the address itself */ + if(st->svc->keyed && hashresolv(&st->keys, &defparam->sincr, &ss, NULL) && + *SAFAMILY(&ss->param->sincr) == *SAFAMILY(&defparam->sincr) && + !memcmp(SAADDR(&ss->param->sincr), SAADDR(&defparam->sincr), SAADDRLEN(&defparam->sincr)) && + *SAPORT(&ss->param->sincr) == *SAPORT(&defparam->sincr)){ if(ss->done) continue; udprefresh(ss, now); if(st->svc->client && (*st->svc->client)(&st->u, ss, srv->udpbuf, len)) ss->done = 1;