Auto exclude IP ranges

This commit is contained in:
M66B 2016-03-29 18:30:04 +02:00
parent b9bed43477
commit 6f9fed8022
2 changed files with 84 additions and 36 deletions

View File

@ -43,7 +43,7 @@ public class IPUtil {
while (to >= from) {
byte prefix = 32;
while (prefix > 0) {
long mask = (0xFFFFFFFF00000000L >> (prefix - 1)) % 0x0100000000L;
long mask = prefix2mask(prefix - 1);
if ((from & mask) != from)
break;
prefix--;
@ -64,6 +64,10 @@ public class IPUtil {
return listResult;
}
private static long prefix2mask(int bits) {
return (0xFFFFFFFF00000000L >> bits) & 0xFFFFFFFFL;
}
private static long inet2long(InetAddress addr) {
long result = 0;
for (byte b : addr.getAddress())
@ -71,20 +75,28 @@ public class IPUtil {
return result;
}
private static InetAddress long2inet(long addr) throws UnknownHostException {
byte[] b = new byte[4];
for (int i = b.length - 1; i >= 0; i--) {
b[i] = (byte) (addr & 0xFF);
addr = addr >> 8;
private static InetAddress long2inet(long addr) {
try {
byte[] b = new byte[4];
for (int i = b.length - 1; i >= 0; i--) {
b[i] = (byte) (addr & 0xFF);
addr = addr >> 8;
}
return InetAddress.getByAddress(b);
} catch (UnknownHostException ignore) {
return null;
}
return InetAddress.getByAddress(b);
}
public static String minus1(String addr) throws UnknownHostException {
return long2inet(inet2long(InetAddress.getByName(addr)) - 1).getHostAddress();
public static InetAddress minus1(InetAddress addr) {
return long2inet(inet2long(addr) - 1);
}
public static class CIDR {
public static InetAddress plus1(InetAddress addr) {
return long2inet(inet2long(addr) + 1);
}
public static class CIDR implements Comparable<CIDR> {
public InetAddress address;
public int prefix;
@ -93,9 +105,33 @@ public class IPUtil {
this.prefix = prefix;
}
public CIDR(String ip, int prefix) {
try {
this.address = InetAddress.getByName(ip);
this.prefix = prefix;
} catch (UnknownHostException ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
}
}
public InetAddress getStart() {
return long2inet(inet2long(this.address) & prefix2mask(this.prefix));
}
public InetAddress getEnd() {
return long2inet((inet2long(this.address) & prefix2mask(this.prefix)) + (1L << (32 - this.prefix)) - 1);
}
@Override
public String toString() {
return address.getHostAddress() + "/" + prefix;
return address.getHostAddress() + "/" + prefix + "=" + getStart().getHostAddress() + "..." + getEnd().getHostAddress();
}
@Override
public int compareTo(CIDR other) {
Long lcidr = IPUtil.inet2long(this.address);
Long lother = IPUtil.inet2long(other.address);
return lcidr.compareTo(lother);
}
}
}

View File

@ -31,6 +31,7 @@ import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Canvas;
@ -85,6 +86,7 @@ import java.net.UnknownHostException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
@ -967,37 +969,47 @@ public class ServiceSinkhole extends VpnService implements SharedPreferences.OnS
builder.addDnsServer(dns);
}
// Exclude IP ranges
List<IPUtil.CIDR> listExclude = new ArrayList<>();
listExclude.add(new IPUtil.CIDR("127.0.0.0", 8)); // localhost
if (tethering) {
// USB Tethering 192.168.42.x
// Wi-Fi Tethering 192.168.43.x
// https://en.wikipedia.org/wiki/IPv4#Special-use_addresses
listExclude.add(new IPUtil.CIDR("192.168.42.0", 23));
}
Configuration config = getResources().getConfiguration();
if (config.mcc == -1 && config.mnc == -1) {
// T-Mobile Wi-Fi calling
listExclude.add(new IPUtil.CIDR("66.94.2.0", 24));
listExclude.add(new IPUtil.CIDR("66.94.6.0", 23));
listExclude.add(new IPUtil.CIDR("66.94.8.0", 22));
listExclude.add(new IPUtil.CIDR("208.54.0.0", 16));
}
listExclude.add(new IPUtil.CIDR("224.0.0.0", 3)); // broadcast
try {
for (IPUtil.CIDR cidr : IPUtil.toCIDR("0.0.0.0", IPUtil.minus1("127.0.0.0")))
builder.addRoute(cidr.address, cidr.prefix);
Collections.sort(listExclude);
// Skip 127.0.0.0/8 - localhost
for (IPUtil.CIDR cidr : IPUtil.toCIDR("128.0.0.0", IPUtil.minus1("192.168.42.0")))
builder.addRoute(cidr.address, cidr.prefix);
// Skip 192.168.42 - 192.168.43 - tethering
for (IPUtil.CIDR cidr : IPUtil.toCIDR("192.168.44.0", IPUtil.minus1("224.0.0.0")))
builder.addRoute(cidr.address, cidr.prefix);
} catch (UnknownHostException ex) {
Log.w(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
try {
InetAddress start = InetAddress.getByName("0.0.0.0");
for (IPUtil.CIDR exclude : listExclude) {
Log.i(TAG, "Exclude " + exclude.getStart().getHostAddress() + "..." + exclude.getEnd().getHostAddress());
for (IPUtil.CIDR include : IPUtil.toCIDR(start, IPUtil.minus1(exclude.getStart())))
try {
builder.addRoute(include.address, include.prefix);
} catch (Throwable ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
}
start = IPUtil.plus1(exclude.getEnd());
}
try {
for (IPUtil.CIDR cidr : IPUtil.toCIDR("224.0.0.0", "255.255.255.255"))
builder.addRoute(cidr.address, cidr.prefix);
} catch (Throwable ex) {
// Some Android versions do not accept broadcast addresses
Log.w(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
}
} else
builder.addRoute("0.0.0.0", 0);
for (IPUtil.CIDR include : IPUtil.toCIDR("224.0.0.0", "255.255.255.255"))
try {
builder.addRoute(include.address, include.prefix);
} catch (Throwable ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
}
} catch (UnknownHostException ex) {
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
}
builder.addRoute("0:0:0:0:0:0:0:0", 0);