From c703d26e54fc59db06916c89090deac1a8a8df52 Mon Sep 17 00:00:00 2001 From: Vladimir Dubrovin <3proxy@3proxy.ru> Date: Thu, 1 Oct 2026 16:57:36 +0300 Subject: [PATCH] Fix: invalid hostname ACL handling in UDPASSOC --- src/udpsockmap.c | 6 ++++++ tests/cases/socks.py | 25 ++++++++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/udpsockmap.c b/src/udpsockmap.c index 9729d73..96df681 100644 --- a/src/udpsockmap.c +++ b/src/udpsockmap.c @@ -288,6 +288,12 @@ int udpsockmap(struct clientparam *param, int timeo) } default: return 997; } + /* As for TCP requests, a literal address is the host name, + otherwise an ACL with host names only matches any address */ + if (!dstname) { + myinet_ntop(*SAFAMILY(&dst), SAADDR(&dst), dstnamebuf, sizeof(dstnamebuf)); + dstname = dstnamebuf; + } memcpy(SAPORT(&dst), base + i, 2); i += 2; diff --git a/tests/cases/socks.py b/tests/cases/socks.py index 39de551..96069be 100644 --- a/tests/cases/socks.py +++ b/tests/cases/socks.py @@ -5,6 +5,8 @@ def run(t): srv = t.free_port() sks = t.free_port() sauth = t.free_port() + sdeny = t.free_port() + sallow = t.free_port() t.start("socks", f""" log @@ -24,7 +26,18 @@ def run(t): users alice:CL:secret allow alice socks -p{sauth} - """, ports=[srv, sks, sauth]) + + flush + auth iponly + deny * * *.example.com + allow * + socks -p{sdeny} + + flush + auth iponly + allow * * *.example.com + socks -p{sallow} + """, ports=[srv, sks, sauth, sdeny, sallow]) origin = f"http://127.0.0.1:{srv}" plain = f"127.0.0.1:{sks}" @@ -62,6 +75,16 @@ def run(t): _, second = t.socks_udp(plain, "127.0.0.1", echo, b"two") t.ne(first, second, "a second association binds its own port") + # A datagram names its destination by address. A rule listing host names + # only has to judge it by that address as text, the way CONNECT is judged, + # rather than match whatever the address is. + reply, _ = t.socks_udp(f"127.0.0.1:{sdeny}", "127.0.0.1", echo, b"ip") + t.eq(b"echo:ip", reply, + "a deny by host name leaves datagrams to an address alone") + reply, _ = t.socks_udp(f"127.0.0.1:{sallow}", "127.0.0.1", echo, b"ip") + t.eq(None, reply, + "an allow by host name does not let datagrams to an address through") + # --- authentication ---------------------------------------------------- t.eq(200, t.socks_http(guarded, origin + "/echo", auth=("alice", "secret")).status,