Format real IPv6 addresses correctly in connect-hook debug logs

getReadableAddress() formatted real (non-IPv4-mapped) IPv6 destinations
by mapping each of the 16 address bytes to hex and joining them with ':'.
That produces 16 single-byte groups with per-byte leading zeros stripped,
so e.g. 2001:db8::1 was logged as '[20:1:d:b8:0:0:0:0:0:0:0:0:0:0:0:1]'.

Group the bytes into the 8 standard hextets instead, and collapse the
longest run of zero hextets to '::' (RFC 5952), so the same address now
logs as '[2001:db8::1]'. IPv4 and IPv4-mapped formatting are unchanged.

This only affects DEBUG_MODE output, but readable addresses are the whole
point of getReadableAddress when checking which connections are being
intercepted or blocked.
This commit is contained in:
az-xx
2026-09-18 07:12:23 +02:00
parent a277db78b7
commit c2c1d58dc4
+24 -2
View File
@@ -242,8 +242,30 @@
}
else {
// Real IPv6:
return `[${[...hostBytes].map(x => x.toString(16)).join(':')}]`;
// Real IPv6: pair up the 16 bytes into 8 hextets, then collapse the longest run
// of zero hextets to '::' (per RFC 5952) so the output is actually readable,
// rather than 16 stray single-byte values (e.g. '2001:db8::1' not '20:1:d:b8:...:1'):
const hextets = [];
for (let i = 0; i < 16; i += 2) {
hextets.push(((hostBytes[i] << 8) | hostBytes[i + 1]).toString(16));
}
// Find the longest run of consecutive zero hextets (only runs of 2+ are worth
// compressing) preferring the leftmost run on a tie:
let runStart = -1, runLength = 0;
for (let i = 0; i < hextets.length; /* advance below */) {
if (hextets[i] !== '0') { i += 1; continue; }
let end = i;
while (end < hextets.length && hextets[end] === '0') end += 1;
if (end - i > runLength) { runStart = i; runLength = end - i; }
i = end;
}
const readable = runLength >= 2
? `${hextets.slice(0, runStart).join(':')}::${hextets.slice(runStart + runLength).join(':')}`
: hextets.join(':');
return `[${readable}]`;
}
};