Skip to content

Commit

Permalink
Proxy module: support for IPv6 (#92).
Browse files Browse the repository at this point in the history
It should work now.

If you want restrict proxy access to localhost you should change the `dm4.proxy.net.filter` setting in `./pom.xml` to `::1/128`.

See ticket 92.
  • Loading branch information
jri committed Sep 14, 2011
1 parent 5f2ec45 commit 507da21
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 34 deletions.
Expand Up @@ -7,7 +7,12 @@
import java.io.InputStream;
import java.io.UnsupportedEncodingException;

import java.math.BigInteger;

import java.net.FileNameMap;
import java.net.InetAddress;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.URLConnection;
import java.net.URLEncoder;

Expand All @@ -32,6 +37,14 @@ public static String stripHTML(String html) {
return html.replaceAll("<.*?>", ""); // *? is the reluctant version of the * quantifier (which is greedy)
}

public static String times(String str, int times) {
StringBuilder sb = new StringBuilder(times * str.length());
for (int i = 0; i < times; i++) {
sb.append(str);
}
return sb.toString();
}



// === Files ===
Expand Down Expand Up @@ -122,27 +135,53 @@ public static String encodeURIComponent(String uriComp) {
// === Networking ===

/**
* @param inetAddress e.g. "172.68.8.12"
* @param range e.g. "172.68.8.0/24"
* @param inetAddress IPv4 or IPv6 address or a machine name, e.g. "172.68.8.12"
* @param range IPv4 or IPv6 address range in CIDR notation, e.g. "172.68.8.0/24"
*/
public static boolean isInRange(String inetAddress, String range) {
String[] r = range.split("/");
int networkAddr = inetAddress(r[0]);
int networkMask = networkMask(Integer.parseInt(r[1]));
//
return ((inetAddress(inetAddress) ^ networkAddr) & networkMask) == 0;
try {
String[] r = range.split("/");
BigInteger networkAddr = inetAddress(r[0]);
int maskNumber = Integer.parseInt(r[1]);
InetAddress addr = InetAddress.getByName(inetAddress);
BigInteger networkMask = networkMask(addr, maskNumber);
//
return inetAddress(addr).xor(networkAddr).and(networkMask).equals(BigInteger.ZERO);
} catch (Exception e) {
throw new RuntimeException("Checking IP range failed (inetAddress=\"" + inetAddress +
"\", range=\"" + range + "\"", e);
}
}

// ---

public static BigInteger inetAddress(String inetAddress) {
try {
return inetAddress(InetAddress.getByName(inetAddress));
} catch (Exception e) {
throw new RuntimeException("Parsing inet address \"" + inetAddress + "\" failed", e);
}
}

public static int inetAddress(String inetAddress) {
String[] a = inetAddress.split("\\.");
return (Integer.parseInt(a[0]) << 24) +
(Integer.parseInt(a[1]) << 16) +
(Integer.parseInt(a[2]) << 8) +
Integer.parseInt(a[3]);
public static BigInteger inetAddress(InetAddress inetAddress) {
return new BigInteger(1, inetAddress.getAddress()); // signum=1 (positive)
}

// ---

public static BigInteger networkMask(InetAddress addr, int maskNumber) {
if (addr instanceof Inet4Address) {
return networkMask(maskNumber, 32);
} else if (addr instanceof Inet6Address) {
return networkMask(maskNumber, 128);
} else {
throw new RuntimeException("Unexpected InetAddress object: " + addr.getClass().getName());
}
}

public static int networkMask(int maskNr) {
return -1 << 32 - maskNr;
public static BigInteger networkMask(int maskNumber, int size) {
String networkMask = times("1", maskNumber) + times("0", size - maskNumber);
return new BigInteger(networkMask, 2); // radix=2 (binary)
}


Expand Down
Expand Up @@ -2,6 +2,8 @@

import de.deepamehta.core.util.JavaUtils;

import java.math.BigInteger;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
Expand Down Expand Up @@ -29,7 +31,7 @@ public void stripHTMLwithLinebreaks() {
// ---

@Test
public void isInRange() {
public void isInRangeIPv4() {
assertTrue(JavaUtils.isInRange("172.68.8.0", "172.68.8.0/24"));
assertTrue(JavaUtils.isInRange("172.68.8.12", "172.68.8.0/24"));
assertTrue(JavaUtils.isInRange("172.68.8.255", "172.68.8.0/24"));
Expand All @@ -42,24 +44,73 @@ public void isInRange() {
}

@Test
public void inetAddress() {
assertEquals( 0, JavaUtils.inetAddress("0.0.0.0"));
assertEquals( 1, JavaUtils.inetAddress("0.0.0.1"));
assertEquals(256, JavaUtils.inetAddress("0.0.1.0"));
assertEquals((int) Math.pow(2, 24) - 1, JavaUtils.inetAddress("0.255.255.255"));
assertEquals((int) (Math.pow(2, 31) - 1), JavaUtils.inetAddress("127.255.255.255"));
assertEquals((int) -Math.pow(2, 31), JavaUtils.inetAddress("128.0.0.0"));
assertEquals(-1, JavaUtils.inetAddress("255.255.255.255"));
public void inetAddressIPv4() {
assertEquals(BigInteger.ZERO, JavaUtils.inetAddress("0.0.0.0"));
assertEquals(BigInteger.ONE, JavaUtils.inetAddress("0.0.0.1"));
assertEquals(bigInt(256), JavaUtils.inetAddress("0.0.1.0"));
assertEquals(bigInt(Math.pow(2, 24) - 1), JavaUtils.inetAddress("0.255.255.255"));
assertEquals(bigInt(Math.pow(2, 31) - 1), JavaUtils.inetAddress("127.255.255.255"));
assertEquals(bigInt(Math.pow(2, 31)), JavaUtils.inetAddress("128.0.0.0"));
assertEquals(bigInt(Math.pow(2, 32) - 1), JavaUtils.inetAddress("255.255.255.255"));
}

@Test
public void networkMaskIPv4() {
assertEquals(JavaUtils.inetAddress("0.0.0.0"), JavaUtils.networkMask(0, 32));
assertEquals(JavaUtils.inetAddress("128.0.0.0"), JavaUtils.networkMask(1, 32));
assertEquals(JavaUtils.inetAddress("255.0.0.0"), JavaUtils.networkMask(8, 32));
assertEquals(JavaUtils.inetAddress("255.255.0.0"), JavaUtils.networkMask(16, 32));
assertEquals(JavaUtils.inetAddress("255.255.255.0"), JavaUtils.networkMask(24, 32));
assertEquals(JavaUtils.inetAddress("255.255.255.192"), JavaUtils.networkMask(26, 32));
assertEquals(JavaUtils.inetAddress("255.255.255.255"), JavaUtils.networkMask(32, 32));
}

// ---

@Test
public void isInRangeIPv6() {
assertTrue(JavaUtils.isInRange("::3afe:7a0:c800", "::3afe:7a0:c800/120"));
assertTrue(JavaUtils.isInRange("::3afe:7a0:c880", "::3afe:7a0:c800/120"));
assertTrue(JavaUtils.isInRange("::3afe:7a0:c8ff", "::3afe:7a0:c800/120"));
assertTrue(JavaUtils.isInRange("::3afe:7a0:c800", "::3afe:7a0:c800/121"));
assertTrue(JavaUtils.isInRange("::3afe:7a0:c87f", "::3afe:7a0:c800/121"));
assertFalse(JavaUtils.isInRange("::3afe:7a0:c880", "::3afe:7a0:c800/121"));
assertFalse(JavaUtils.isInRange("::3afe:7a0:c8ff", "::3afe:7a0:c800/121"));
}

@Test
public void inetAddressIPv6() {
assertEquals(BigInteger.ZERO, JavaUtils.inetAddress("::"));
assertEquals(BigInteger.ONE, JavaUtils.inetAddress("::1"));
assertEquals(bigInt(256), JavaUtils.inetAddress("::100"));
assertEquals(bigInt(Math.pow(2, 24) - 1), JavaUtils.inetAddress("::ff:ffff"));
assertEquals(bigInt(Math.pow(2, 31) - 1), JavaUtils.inetAddress("::7fff:ffff"));
assertEquals(bigInt(Math.pow(2, 31)), JavaUtils.inetAddress("::8000:0000"));
assertEquals(bigInt(Math.pow(2, 32) - 1), JavaUtils.inetAddress("::ffff:ffff"));
assertEquals(bigInt(Math.pow(2, 32)), JavaUtils.inetAddress("::1:0000:0000"));
assertEquals(bigInt(Math.pow(2, 63) - 1), JavaUtils.inetAddress("::7fff:ffff:ffff:ffff"));
}

@Test
public void networkMask() {
assertEquals(JavaUtils.inetAddress("255.255.255.255"), JavaUtils.networkMask(0));
assertEquals(JavaUtils.inetAddress("128.0.0.0"), JavaUtils.networkMask(1));
assertEquals(JavaUtils.inetAddress("255.0.0.0"), JavaUtils.networkMask(8));
assertEquals(JavaUtils.inetAddress("255.255.0.0"), JavaUtils.networkMask(16));
assertEquals(JavaUtils.inetAddress("255.255.255.0"), JavaUtils.networkMask(24));
assertEquals(JavaUtils.inetAddress("255.255.255.192"), JavaUtils.networkMask(26));
assertEquals(JavaUtils.inetAddress("255.255.255.255"), JavaUtils.networkMask(32));
public void networkMaskIPv6() {
assertEquals(JavaUtils.inetAddress("::"), JavaUtils.networkMask(0, 128));
assertEquals(JavaUtils.inetAddress("8000::"), JavaUtils.networkMask(1, 128));
assertEquals(JavaUtils.inetAddress("ff00::"), JavaUtils.networkMask(8, 128));
assertEquals(JavaUtils.inetAddress("ffff::"), JavaUtils.networkMask(16, 128));
assertEquals(JavaUtils.inetAddress("ffff:ff00::"), JavaUtils.networkMask(24, 128));
assertEquals(JavaUtils.inetAddress("ffff:ffc0::"), JavaUtils.networkMask(26, 128));
assertEquals(JavaUtils.inetAddress("ffff:ffff::"), JavaUtils.networkMask(32, 128));
assertEquals(JavaUtils.inetAddress("ffff:ffff:ffff:ffff::"), JavaUtils.networkMask(64, 128));
assertEquals(JavaUtils.inetAddress("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"), JavaUtils.networkMask(128, 128));
}

// ---

private BigInteger bigInt(double val) {
return bigInt((long) val);
}

private BigInteger bigInt(long val) {
return new BigInteger(Long.toString(val));
}
}
Expand Up @@ -101,8 +101,9 @@ private void checkRemoteAccess(HttpServletRequest request) {
String remoteAddr = request.getRemoteAddr();
boolean isInRange = JavaUtils.isInRange(remoteAddr, REMOTE_ACCESS_FILTER);
//
logger.info("Checking remote access to \"" + request.getRequestURL() + "\"\n remote address=\"" +
remoteAddr + "\", range=\"" + REMOTE_ACCESS_FILTER + "\" => " + (isInRange ? "ALLOWED" : "FORBIDDEN"));
logger.info("Checking remote access to \"" + request.getRequestURL() + "\"\n dm4.proxy.net.filter=\"" +
REMOTE_ACCESS_FILTER + "\", remote address=\"" + remoteAddr + "\" => " +
(isInRange ? "ALLOWED" : "FORBIDDEN"));
//
if (!isInRange) {
throw new WebApplicationException(Status.FORBIDDEN);
Expand Down

0 comments on commit 507da21

Please sign in to comment.