From 8914b7881677eedebf087bd053933d6a332446b4 Mon Sep 17 00:00:00 2001 From: Jonathan Coates Date: Sat, 8 Jul 2023 09:27:09 +0100 Subject: [PATCH] Also block the CGNAT range (100.64.0.0/10) --- .../core/apis/http/options/AddressPredicate.java | 16 +++++++++++++++- .../core/apis/http/options/AddressRuleTest.java | 11 +++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/projects/core/src/main/java/dan200/computercraft/core/apis/http/options/AddressPredicate.java b/projects/core/src/main/java/dan200/computercraft/core/apis/http/options/AddressPredicate.java index 1dfd09819..2ebed272c 100644 --- a/projects/core/src/main/java/dan200/computercraft/core/apis/http/options/AddressPredicate.java +++ b/projects/core/src/main/java/dan200/computercraft/core/apis/http/options/AddressPredicate.java @@ -6,6 +6,7 @@ import com.google.common.net.InetAddresses; +import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; import java.net.InetSocketAddress; @@ -113,7 +114,6 @@ final class PrivatePattern implements AddressPredicate { private static final Set additionalAddresses = Arrays.stream(new String[]{ // Block various cloud providers internal IPs. - "100.100.100.200", // Alibaba "192.0.0.192", // Oracle }).map(InetAddresses::forString).collect(Collectors.toUnmodifiableSet()); @@ -126,6 +126,7 @@ public boolean matches(InetAddress socketAddress) { || socketAddress.isSiteLocalAddress() // 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, fec0::/10 || socketAddress.isMulticastAddress() // 224.0.0.0/4, ff00::/8 || isUniqueLocalAddress(socketAddress) // fd00::/8 + || isCarrierGradeNatAddress(socketAddress) // 100.64.0.0/10 || additionalAddresses.contains(socketAddress); } @@ -141,6 +142,19 @@ private boolean isUniqueLocalAddress(InetAddress address) { // defined right now, so let's be conservative. return address instanceof Inet6Address && (address.getAddress()[0] & 0xff) == 0xfd; } + + /** + * Determine if an IP address lives within the CGNAT address range (100.64.0.0/10). + * + * @param address The IP address to test. + * @return Whether this address sits in the CGNAT address range. + * @see Carrier-grade NAT on Wikipedia + */ + private boolean isCarrierGradeNatAddress(InetAddress address) { + if (!(address instanceof Inet4Address)) return false; + var bytes = address.getAddress(); + return bytes[0] == 100 && ((bytes[1] & 0xFF) >= 64 && (bytes[1] & 0xFF) <= 127); + } } } diff --git a/projects/core/src/test/java/dan200/computercraft/core/apis/http/options/AddressRuleTest.java b/projects/core/src/test/java/dan200/computercraft/core/apis/http/options/AddressRuleTest.java index a7a7bf488..45f8c97e1 100644 --- a/projects/core/src/test/java/dan200/computercraft/core/apis/http/options/AddressRuleTest.java +++ b/projects/core/src/test/java/dan200/computercraft/core/apis/http/options/AddressRuleTest.java @@ -34,6 +34,8 @@ public void matchesPort() { "172.17.0.1", "192.168.1.114", "[0:0:0:0:0:ffff:c0a8:172]", "10.0.0.1", // Multicast "224.0.0.1", "ff02::1", + // CGNAT + "100.64.0.0", "100.127.255.255", // Cloud metadata providers "100.100.100.200", // Alibaba "192.0.0.192", // Oracle @@ -44,6 +46,15 @@ public void blocksLocalDomains(String domain) { assertEquals(apply(CoreConfig.httpRules, domain, 80).action, Action.DENY); } + @ParameterizedTest + @ValueSource(strings = { + // Ensure either side of the CGNAT range is allowed. + "100.63.255.255", "100.128.0.0" + }) + public void allowsNonLocalDomains(String domain) { + assertEquals(apply(CoreConfig.httpRules, domain, 80).action, Action.ALLOW); + } + private Options apply(Iterable rules, String host, int port) { return AddressRule.apply(rules, host, new InetSocketAddress(host, port)); }