Skip to content

Commit

Permalink
Merge pull request #157 from Graylog2/issue-156
Browse files Browse the repository at this point in the history
Support IPv6 in in_private_net function, reduce noise on errors
  • Loading branch information
mpfz0r authored Oct 14, 2020
2 parents 77750bb + 91d4f64 commit 53b8a33
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.graylog.plugins.pipelineprocessor.ast.functions.FunctionDescriptor;
import org.graylog.plugins.pipelineprocessor.ast.functions.ParameterDescriptor;
import org.graylog.plugins.threatintel.tools.PrivateNet;
import org.graylog2.shared.utilities.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -38,7 +39,7 @@ public class PrivateNetLookupFunction extends AbstractFunction<Boolean> {
public static final String NAME = "in_private_net";
private static final String VALUE = "ip_address";

private final ParameterDescriptor<String, String> valueParam = ParameterDescriptor.string(VALUE).description("The IPv4 address to look up.").build();
private final ParameterDescriptor<String, String> valueParam = ParameterDescriptor.string(VALUE).description("The IP address to look up.").build();

protected Timer lookupTime;

Expand All @@ -64,7 +65,7 @@ public Boolean evaluate(FunctionArgs args, EvaluationContext context) {

return result;
} catch (Exception e) {
LOG.error("Could not run private net lookup for IP [{}].", ip, e);
LOG.error("Could not run private net lookup for IP [{}]: {}", ip, ExceptionUtils.getRootCauseMessage(e));
return null;
}
}
Expand All @@ -74,7 +75,7 @@ public Boolean evaluate(FunctionArgs args, EvaluationContext context) {
public FunctionDescriptor<Boolean> descriptor() {
return FunctionDescriptor.<Boolean>builder()
.name(NAME)
.description("Check if an IPv4 address is in a private network as defined in RFC 1918. (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)")
.description("Check if an IP address is in a private network as defined in RFC 1918 (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) or RFC 4193 (fc00::/7)")
.params(valueParam)
.returnType(Boolean.class)
.build();
Expand Down
38 changes: 26 additions & 12 deletions src/main/java/org/graylog/plugins/threatintel/tools/PrivateNet.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,40 @@
package org.graylog.plugins.threatintel.tools;

import com.google.common.net.InetAddresses;
import org.apache.commons.net.util.SubnetUtils;
import org.graylog2.utilities.IpSubnet;

import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;

@SuppressWarnings("UnstableApiUsage")
public class PrivateNet {

public static final SubnetUtils.SubnetInfo TEN = new SubnetUtils("10.0.0.0/8").getInfo();
public static final SubnetUtils.SubnetInfo ONE_HUNDRED_SEVENTY_TWO = new SubnetUtils("172.16.0.0/12").getInfo();
public static final SubnetUtils.SubnetInfo ONE_HUNDRED_NINETY_TWO = new SubnetUtils("192.168.0.0/16").getInfo();
private static IpSubnet UNIQUE_LOCAL_ADDR_MASK = null;
static {
try {
// RFC 4193: https://tools.ietf.org/html/rfc4193#section-3.1
UNIQUE_LOCAL_ADDR_MASK = new IpSubnet("FC00::/7");
} catch (UnknownHostException ignored) {
}

/**
* Checks if an IPv4 address is part of a private network as defined in RFC 1918.
}
/**
* Checks if an IP address is part of a private network as defined in RFC 1918 (for IPv4) and RFC 4193 (for IPv6).
*
*
* @param ip The IPv4 address to check
* @return
* @param ip The IP address to check
* @return true if IP address is in a private subnet, false if not or unknown
*/
public static boolean isInPrivateAddressSpace(String ip) {
if(!InetAddresses.isInetAddress(ip)) {
return false;
InetAddress inetAddress = InetAddresses.forString(ip);
if (inetAddress instanceof Inet6Address) {
// Inet6Address#isSiteLocalAddress is wrong: it only checks for FEC0:: prefixes, which is deprecated in RFC 3879
// instead we need to check for unique local addresses, which are in FC00::/7 (in practice assigned are in FD00::/8,
// but the RFC allows others in the future)
return UNIQUE_LOCAL_ADDR_MASK.contains(inetAddress);
}

return ONE_HUNDRED_SEVENTY_TWO.isInRange(ip) || TEN.isInRange(ip) || ONE_HUNDRED_NINETY_TWO.isInRange(ip);
return inetAddress.isSiteLocalAddress();
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ public void testIsInPrivateAddressSpace() throws Exception {
assertTrue(PrivateNet.isInPrivateAddressSpace("172.16.20.50"));
assertTrue(PrivateNet.isInPrivateAddressSpace("192.168.1.1"));
assertFalse(PrivateNet.isInPrivateAddressSpace("99.42.44.219"));
assertFalse(PrivateNet.isInPrivateAddressSpace("ff02:0:0:0:0:0:0:fb"));
assertTrue(PrivateNet.isInPrivateAddressSpace("fd80:0:0:0:0:0:0:fb"));
assertThrows(IllegalArgumentException.class, () -> PrivateNet.isInPrivateAddressSpace("this is not an IP address"));
}

}

0 comments on commit 53b8a33

Please sign in to comment.