Refuse local-use NAT64 addresses, and IPv4-compatible ones in blocked_networks (closes #299) #300

Merged
clawbot merged 7 commits from issue-299-nat64-local-and-blocked-networks into next 2026-10-16 06:52:18 +02:00
7 Commits
Author SHA1 Message Date
sneak 07c4746c59 Correct the comment on asIPv4 in isBlockedIP
check / check (push) Waiting to run
Its last sentence said asIPv4 differs from addr only for an
IPv4-compatible address, which is untrue for any other IPv6 address,
where asIPv4 is the zero netip.Addr. It now says that matching asIPv4
as well as addr refuses more only for an IPv4-compatible address.

Model: opus-5-5
2026-10-16 04:38:58 +00:00
sneak 19113ffa2f Match the mapped form against blocked_networks only as IPv4
check / check (push) Canceled after 0s
isBlockedIP again matches an IPv4-mapped address (::ffff:0:0/96) only
as the IPv4 address it holds, as on next: Go keeps a plain IPv4 address
in that form, so matching it as written let an IPv6 entry such as ::/0
refuse every IPv4 address. An IPv4-compatible address (::/96) is still
matched both as written and as the IPv4 address it holds.
ipv6AndIPv4Forms is gone. README.md says the mapped form is matched as
IPv4 only.

Model: opus-5-5
2026-10-16 04:25:45 +00:00
sneak a5088a69a1 Test that an IPv6 entry in blocked_networks does not refuse a plain IPv4 source
check / check (push) Canceled after 0s
Both image routes: the plain IPv4 source host 203.0.113.5 must not be
refused when blocked_networks lists ::/0. It fails on this branch: Go
keeps a plain IPv4 address in the mapped form, and isBlockedIP matches
that form as written. The case that expected [::ffff:203.0.113.5]
refused with ::ffff:0:0/96 listed, added earlier on this branch, is
dropped: the mapped form is matched only as the IPv4 address it holds.

Model: opus-5-5
2026-10-16 04:24:19 +00:00
sneak 8fceeca202 Match blocked_networks against both forms of an address holding IPv4
check / check (push) Canceled after 0s
isBlockedIP refuses an address when a blocked_networks entry contains
it as an IPv6 address or contains the IPv4 address it holds, for the
mapped (::ffff:0:0/96) and the IPv4-compatible (::/96) form alike, so
an IPv6 entry refuses everything it refused on next. ipv6AndIPv4Forms
gives the two forms. Go keeps a plain IPv4 address in the mapped form,
so an entry covering ::ffff:0:0/96, such as ::/0, now refuses every
IPv4 address too.

Model: opus-5-5
2026-10-16 04:14:20 +00:00
sneak 4900837068 Test blocked_networks on both forms of an IPv6 source host holding IPv4
Both image routes: [::203.0.113.5] must answer 403 when blocked_networks
lists ::/96, and [::ffff:203.0.113.5] when it lists ::ffff:0:0/96 or
203.0.113.0/24. The ::/96 and ::ffff:0:0/96 cases fail on this branch:
isBlockedIP matches such an address only by the IPv4 address it holds.

Model: opus-5-5
2026-10-16 04:14:20 +00:00
sneak 294474a2cd Refuse local-use NAT64 addresses, and IPv4-compatible ones in blocked_networks (closes #299)
check / check (push) Canceled after 0s
64:ff9b:1::/48 joins the built-in blocked ranges next to 64:ff9b::/96.
isBlockedIP now reads an address in ::/96 as the IPv4 address in its
last four bytes before matching blocked_networks, as it already unmapped
the ::ffff: form. The reading isPrivateIP gained for ::/96 moved into
ipv4CompatibleToIPv4, which both call.

Model: opus-5-5
2026-10-16 03:43:55 +00:00
sneak 04d9a6bf37 Test the local-use NAT64 range and blocked_networks on IPv6 source hosts
check / check (push) Canceled after 0s
Both image routes, with the fetcher pixad builds from the config:
[64:ff9b:1::a00:1] must answer 403, and [::203.0.113.5] must answer 403
when blocked_networks lists 203.0.113.0/24 and must not be refused when
the list is empty. The first two fail on next: both addresses are
fetched.

Model: opus-5-5
2026-10-16 03:40:53 +00:00