mirror of https://github.com/M66B/NetGuard.git
Native quick restart, allow root, terminate not allowed session on start
This commit is contained in:
parent
8475dbdf9d
commit
1e75535836
|
@ -362,10 +362,15 @@ public class ActivitySettings extends AppCompatActivity implements SharedPrefere
|
|||
prefs.edit().putBoolean("show_system", manage).apply();
|
||||
SinkholeService.reload(null, "setting changed", this);
|
||||
|
||||
} else if ("tethering".equals(name))
|
||||
SinkholeService.reload(null, "setting changed", this);
|
||||
} else if ("tethering".equals(name)) {
|
||||
if (prefs.getBoolean("filter", false)) {
|
||||
// Requires a full stop to reconfigure the VPN
|
||||
SinkholeService.stop("tethering", this);
|
||||
SinkholeService.start("tethering", this);
|
||||
} else
|
||||
SinkholeService.reload(null, "setting changed", this);
|
||||
|
||||
else if ("log".equals(name)) {
|
||||
} else if ("log".equals(name)) {
|
||||
if (prefs.getBoolean(name, false) && !IAB.isPurchased(ActivityPro.SKU_LOG, this)) {
|
||||
prefs.edit().putBoolean(name, false).apply();
|
||||
((SwitchPreference) getPreferenceScreen().findPreference(name)).setChecked(false);
|
||||
|
|
|
@ -39,7 +39,7 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
public class IAB implements ServiceConnection {
|
||||
private static final String TAG = "Netguard.IAB";
|
||||
private static final String TAG = "NetGuard.IAB";
|
||||
|
||||
private Context context;
|
||||
private Delegate delegate;
|
||||
|
|
|
@ -325,7 +325,7 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
|
|||
if (vpn == null)
|
||||
throw new IllegalStateException("VPN start failed");
|
||||
|
||||
startNative(listAllowed);
|
||||
startNative(vpn, listAllowed);
|
||||
|
||||
removeWarningNotifications();
|
||||
updateEnforcingNotification(listAllowed.size(), listRule.size());
|
||||
|
@ -333,6 +333,8 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
|
|||
}
|
||||
|
||||
private void reload() {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(SinkholeService.this);
|
||||
|
||||
if (state != State.enforcing) {
|
||||
if (state != State.none) {
|
||||
Log.d(TAG, "Stop foreground state=" + state.toString());
|
||||
|
@ -343,28 +345,44 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
|
|||
Log.d(TAG, "Start foreground state=" + state.toString());
|
||||
}
|
||||
|
||||
// Seamless handover
|
||||
ParcelFileDescriptor prev = vpn;
|
||||
List<Rule> listRule = Rule.getRules(true, TAG, SinkholeService.this);
|
||||
List<Rule> listAllowed = getAllowedRules(listRule);
|
||||
|
||||
vpn = startVPN(listAllowed);
|
||||
if (prev != null && vpn == null) {
|
||||
Log.w(TAG, "Handover failed");
|
||||
stopVPN(prev);
|
||||
prev = null;
|
||||
vpn = startVPN(listAllowed);
|
||||
if (prefs.getBoolean("filter", false)) {
|
||||
Log.i(TAG, "Native restart");
|
||||
|
||||
if (vpn != null)
|
||||
jni_stop(vpn.getFd(), false);
|
||||
|
||||
if (vpn == null)
|
||||
throw new IllegalStateException("Handover failed");
|
||||
vpn = startVPN(listAllowed);
|
||||
if (vpn == null)
|
||||
throw new IllegalStateException("VPN start failed");
|
||||
|
||||
startNative(vpn, listAllowed);
|
||||
|
||||
} else {
|
||||
Log.i(TAG, "VPN restart");
|
||||
|
||||
// Attempt seamless handover
|
||||
ParcelFileDescriptor prev = vpn;
|
||||
vpn = startVPN(listAllowed);
|
||||
if (prev != null && vpn == null) {
|
||||
Log.w(TAG, "Handover failed");
|
||||
stopVPN(prev);
|
||||
prev = null;
|
||||
vpn = startVPN(listAllowed);
|
||||
if (vpn == null)
|
||||
throw new IllegalStateException("Handover failed");
|
||||
}
|
||||
|
||||
if (prev != null) {
|
||||
jni_stop(prev.getFd(), false);
|
||||
stopVPN(prev);
|
||||
}
|
||||
startNative(vpn, listAllowed);
|
||||
}
|
||||
|
||||
// TODO drain old VPN
|
||||
jni_stop(vpn.getFd(), false);
|
||||
startNative(listAllowed);
|
||||
|
||||
if (prev != null)
|
||||
stopVPN(prev);
|
||||
|
||||
updateEnforcingNotification(listAllowed.size(), listRule.size());
|
||||
}
|
||||
|
||||
|
@ -701,7 +719,7 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
|
|||
}
|
||||
}
|
||||
|
||||
private void startNative(List<Rule> listAllowed) {
|
||||
private void startNative(ParcelFileDescriptor vpn, List<Rule> listAllowed) {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(SinkholeService.this);
|
||||
boolean log = prefs.getBoolean("log", false);
|
||||
boolean filter = prefs.getBoolean("filter", false);
|
||||
|
@ -779,9 +797,10 @@ public class SinkholeService extends VpnService implements SharedPreferences.OnS
|
|||
}
|
||||
|
||||
private int[] getAllowedUids(List<Rule> listAllowed) {
|
||||
int[] uid = new int[listAllowed.size()];
|
||||
int[] uid = new int[listAllowed.size() + 1];
|
||||
uid[0] = 0; // Allow root (DNS, etc)
|
||||
for (int i = 0; i < listAllowed.size(); i++)
|
||||
uid[i] = listAllowed.get(i).info.applicationInfo.uid;
|
||||
uid[i + 1] = listAllowed.get(i).info.applicationInfo.uid;
|
||||
return uid;
|
||||
}
|
||||
|
||||
|
|
|
@ -150,6 +150,9 @@ Java_eu_faircode_netguard_SinkholeService_jni_1start(
|
|||
for (int i = 0; i < args->ucount; i++)
|
||||
log_android(ANDROID_LOG_DEBUG, "Allowed uid %d", args->uids[i]);
|
||||
|
||||
// Terminate sessions not allowed anymore
|
||||
check_allowed(args);
|
||||
|
||||
// Start native thread
|
||||
int err = pthread_create(&thread_id, NULL, handle_events, (void *) args);
|
||||
if (err == 0)
|
||||
|
@ -222,6 +225,38 @@ Java_eu_faircode_netguard_SinkholeService_jni_1pcap(JNIEnv *env, jclass type, js
|
|||
|
||||
// Private functions
|
||||
|
||||
void check_allowed(const struct arguments *args) {
|
||||
struct udp_session *u = udp_session;
|
||||
while (u != NULL) {
|
||||
int found = 0;
|
||||
for (int i = 0; i < args->ucount; i++)
|
||||
if (u->uid == args->uids[i]) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
if (!found) {
|
||||
u->error = 1;
|
||||
log_android(ANDROID_LOG_WARN, "UDP terminate uid %d", u->uid);
|
||||
}
|
||||
u = u->next;
|
||||
}
|
||||
|
||||
struct tcp_session *t = tcp_session;
|
||||
while (t != NULL) {
|
||||
int found = 0;
|
||||
for (int i = 0; i < args->ucount; i++)
|
||||
if (t->uid == args->uids[i]) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
if (!found) {
|
||||
t->state = TCP_TIME_WAIT;
|
||||
log_android(ANDROID_LOG_WARN, "TCP terminate uid %d", t->uid);
|
||||
}
|
||||
t = t->next;
|
||||
}
|
||||
}
|
||||
|
||||
void clear_sessions() {
|
||||
struct udp_session *u = udp_session;
|
||||
while (u != NULL) {
|
||||
|
@ -300,14 +335,15 @@ void *handle_events(void *a) {
|
|||
if (ready < 0) {
|
||||
if (errno == EINTR) {
|
||||
if (stopping && signaled) { ;
|
||||
log_android(ANDROID_LOG_WARN, "pselect signaled");
|
||||
log_android(ANDROID_LOG_WARN, "pselect signaled tun %d", args->tun);
|
||||
break;
|
||||
} else {
|
||||
log_android(ANDROID_LOG_DEBUG, "pselect interrupted");
|
||||
log_android(ANDROID_LOG_DEBUG, "pselect interrupted %d", args->tun);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
log_android(ANDROID_LOG_ERROR, "pselect error %d: %s", errno, strerror(errno));
|
||||
log_android(ANDROID_LOG_ERROR, "pselect tun %d error %d: %s",
|
||||
args->tun, errno, strerror(errno));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -389,7 +425,7 @@ void *handle_events(void *a) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void report_exit(struct arguments *args) {
|
||||
void report_exit(const struct arguments *args) {
|
||||
jclass cls = (*args->env)->GetObjectClass(args->env, args->instance);
|
||||
jmethodID mid = jniGetMethodID(args->env, cls, "selectExit", "(Z)V");
|
||||
|
||||
|
@ -411,7 +447,8 @@ void check_sessions(const struct arguments *args) {
|
|||
log_android(ANDROID_LOG_WARN, "UDP timeout");
|
||||
|
||||
if (close(u->socket))
|
||||
log_android(ANDROID_LOG_ERROR, "UDP close error %d: %s", errno, strerror(errno));
|
||||
log_android(ANDROID_LOG_ERROR, "UDP close %d error %d: %s",
|
||||
u->socket, errno, strerror(errno));
|
||||
|
||||
if (ul == NULL)
|
||||
udp_session = u->next;
|
||||
|
@ -459,7 +496,8 @@ void check_sessions(const struct arguments *args) {
|
|||
source, ntohs(t->source), dest, ntohs(t->dest), t->socket);
|
||||
|
||||
if (close(t->socket))
|
||||
log_android(ANDROID_LOG_ERROR, "close error %d: %s", errno, strerror(errno));
|
||||
log_android(ANDROID_LOG_ERROR, "close %d error %d: %s",
|
||||
t->socket, errno, strerror(errno));
|
||||
|
||||
t->time = time(NULL);
|
||||
t->state = TCP_CLOSE;
|
||||
|
@ -988,6 +1026,8 @@ jboolean handle_udp(const struct arguments *args, const uint8_t *buffer, size_t
|
|||
if (check_dns(args, cur, buffer, length))
|
||||
return 0;
|
||||
|
||||
// TODO check DHCP (tethering)
|
||||
|
||||
log_android(ANDROID_LOG_INFO, "UDP forward from tun %s/%u to %s/%u data %d",
|
||||
source, ntohs(udphdr->source), dest, ntohs(udphdr->dest), datalen);
|
||||
|
||||
|
|
|
@ -123,13 +123,15 @@ typedef struct __attribute__((__packed__)) dns_response {
|
|||
|
||||
#define DNS_TTL 3600 // seconds
|
||||
|
||||
void check_allowed(const struct arguments *args);
|
||||
|
||||
void clear_sessions();
|
||||
|
||||
void handle_signal(int sig, siginfo_t *info, void *context);
|
||||
|
||||
void *handle_events(void *a);
|
||||
|
||||
void report_exit(struct arguments *args);
|
||||
void report_exit(const struct arguments *args);
|
||||
|
||||
void check_sessions(const struct arguments *args);
|
||||
|
||||
|
|
Loading…
Reference in New Issue