diff --git a/app/src/main/java/io/netbird/client/MainActivity.java b/app/src/main/java/io/netbird/client/MainActivity.java index 3256cba4..31e06e06 100644 --- a/app/src/main/java/io/netbird/client/MainActivity.java +++ b/app/src/main/java/io/netbird/client/MainActivity.java @@ -612,11 +612,11 @@ public void deselectRoute(String route) throws Exception { } @Override - public String debugBundle(boolean anonymize) throws Exception { + public String debugBundle(boolean anonymize, String anonymizeLevel) throws Exception { if (mBinder == null) { throw new Exception("VPN service not connected"); } - return mBinder.debugBundle(anonymize); + return mBinder.debugBundle(anonymize, anonymizeLevel); } @Override diff --git a/app/src/main/java/io/netbird/client/ServiceAccessor.java b/app/src/main/java/io/netbird/client/ServiceAccessor.java index bffc12fb..546055a0 100644 --- a/app/src/main/java/io/netbird/client/ServiceAccessor.java +++ b/app/src/main/java/io/netbird/client/ServiceAccessor.java @@ -31,7 +31,7 @@ public interface ServiceAccessor { void addRouteChangeListener(RouteChangeListener listener); void removeRouteChangeListener(RouteChangeListener listener); - String debugBundle(boolean anonymize) throws Exception; + String debugBundle(boolean anonymize, String anonymizeLevel) throws Exception; /** SSO session deadline as unix seconds; 0 when unknown or not bound. */ long sessionExpiresAt(); diff --git a/app/src/main/java/io/netbird/client/ui/troubleshoot/AnonymizeLevelSheet.java b/app/src/main/java/io/netbird/client/ui/troubleshoot/AnonymizeLevelSheet.java new file mode 100644 index 00000000..aa32b2bf --- /dev/null +++ b/app/src/main/java/io/netbird/client/ui/troubleshoot/AnonymizeLevelSheet.java @@ -0,0 +1,78 @@ +package io.netbird.client.ui.troubleshoot; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.google.android.material.bottomsheet.BottomSheetDialogFragment; + +import io.netbird.client.databinding.SheetAnonymizeLevelBinding; +import io.netbird.client.tool.Preferences; + +public class AnonymizeLevelSheet extends BottomSheetDialogFragment { + + public interface OnLevelChangedListener { + void onAnonymizeLevelChanged(String level); + } + + private static final String ARG_LEVEL = "level"; + + private SheetAnonymizeLevelBinding binding; + + public static AnonymizeLevelSheet newInstance(String current) { + AnonymizeLevelSheet sheet = new AnonymizeLevelSheet(); + Bundle args = new Bundle(); + args.putString(ARG_LEVEL, current); + sheet.setArguments(args); + return sheet; + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, + @Nullable Bundle savedInstanceState) { + binding = SheetAnonymizeLevelBinding.inflate(inflater, container, false); + + binding.levelRowNone.setOnClickListener(v -> pick(Preferences.ANONYMIZE_LEVEL_NONE)); + binding.levelRowDefault.setOnClickListener(v -> pick(Preferences.ANONYMIZE_LEVEL_DEFAULT)); + binding.levelRowStrict.setOnClickListener(v -> pick(Preferences.ANONYMIZE_LEVEL_STRICT)); + + showCheckmarkFor(currentLevel()); + return binding.getRoot(); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + binding = null; + } + + private String currentLevel() { + Bundle args = getArguments(); + if (args == null) { + return Preferences.ANONYMIZE_LEVEL_DEFAULT; + } + return args.getString(ARG_LEVEL, Preferences.ANONYMIZE_LEVEL_DEFAULT); + } + + private void showCheckmarkFor(String level) { + binding.levelCheckNone.setVisibility( + Preferences.ANONYMIZE_LEVEL_NONE.equals(level) ? View.VISIBLE : View.INVISIBLE); + binding.levelCheckStrict.setVisibility( + Preferences.ANONYMIZE_LEVEL_STRICT.equals(level) ? View.VISIBLE : View.INVISIBLE); + binding.levelCheckDefault.setVisibility( + Preferences.ANONYMIZE_LEVEL_NONE.equals(level) || Preferences.ANONYMIZE_LEVEL_STRICT.equals(level) + ? View.INVISIBLE : View.VISIBLE); + } + + private void pick(String level) { + if (getParentFragment() instanceof OnLevelChangedListener) { + ((OnLevelChangedListener) getParentFragment()).onAnonymizeLevelChanged(level); + } + dismiss(); + } +} diff --git a/app/src/main/java/io/netbird/client/ui/troubleshoot/TroubleshootFragment.java b/app/src/main/java/io/netbird/client/ui/troubleshoot/TroubleshootFragment.java index 2a6edff7..4a2220a5 100644 --- a/app/src/main/java/io/netbird/client/ui/troubleshoot/TroubleshootFragment.java +++ b/app/src/main/java/io/netbird/client/ui/troubleshoot/TroubleshootFragment.java @@ -20,16 +20,18 @@ import io.netbird.client.tool.Preferences; import io.netbird.client.tool.ProfileManagerWrapper; -public class TroubleshootFragment extends Fragment { +public class TroubleshootFragment extends Fragment implements AnonymizeLevelSheet.OnLevelChangedListener { private static final String LOGTAG = "TroubleshootFragment"; + private FragmentTroubleshootBinding binding; + private Preferences preferences; @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { binding = FragmentTroubleshootBinding.inflate(inflater, container, false); - Preferences preferences = new Preferences(inflater.getContext()); + preferences = new Preferences(inflater.getContext()); binding.switchTraceLog.setChecked(preferences.isTraceLogEnabled()); binding.switchTraceLog.setOnCheckedChangeListener((buttonView, isChecked) -> { @@ -44,9 +46,10 @@ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, binding.switchTraceLog.toggle(); }); - binding.anonymizeLayout.setOnClickListener(v -> { - binding.switchAnonymize.toggle(); - }); + updateAnonymizeValue(); + binding.anonymizeLayout.setOnClickListener(v -> + AnonymizeLevelSheet.newInstance(preferences.getAnonymizeLevel()) + .show(getChildFragmentManager(), "anonymize_level")); initializeRemoteJobsSwitch(inflater.getContext()); @@ -63,6 +66,18 @@ public void onDestroyView() { binding = null; } + @Override + public void onAnonymizeLevelChanged(String level) { + preferences.setAnonymizeLevel(level); + if (binding != null) { + updateAnonymizeValue(); + } + } + + private void updateAnonymizeValue() { + binding.anonymizeValue.setText(anonymizeLevelLabel(preferences.getAnonymizeLevel())); + } + private void initializeRemoteJobsSwitch(Context context) { try { String configFilePath = new ProfileManagerWrapper(context).getActiveConfigPath(); @@ -88,11 +103,15 @@ private void generateDebugBundle() { return; } - boolean anonymize = binding.switchAnonymize.isChecked(); + String level = preferences.getAnonymizeLevel(); + boolean anonymize = !Preferences.ANONYMIZE_LEVEL_NONE.equals(level); + String anonymizeLevel = Preferences.ANONYMIZE_LEVEL_STRICT.equals(level) + ? Preferences.ANONYMIZE_LEVEL_STRICT + : Preferences.ANONYMIZE_LEVEL_DEFAULT; binding.buttonDebugBundle.setEnabled(false); new Thread(() -> { try { - String key = ((ServiceAccessor) activity).debugBundle(anonymize); + String key = ((ServiceAccessor) activity).debugBundle(anonymize, anonymizeLevel); activity.runOnUiThread(() -> { if (binding == null || !isAdded()) return; binding.buttonDebugBundle.setEnabled(true); @@ -111,4 +130,15 @@ private void generateDebugBundle() { } }).start(); } + + private static int anonymizeLevelLabel(String level) { + switch (level) { + case Preferences.ANONYMIZE_LEVEL_NONE: + return R.string.troubleshoot_anonymize_none; + case Preferences.ANONYMIZE_LEVEL_STRICT: + return R.string.troubleshoot_anonymize_strict; + default: + return R.string.troubleshoot_anonymize_default; + } + } } diff --git a/app/src/main/res/layout/fragment_troubleshoot.xml b/app/src/main/res/layout/fragment_troubleshoot.xml index 8c0f6ea3..5638f54a 100644 --- a/app/src/main/res/layout/fragment_troubleshoot.xml +++ b/app/src/main/res/layout/fragment_troubleshoot.xml @@ -54,7 +54,7 @@ + android:paddingEnd="16dp" + android:paddingTop="10dp" + android:paddingBottom="10dp"> - + android:orientation="vertical"> + + + + + - + + @@ -118,26 +137,21 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="2dp" - android:text="@string/troubleshoot_allow_remote_jobs_desc" + android:text="@string/troubleshoot_anonymize_desc" android:textColor="@color/nb_txt_light" android:textSize="12sp" /> - + android:textColor="@color/nb_txt_light" + android:textSize="14sp" + tools:text="@string/troubleshoot_anonymize_default" /> - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index af607bc8..097a7e64 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -119,6 +119,13 @@ Trace-Logs aktivieren. Debug-Paket hochladen Sensible Daten anonymisieren + Verbirgt IP-Adressen, Domains und andere sensible Werte. + Keine + Alles bleibt lesbar. Nur innerhalb Ihrer Organisation weitergeben. + Standard + Verbirgt öffentliche IP-Adressen und Domains. Interne IPv4-Adressen und Peer-Namen bleiben für den Support lesbar. + Strikt + Verbirgt zusätzlich private, CGNAT- und Link-Local-Adressen, Peer-Namen und WireGuard-Schlüssel. Außerhalb Ihrer Organisation verwenden. Protokollierung Debug-Paket Rosenpass aktivieren diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 2bfbc8bc..fbdadc3f 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -119,6 +119,13 @@ Activar el nivel de registro de seguimiento. Subir paquete de diagnóstico Anonimizar datos sensibles + Oculta direcciones IP, dominios y otros valores sensibles. + Ninguno + Todo permanece legible. Compártelo solo dentro de tu organización. + Predeterminado + Oculta las direcciones IP públicas y los dominios. Las direcciones IPv4 internas y los nombres de los peers siguen legibles para el soporte. + Estricto + Oculta además las direcciones privadas, CGNAT y de enlace local, los nombres de los peers y las claves WireGuard. Úsalo fuera de tu organización. Registro Paquete de diagnóstico Habilitar Rosenpass diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index a37df577..893690ee 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -119,6 +119,13 @@ Activer le niveau de journalisation trace. Envoyer le lot de diagnostic Anonymiser les données sensibles + Masque les adresses IP, les domaines et d\'autres valeurs sensibles. + Aucune + Tout reste lisible. À partager uniquement au sein de votre organisation. + Par défaut + Masque les adresses IP publiques et les domaines. Les adresses IPv4 internes et les noms des pairs restent lisibles pour le support. + Strict + Masque aussi les adresses privées, CGNAT et de lien local, les noms des pairs et les clés WireGuard. À utiliser hors de votre organisation. Journalisation Lot de diagnostic Activer Rosenpass diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index e054a07c..9983d230 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -119,6 +119,13 @@ Trace naplózási szint engedélyezése. Hibakeresési csomag feltöltése Érzékeny adatok anonimizálása + Elrejti az IP-címeket, a tartományokat és más érzékeny értékeket. + Nincs + Minden olvasható marad. Csak a szervezeten belül ossza meg. + Alapértelmezett + Elrejti a nyilvános IP-címeket és tartományokat. A belső IPv4-címek és a peer-nevek olvashatók maradnak a támogatás számára. + Szigorú + A privát, CGNAT és link-local címeket, a peer-neveket és a WireGuard-kulcsokat is elrejti. A szervezeten kívül ezt használja. Naplózás Hibakeresési csomag Rosenpass engedélyezése diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index a1d09564..04f09198 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -119,6 +119,13 @@ Abilita il livello di log di traccia. Carica pacchetto di debug Anonimizza dati sensibili + Nasconde indirizzi IP, domini e altri valori sensibili. + Nessuna + Tutto resta leggibile. Condividi solo all’interno della tua organizzazione. + Predefinito + Nasconde gli indirizzi IP pubblici e i domini. Gli indirizzi IPv4 interni e i nomi dei peer restano leggibili per il supporto. + Rigoroso + Nasconde anche gli indirizzi privati, CGNAT e link-local, i nomi dei peer e le chiavi WireGuard. Usalo fuori dalla tua organizzazione. Registrazione Pacchetto di debug Abilita Rosenpass diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index daff79b5..d7f87770 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -119,6 +119,13 @@ トレースログレベルを有効にします。 デバッグバンドルをアップロード 機密データを匿名化 + IP アドレス、ドメイン、その他の機密性の高い値を隠します。 + なし + すべてそのまま残ります。組織内でのみ共有してください。 + デフォルト + パブリック IP アドレスとドメインを隠します。内部 IPv4 アドレスとピア名はサポート向けに読める状態で残ります。 + 厳格 + プライベート、CGNAT、リンクローカルのアドレス、ピア名、WireGuard 鍵も隠します。組織外へ共有する場合に使用します。 ログ デバッグバンドル Rosenpass を有効にする diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index c5c602b6..3955229e 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -119,6 +119,13 @@ Habilitar o nível de log de trace. Enviar pacote de depuração Anonimizar dados sensíveis + Oculta endereços IP, domínios e outros valores sensíveis. + Nenhum + Tudo permanece legível. Compartilhe apenas dentro da sua organização. + Padrão + Oculta os endereços IP públicos e os domínios. Os endereços IPv4 internos e os nomes dos peers continuam legíveis para o suporte. + Estrito + Oculta também os endereços privados, CGNAT e link-local, os nomes dos peers e as chaves WireGuard. Use fora da sua organização. Registro Pacote de depuração Ativar Rosenpass diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 8ed43a21..b7769ff6 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -119,6 +119,13 @@ Включить уровень журналирования TRACE. Загрузить отладочный пакет Анонимизировать конфиденциальные данные + Скрывает IP-адреса, домены и другие конфиденциальные значения. + Нет + Всё остаётся читаемым. Передавайте только внутри вашей организации. + По умолчанию + Скрывает публичные IP-адреса и домены. Внутренние IPv4-адреса и имена пиров остаются читаемыми для поддержки. + Строгий + Скрывает также частные, CGNAT и link-local адреса, имена пиров и ключи WireGuard. Используйте за пределами вашей организации. Журналирование Отладочный пакет Включить Rosenpass diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 4b40dce6..d827e5df 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -119,6 +119,13 @@ 启用跟踪日志级别。 上传调试包 匿名化敏感数据 + 隐藏 IP 地址、域名和其他敏感值。 + 无 + 所有内容均保持可读。请仅在组织内部分享。 + 默认 + 隐藏公网 IP 地址和域名。内部 IPv4 地址和对等节点名称保持可读,便于支持人员查看。 + 严格 + 同时隐藏私有、CGNAT 和链路本地地址、对等节点名称以及 WireGuard 密钥。向组织外分享时请使用。 日志 调试包 启用 Rosenpass diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d9873929..1d626ca4 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -188,6 +188,13 @@ Enable trace log level. Upload debug bundle Anonymize sensitive data + Hides IP addresses, domains, and other sensitive values. + None + Everything stays readable. Only share inside your organization. + Default + Hides public IP addresses and domains. Internal IPv4 addresses and peer names stay readable for support. + Strict + Also hides private, CGNAT and link-local addresses, peer names and WireGuard keys. Use it outside your organization. Logging Debug bundle Enable Rosenpass diff --git a/tool/src/main/java/io/netbird/client/tool/EngineRunner.java b/tool/src/main/java/io/netbird/client/tool/EngineRunner.java index ec68f97e..85446af3 100644 --- a/tool/src/main/java/io/netbird/client/tool/EngineRunner.java +++ b/tool/src/main/java/io/netbird/client/tool/EngineRunner.java @@ -436,15 +436,13 @@ public void deselectRoute(String route) throws Exception { } } - public String debugBundle(boolean anonymize) throws Exception { + public String debugBundle(boolean anonymize, String anonymizeLevel) throws Exception { String configPath = profileManager.getActiveConfigPath(); String statePath = profileManager.getActiveStateFilePath(); String cacheDir = context.getCacheDir().getAbsolutePath(); var platformFiles = new AndroidPlatformFiles(configPath, statePath, cacheDir); try { - // The strict level stays unused until the troubleshoot screen - // grows an option for it. - return goClient.debugBundle(platformFiles, anonymize, Android.AnonymizeLevelDefault); + return goClient.debugBundle(platformFiles, anonymize, anonymizeLevel); } catch (Exception e) { Log.e(LOGTAG, "goClient error", e); throw e; diff --git a/tool/src/main/java/io/netbird/client/tool/Preferences.java b/tool/src/main/java/io/netbird/client/tool/Preferences.java index ddf57ca5..1ad4fd64 100644 --- a/tool/src/main/java/io/netbird/client/tool/Preferences.java +++ b/tool/src/main/java/io/netbird/client/tool/Preferences.java @@ -5,10 +5,18 @@ public class Preferences { + public static final String ANONYMIZE_LEVEL_NONE = "none"; + + public static final String ANONYMIZE_LEVEL_DEFAULT = "default"; + + public static final String ANONYMIZE_LEVEL_STRICT = "strict"; + private final String keyTraceLog = "tracelog"; private final String keyForceRelayConnection = "isConnectionForceRelayed"; + private final String keyAnonymizeLevel = "anonymizeLevel"; + private final SharedPreferences sharedPref; public Preferences(Context context) { @@ -26,6 +34,14 @@ public void disableTraceLog() { sharedPref.edit().putBoolean(keyTraceLog, false).apply(); } + public String getAnonymizeLevel() { + return sharedPref.getString(keyAnonymizeLevel, ANONYMIZE_LEVEL_DEFAULT); + } + + public void setAnonymizeLevel(String level) { + sharedPref.edit().putString(keyAnonymizeLevel, level).apply(); + } + public boolean isConnectionForceRelayed() { return sharedPref.getBoolean(keyForceRelayConnection, true); } diff --git a/tool/src/main/java/io/netbird/client/tool/VPNService.java b/tool/src/main/java/io/netbird/client/tool/VPNService.java index eed792d9..0f5e900a 100644 --- a/tool/src/main/java/io/netbird/client/tool/VPNService.java +++ b/tool/src/main/java/io/netbird/client/tool/VPNService.java @@ -330,8 +330,8 @@ public void removeRouteChangeListener(RouteChangeListener listener) { } } - public String debugBundle(boolean anonymize) throws Exception { - return engineRunner.debugBundle(anonymize); + public String debugBundle(boolean anonymize, String anonymizeLevel) throws Exception { + return engineRunner.debugBundle(anonymize, anonymizeLevel); } /**