Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 61 additions & 2 deletions app/src/main/java/eu/faircode/netguard/ServiceSinkhole.java
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ public class ServiceSinkhole extends VpnService {
public static final int NOTIFY_EXTERNAL = 9;
private static final int NOTIFY_DOH_ERROR = 11;
private static final int NOTIFY_WG_ERROR = 12;
private static final int NOTIFY_LOCAL_NETWORK = 13;

public static final String EXTRA_COMMAND = "Command";
private static final String EXTRA_REASON = "Reason";
Expand Down Expand Up @@ -1663,9 +1664,15 @@ private Builder getBuilder(List<Rule> listAllowed, List<Rule> listRule) {
// Android 17 refuses local network traffic without ACCESS_LOCAL_NETWORK:
// TCP times out, UDP fails with EPERM. A LAN resolver routed into the tun
// above is re-sent from our own socket, so it goes silent (#701).
if (net.kollnig.missioncontrol.LocalNetworkAccess.isMissing(ServiceSinkhole.this))
// The symptom is "nothing resolves", which no one attributes to a
// permission — and the banner only reaches someone who opens the app.
// Notify, so the reason meets the user where the failure appears.
if (net.kollnig.missioncontrol.LocalNetworkAccess.isMissing(ServiceSinkhole.this)) {
Log.w(TAG, "Local network access not granted: configured LAN destinations" +
" (custom DNS, Secure DNS resolver, WireGuard peer) are unreachable");
" (custom DNS, Secure DNS resolver, WireGuard peer, proxy) are unreachable");
showLocalNetworkNotification();
} else
clearLocalNetworkNotification();

// Dynamically exclude carrier ePDG IPs so Wi-Fi calling works globally.
// ePDG domains follow 3GPP standard: epdg.epc.mnc{MNC}.mcc{MCC}.pub.3gppnetwork.org
Expand Down Expand Up @@ -3662,6 +3669,14 @@ private void showErrorNotification(String message) {
}

private void showDohErrorNotification() {
// A local resolver we are not allowed to reach is not a DoH problem,
// and "consider disabling Secure DNS" is the wrong advice for it: the
// fix is one permission away. Say so instead (#701).
if (net.kollnig.missioncontrol.LocalNetworkAccess.isMissing(this)) {
showLocalNetworkNotification();
return;
}

Intent main = new Intent(this, ActivityMain.class);
PendingIntent pi = PendingIntentCompat.getActivity(this, 0, main, PendingIntent.FLAG_UPDATE_CURRENT);

Expand All @@ -3686,6 +3701,14 @@ private void showDohErrorNotification() {
}

private void showWireGuardErrorNotification(String message) {
// Same as the DoH case: a peer on the LAN that we may not talk to is a
// permission problem, not a tunnel problem, and sending the user to the
// WireGuard settings only wastes their time (#701).
if (net.kollnig.missioncontrol.LocalNetworkAccess.isMissing(this)) {
showLocalNetworkNotification();
return;
}

Intent main = new Intent(this, ActivitySettings.class);
PendingIntent pi = PendingIntentCompat.getActivity(this, NOTIFY_WG_ERROR, main,
PendingIntent.FLAG_UPDATE_CURRENT);
Expand Down Expand Up @@ -3717,6 +3740,42 @@ private void clearWireGuardErrorNotification() {
NotificationManagerCompat.from(this).cancel(NOTIFY_WG_ERROR);
}

/**
* Local network access is missing and something the user configured needs
* it. Opens the main screen, where the warning row requests the permission.
*/
private void showLocalNetworkNotification() {
Intent main = new Intent(this, ActivityMain.class);
PendingIntent pi = PendingIntentCompat.getActivity(this, NOTIFY_LOCAL_NETWORK, main,
PendingIntent.FLAG_UPDATE_CURRENT);

String detail = getString(R.string.msg_local_network_notify);

NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "notify");
builder.setSmallIcon(R.drawable.ic_error_white_24dp)
.setContentTitle(getString(R.string.msg_local_network_title))
.setContentText(detail)
.setContentIntent(pi)
.setColor(getResources().getColor(R.color.colorTrackerControl))
.setOngoing(false)
.setAutoCancel(true)
// Rebuilt on every network change; alert once, then sit quietly.
.setOnlyAlertOnce(true);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
builder.setCategory(NotificationCompat.CATEGORY_STATUS)
.setVisibility(NotificationCompat.VISIBILITY_SECRET);

NotificationCompat.BigTextStyle notification = new NotificationCompat.BigTextStyle(builder);
notification.bigText(detail);

Util.notify(this, NOTIFY_LOCAL_NETWORK, notification.build());
}

private void clearLocalNetworkNotification() {
NotificationManagerCompat.from(this).cancel(NOTIFY_LOCAL_NETWORK);
}

private void showUpdateNotification(String name, String url) {
if (Util.isFDroidInstall())
return;
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,8 @@ Sincerely,\n\n]]></string>
<string name="failed_loading_cached_analysis">Loading cached tracker results failed. Please report this to the developer at hello@trackercontrol.org</string>
<string name="msg_notifications">Tap to grant notification permissions (for error messages, etc.)</string>
<string name="msg_local_network">Tap to allow local network access, which Android asks about as \"nearby devices\". Android 17 blocks it by default, so your own DNS server, Secure DNS resolver, WireGuard peer or proxy cannot be reached.</string>
<string name="msg_local_network_title">Local network access needed</string>
<string name="msg_local_network_notify">TrackerControl cannot reach your own DNS server, Secure DNS resolver, WireGuard peer or proxy, so name resolution may fail. Android 17 requires permission for this, which Android asks about as \"nearby devices\". Tap to open TrackerControl and allow it.</string>

<string name="setting_monitor_system">Monitor system apps</string>
<string name="summary_monitor_system">Route system apps (Play Services, carrier services, etc.) through the VPN so their trackers are detected and blocked, and show them in the app list.\n\nOff by default: excluding system apps is friendlier to battery, because their background traffic no longer wakes the VPN. Turning this on conflicts with \"Block connections without VPN\" in the Android VPN settings, which must be DISABLED.</string>
Expand Down