diff --git a/apk/controller/app/src/main/java/org/iiab/controller/MainActivity.java b/apk/controller/app/src/main/java/org/iiab/controller/MainActivity.java
index 40dd13a..8316a19 100644
--- a/apk/controller/app/src/main/java/org/iiab/controller/MainActivity.java
+++ b/apk/controller/app/src/main/java/org/iiab/controller/MainActivity.java
@@ -78,6 +78,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
private CheckBox checkbox_udp_in_tcp;
private CheckBox checkbox_remote_dns;
private CheckBox checkbox_global;
+ private CheckBox checkbox_maintenance;
private CheckBox checkbox_ipv4;
private CheckBox checkbox_ipv6;
private Button button_apps;
@@ -170,6 +171,8 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
checkbox_global = findViewById(R.id.global);
checkbox_udp_in_tcp = findViewById(R.id.udp_in_tcp);
checkbox_remote_dns = findViewById(R.id.remote_dns);
+ checkbox_maintenance = findViewById(R.id.checkbox_maintenance);
+ checkbox_maintenance.setOnClickListener(this);
button_apps = findViewById(R.id.apps);
button_save = findViewById(R.id.save);
button_control = findViewById(R.id.control);
@@ -196,7 +199,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
btnClearLog.setOnClickListener(this);
btnCopyLog.setOnClickListener(this);
themeToggle.setOnClickListener(v -> toggleTheme());
- configLabel.setOnClickListener(v -> toggleVisibility(configLayout, configLabel, getString(R.string.configuration_label)));
+ configLabel.setOnClickListener(v -> handleConfigToggle());
advConfigLabel.setOnClickListener(v -> toggleVisibility(advancedConfig, advConfigLabel, getString(R.string.advanced_settings_label)));
logLabel.setOnClickListener(v -> handleLogToggle());
checkbox_udp_in_tcp.setOnClickListener(this);
@@ -525,7 +528,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
@Override
public void onClick(View view) {
- if (view == checkbox_global || view == checkbox_remote_dns) {
+ if (view == checkbox_global || view == checkbox_remote_dns || view == checkbox_maintenance) {
savePrefs();
updateUI();
} else if (view == button_apps) {
@@ -571,8 +574,9 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
}
private void handleWatchdogClick() {
- if (prefs.getWatchdogEnable()) showWatchdogBiometricPrompt();
- else toggleWatchdog(false);
+// if (prefs.getWatchdogEnable()) showWatchdogBiometricPrompt();
+// else toggleWatchdog(false);
+ toggleWatchdog(prefs.getWatchdogEnable());
}
private void toggleWatchdog(boolean stop) {
@@ -629,6 +633,53 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
bp.authenticate(new BiometricPrompt.PromptInfo.Builder().setTitle(getString(R.string.auth_required_title)).setSubtitle(getString(R.string.auth_required_subtitle)).setAllowedAuthenticators(auth).build());
}
+ // --- Secure Advanced Settings Menu ---
+ private void handleConfigToggle() {
+ if (configLayout.getVisibility() == View.GONE) {
+ // The menu is closed. We want to open it, so we check for security first.
+ BiometricManager bm = BiometricManager.from(this);
+ int auth = BiometricManager.Authenticators.BIOMETRIC_STRONG | BiometricManager.Authenticators.DEVICE_CREDENTIAL;
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
+ auth = BiometricManager.Authenticators.BIOMETRIC_WEAK | BiometricManager.Authenticators.DEVICE_CREDENTIAL;
+ }
+ android.app.KeyguardManager km = (android.app.KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
+
+ if (bm.canAuthenticate(auth) == BiometricManager.BIOMETRIC_SUCCESS || (km != null && km.isDeviceSecure())) {
+ showConfigBiometricPrompt();
+ } else {
+ showEnrollmentDialog(); // Forces user to set a PIN if device has no security
+ }
+ } else {
+ // The menu is open. Just close it without asking for fingerprint.
+ toggleVisibility(configLayout, configLabel, getString(R.string.advanced_settings_label));
+ }
+ }
+
+ private void showConfigBiometricPrompt() {
+ Executor ex = ContextCompat.getMainExecutor(this);
+ BiometricPrompt bp = new BiometricPrompt(this, ex, new BiometricPrompt.AuthenticationCallback() {
+ @Override
+ public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) {
+ super.onAuthenticationSucceeded(result);
+ // Auth successful! Open the menu.
+ toggleVisibility(configLayout, configLabel, getString(R.string.advanced_settings_label));
+ }
+ });
+
+ int auth = BiometricManager.Authenticators.BIOMETRIC_STRONG | BiometricManager.Authenticators.DEVICE_CREDENTIAL;
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
+ auth = BiometricManager.Authenticators.BIOMETRIC_WEAK | BiometricManager.Authenticators.DEVICE_CREDENTIAL;
+ }
+
+ // Reusing your existing strings to avoid compilation errors
+ bp.authenticate(new BiometricPrompt.PromptInfo.Builder()
+ .setTitle(getString(R.string.auth_required_title))
+ .setSubtitle(getString(R.string.auth_required_subtitle))
+ .setAllowedAuthenticators(auth)
+ .build());
+ }
+ // ------------------------------------------------
+
private void showWatchdogBiometricPrompt() {
Executor ex = ContextCompat.getMainExecutor(this);
BiometricPrompt bp = new BiometricPrompt(this, new BiometricPrompt.AuthenticationCallback() {
@@ -685,27 +736,51 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
checkbox_global.setChecked(prefs.getGlobal());
checkbox_udp_in_tcp.setChecked(prefs.getUdpInTcp());
checkbox_remote_dns.setChecked(prefs.getRemoteDns());
+ checkbox_maintenance.setChecked(prefs.getMaintenanceMode());
boolean editable = !vpnActive;
edittext_socks_addr.setEnabled(editable);
edittext_socks_port.setEnabled(editable);
button_save.setEnabled(editable);
}
+ //DEFAULT VALUES ON ORIGINAL INTERFACE
+// private void savePrefs() {
+// prefs.setSocksAddress(edittext_socks_addr.getText().toString());
+// prefs.setSocksPort(Integer.parseInt(edittext_socks_port.getText().toString()));
+// prefs.setSocksUdpAddress(edittext_socks_udp_addr.getText().toString());
+// prefs.setSocksUsername(edittext_socks_user.getText().toString());
+// prefs.setSocksPassword(edittext_socks_pass.getText().toString());
+// prefs.setDnsIpv4(edittext_dns_ipv4.getText().toString());
+// prefs.setDnsIpv6(edittext_dns_ipv6.getText().toString());
+// prefs.setIpv4(checkbox_ipv4.isChecked());
+// prefs.setIpv6(checkbox_ipv6.isChecked());
+// prefs.setGlobal(checkbox_global.isChecked());
+// prefs.setUdpInTcp(checkbox_udp_in_tcp.isChecked());
+// prefs.setRemoteDns(checkbox_remote_dns.isChecked());
+// prefs.setMaintenanceMode(checkbox_maintenance.isChecked());
+// }
+
private void savePrefs() {
- prefs.setSocksAddress(edittext_socks_addr.getText().toString());
- prefs.setSocksPort(Integer.parseInt(edittext_socks_port.getText().toString()));
- prefs.setSocksUdpAddress(edittext_socks_udp_addr.getText().toString());
- prefs.setSocksUsername(edittext_socks_user.getText().toString());
- prefs.setSocksPassword(edittext_socks_pass.getText().toString());
+ // 1. Hardcoded / Hidden Secure Values (Walled Garden defaults)
+ prefs.setSocksAddress("127.0.0.1");
+ prefs.setSocksPort(1080);
+ prefs.setSocksUdpAddress(""); // Empty by default
+ prefs.setSocksUsername("");
+ prefs.setSocksPassword("");
+ prefs.setIpv4(true);
+ prefs.setIpv6(true);
+ prefs.setUdpInTcp(false);
+ prefs.setRemoteDns(true);
+
+ // CRITICAL: Force Global to TRUE so the tunnel catches ALL system traffic
+ prefs.setGlobal(true);
+
+ // 2. User Editable Values (The only things read from the UI)
prefs.setDnsIpv4(edittext_dns_ipv4.getText().toString());
prefs.setDnsIpv6(edittext_dns_ipv6.getText().toString());
- prefs.setIpv4(checkbox_ipv4.isChecked());
- prefs.setIpv6(checkbox_ipv6.isChecked());
- prefs.setGlobal(checkbox_global.isChecked());
- prefs.setUdpInTcp(checkbox_udp_in_tcp.isChecked());
- prefs.setRemoteDns(checkbox_remote_dns.isChecked());
+ prefs.setMaintenanceMode(checkbox_maintenance.isChecked());
}
-
+
private void addToLog(String message) {
runOnUiThread(() -> {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss", Locale.getDefault());
diff --git a/apk/controller/app/src/main/java/org/iiab/controller/Preferences.java b/apk/controller/app/src/main/java/org/iiab/controller/Preferences.java
index db563ed..7a7b73c 100644
--- a/apk/controller/app/src/main/java/org/iiab/controller/Preferences.java
+++ b/apk/controller/app/src/main/java/org/iiab/controller/Preferences.java
@@ -32,6 +32,7 @@ public class Preferences
public static final String APPS = "Apps";
public static final String ENABLE = "Enable";
public static final String WATCHDOG_ENABLE = "WatchdogEnable";
+ public static final String MAINTENANCE_MODE = "MaintenanceMode";
private SharedPreferences prefs;
@@ -193,6 +194,16 @@ public class Preferences
editor.commit();
}
+ public boolean getMaintenanceMode() {
+ return prefs.getBoolean(MAINTENANCE_MODE, false);
+ }
+
+ public void setMaintenanceMode(boolean enable) {
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putBoolean(MAINTENANCE_MODE, enable);
+ editor.commit();
+ }
+
public int getTunnelMtu() {
return 8500;
}
diff --git a/apk/controller/app/src/main/java/org/iiab/controller/TProxyService.java b/apk/controller/app/src/main/java/org/iiab/controller/TProxyService.java
index 5bfb258..141c30a 100644
--- a/apk/controller/app/src/main/java/org/iiab/controller/TProxyService.java
+++ b/apk/controller/app/src/main/java/org/iiab/controller/TProxyService.java
@@ -226,6 +226,10 @@ public class TProxyService extends VpnService {
String selfName = getApplicationContext().getPackageName();
try {
builder.addDisallowedApplication(selfName);
+ if (prefs.getMaintenanceMode()) { // Verify if the maintenance mode is enabled
+ builder.addDisallowedApplication("com.termux");
+ Log.i(TAG, "Maintenance mode enabled: Termux has direct Internet access");
+ }
} catch (NameNotFoundException e) {
}
}
diff --git a/apk/controller/app/src/main/res/layout/main.xml b/apk/controller/app/src/main/res/layout/main.xml
index 1bdc060..3f6f209 100644
--- a/apk/controller/app/src/main/res/layout/main.xml
+++ b/apk/controller/app/src/main/res/layout/main.xml
@@ -125,23 +125,11 @@
android:elevation="4dp"
android:visibility="gone" />
-
-
-
-
-
-
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ android:focusable="true"
+ android:visibility="gone"/>
-
-
-
-
-
-
@@ -209,12 +241,11 @@
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="8dp">
+ android:layout_marginTop="8dp"
+ android:visibility="gone">
-
-