Block local-use NAT64 and IPv6 benchmarking ranges

The local-use NAT64 prefix (64:ff9b:1::/48, RFC 8215) embeds an IPv4
target like the well-known prefix does, but at a deployment-chosen
position we can't extract, so block the whole range outright.

Also block the IPv6 benchmarking range (2001:2::/48, RFC 5180) to match
the IPv4 benchmarking block on 198.18.0.0/15.
This commit is contained in:
Donal McBreen
2026-07-20 16:49:40 +01:00
parent 0de302c977
commit 9085adcbb3
2 changed files with 13 additions and 2 deletions
+6 -1
View File
@@ -20,8 +20,13 @@ module RestrictedHTTP
# fetch target, so they are blocked outright. ULA (fc00::/7, incl. the AWS
# IMDSv6 address fd00:ec2::254), link-local, and loopback are covered by the
# predicates in #disallowed_ipv6?.
# The local-use NAT64 prefix (64:ff9b:1::/48, RFC 8215) also embeds an
# IPv4 target, but at a deployment-chosen position we can't extract, and it
# is only meaningful inside the network that deployed it, so it is blocked
# outright rather than handled like NAT64_WELL_KNOWN below.
DISALLOWED_IPV6 = %w[
::/128 100::/64 2001::/32 2001:db8::/32 2002::/16 fec0::/10 ff00::/8
::/128 64:ff9b:1::/48 100::/64 2001::/32 2001:2::/48 2001:db8::/32
2002::/16 fec0::/10 ff00::/8
].map { |cidr| IPAddr.new(cidr) }.freeze
# Well-known NAT64 prefix (RFC 6052/6146). An address here embeds an IPv4
@@ -74,6 +74,11 @@ class RestrictedHTTP::PrivateNetworkGuardTest < ActiveSupport::TestCase
assert_private_ip "64:ff9b::a00:5" # NAT64 -> 10.0.0.5
end
test "private_ip? returns true for local-use NAT64 addresses (RFC8215)" do
assert_private_ip "64:ff9b:1:fffe::a00:1" # local-use NAT64 embedding 10.0.0.1
assert_private_ip "64:ff9b:1::808:808" # blocked even when embedding a public IP
end
test "private_ip? returns false for NAT64 addresses embedding a public IPv4" do
# DNS64 legitimately synthesizes these for public sites on IPv6-only hosts.
assert_not RestrictedHTTP::PrivateNetworkGuard.private_ip?("64:ff9b::808:808") # -> 8.8.8.8
@@ -90,9 +95,10 @@ class RestrictedHTTP::PrivateNetworkGuardTest < ActiveSupport::TestCase
assert_private_ip "fe80::1"
end
test "private_ip? returns true for IPv6 multicast and documentation ranges" do
test "private_ip? returns true for IPv6 multicast, documentation, and benchmarking ranges" do
assert_private_ip "ff02::1"
assert_private_ip "2001:db8::1"
assert_private_ip "2001:2::1" # benchmarking (RFC5180), matches 198.18.0.0/15
end
test "private_ip? returns false for public IPv6 addresses" do