diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index bb289c7..d750e5a 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -17,6 +17,9 @@
+
= Build.VERSION_CODES.TIRAMISU) {
+ excludeLocalRoutes(builder);
+ }
+
disallowApp(builder, "com.google.android.projection.gearhead");
disallowApp(builder, "com.google.android.apps.chromecast.app");
disallowApp(builder, "com.google.android.apps.messaging");
@@ -95,6 +109,56 @@ private int createTun(String ip, int prefixLength, int mtu, String dns, String[]
}
}
+ @RequiresApi(api = Build.VERSION_CODES.TIRAMISU)
+ private void excludeLocalRoutes(VpnService.Builder builder) {
+ Log.i(LOGTAG, "excludeLocalRoutes: checking local routes for exclusion (API 33+)");
+
+ ConnectivityManager cm = vpnService.getSystemService(ConnectivityManager.class);
+ if (cm == null) {
+ Log.w(LOGTAG, "excludeLocalRoutes: ConnectivityManager is null, skipping");
+ return;
+ }
+
+ Network activeNetwork = cm.getActiveNetwork();
+ if (activeNetwork == null) {
+ Log.w(LOGTAG, "excludeLocalRoutes: no active network found, skipping");
+ return;
+ }
+
+ LinkProperties lp = cm.getLinkProperties(activeNetwork);
+ if (lp == null) {
+ Log.w(LOGTAG, "excludeLocalRoutes: no link properties for active network, skipping");
+ return;
+ }
+
+ Log.i(LOGTAG, "excludeLocalRoutes: active network interface=" + lp.getInterfaceName() + " routes=" + lp.getRoutes().size());
+
+ List excluded = new ArrayList<>();
+ for (RouteInfo routeInfo : lp.getRoutes()) {
+ IpPrefix dest = routeInfo.getDestination();
+ if (dest.getPrefixLength() == 0) {
+ Log.d(LOGTAG, "excludeLocalRoutes: skipping default route " + dest);
+ continue;
+ }
+
+ try {
+ builder.excludeRoute(dest);
+ excluded.add(dest.toString());
+ Log.i(LOGTAG, "excludeLocalRoutes: excluded " + dest + " (iface=" + routeInfo.getInterface() + ")");
+ } catch (Exception e) {
+ Log.e(LOGTAG, "excludeLocalRoutes: failed to exclude " + dest + ": " + e.getMessage());
+ }
+ }
+
+ Log.i(LOGTAG, "excludeLocalRoutes: total excluded=" + excluded.size() + " routes=" + excluded);
+ if (!excluded.isEmpty()) {
+ String msg = "Excluding " + excluded.size() + " local routes: " + String.join(", ", excluded);
+ new Handler(Looper.getMainLooper()).post(() ->
+ Toast.makeText(vpnService, msg, Toast.LENGTH_LONG).show()
+ );
+ }
+ }
+
private void prepareDnsSetting(VpnService.Builder builder, String dns) {
if(dns == null) {
return;