Fixed name resolving for IP filtering

This commit is contained in:
M66B 2016-01-31 17:16:56 +01:00
parent 33c84c6f90
commit e6f47cd400
1 changed files with 42 additions and 20 deletions

View File

@ -826,14 +826,20 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
Log.i(TAG, "Start native log=" + log + " filter=" + filter); Log.i(TAG, "Start native log=" + log + " filter=" + filter);
// Prepare rules // Prepare rules
prepareUidAllowed(listAllowed); if (filter) {
prepareHostsBlocked(); prepareUidAllowed(listAllowed);
prepareUidIPFilters(); prepareHostsBlocked();
} else
unprepare();
if (log || filter) { if (log || filter) {
int prio = Integer.parseInt(prefs.getString("loglevel", Integer.toString(Log.INFO))); int prio = Integer.parseInt(prefs.getString("loglevel", Integer.toString(Log.INFO)));
jni_start(vpn.getFd(), prio); jni_start(vpn.getFd(), prio);
} }
// Native needs to be started for name resolving
if (filter)
prepareUidIPFilters();
} }
private void stopNative(ParcelFileDescriptor vpn, boolean clear) { private void stopNative(ParcelFileDescriptor vpn, boolean clear) {
@ -841,6 +847,12 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
jni_stop(vpn.getFd(), clear); jni_stop(vpn.getFd(), clear);
} }
private void unprepare() {
mapUidAllowed.clear();
mapHostsBlocked.clear();
mapUidIPFilters.clear();
}
private void prepareUidAllowed(List<Rule> listAllowed) { private void prepareUidAllowed(List<Rule> listAllowed) {
mapUidAllowed.clear(); mapUidAllowed.clear();
for (Rule rule : listAllowed) for (Rule rule : listAllowed)
@ -889,7 +901,7 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
} }
private void prepareUidIPFilters() { private void prepareUidIPFilters() {
mapUidIPFilters.clear(); Map<Integer, Map<Integer, Map<InetAddress, Boolean>>> map = new HashMap<>();
DatabaseHelper dh = new DatabaseHelper(SinkholeService.this); DatabaseHelper dh = new DatabaseHelper(SinkholeService.this);
Cursor cursor = dh.getAccess(); Cursor cursor = dh.getAccess();
@ -903,14 +915,14 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
int dport = cursor.isNull(colDPort) ? -1 : cursor.getInt(colDPort); int dport = cursor.isNull(colDPort) ? -1 : cursor.getInt(colDPort);
boolean block = (cursor.getInt(colBlock) > 0); boolean block = (cursor.getInt(colBlock) > 0);
if (!mapUidIPFilters.containsKey(uid)) if (!map.containsKey(uid))
mapUidIPFilters.put(uid, new HashMap()); map.put(uid, new HashMap());
if (!mapUidIPFilters.get(uid).containsKey(dport)) if (!map.get(uid).containsKey(dport))
mapUidIPFilters.get(uid).put(dport, new HashMap<InetAddress, Boolean>()); map.get(uid).put(dport, new HashMap<InetAddress, Boolean>());
try { try {
for (InetAddress iaddr : InetAddress.getAllByName(daddr)) { for (InetAddress iaddr : InetAddress.getAllByName(daddr)) {
mapUidIPFilters.get(uid).get(dport).put(iaddr, block); map.get(uid).get(dport).put(iaddr, block);
Log.i(TAG, "Set filter uid=" + uid + " " + iaddr + "/" + dport + "=" + block); Log.i(TAG, "Set filter uid=" + uid + " " + iaddr + "/" + dport + "=" + block);
} }
} catch (UnknownHostException ex) { } catch (UnknownHostException ex) {
@ -919,6 +931,10 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
} }
cursor.close(); cursor.close();
dh.close(); dh.close();
synchronized (mapUidIPFilters) {
mapUidIPFilters = map;
}
} }
private List<Rule> getAllowedRules(List<Rule> listRule) { private List<Rule> getAllowedRules(List<Rule> listRule) {
@ -1055,6 +1071,10 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
private boolean isAddressAllowed(Packet packet) { private boolean isAddressAllowed(Packet packet) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
// Allow name resolving
if (packet.uid == Process.myUid())
return true;
packet.allowed = false; packet.allowed = false;
if (packet.protocol == 6 /* TCP */ || packet.protocol == 17 /* UDP */) { if (packet.protocol == 6 /* TCP */ || packet.protocol == 17 /* UDP */) {
if (prefs.getBoolean("filter", false)) { if (prefs.getBoolean("filter", false)) {
@ -1062,18 +1082,20 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
packet.allowed = true; packet.allowed = true;
else { else {
boolean filtered = false; boolean filtered = false;
if (mapUidIPFilters.containsKey(packet.uid)) synchronized (mapUidIPFilters) {
try { if (mapUidIPFilters.containsKey(packet.uid))
InetAddress iaddr = InetAddress.getByName(packet.daddr); try {
Map<InetAddress, Boolean> map = mapUidIPFilters.get(packet.uid).get(packet.dport); InetAddress iaddr = InetAddress.getByName(packet.daddr);
if (map != null && map.containsKey(iaddr)) { Map<InetAddress, Boolean> map = mapUidIPFilters.get(packet.uid).get(packet.dport);
filtered = true; if (map != null && map.containsKey(iaddr)) {
packet.allowed = !mapUidIPFilters.get(packet.uid).get(packet.dport).get(iaddr); filtered = true;
Log.i(TAG, "Filtering uid=" + packet.uid + " " + iaddr + "/" + packet.dport + " allowed=" + packet.allowed); packet.allowed = !mapUidIPFilters.get(packet.uid).get(packet.dport).get(iaddr);
Log.i(TAG, "Filtering uid=" + packet.uid + " " + iaddr + "/" + packet.dport + " allowed=" + packet.allowed);
}
} catch (UnknownHostException ex) {
Log.w(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
} }
} catch (UnknownHostException ex) { }
Log.w(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
}
if (!filtered) if (!filtered)
packet.allowed = (mapUidAllowed.containsKey(packet.uid) && mapUidAllowed.get(packet.uid)); packet.allowed = (mapUidAllowed.containsKey(packet.uid) && mapUidAllowed.get(packet.uid));