Nach Update auf ShiftOS 7L: Netzwerk validiert, aber kein Internet / ERR_NAME_NOT_RESOLVED

Xirrr

Member
Original poster
8 August 2021
25
Hallo zusammen,

nach dem Upgrade von ShiftOS 5 (SHIFT6MQ.SOS.5.0.L.20230330-BETA-LIGHT-OTA) auf ShiftOS 7 (SHIFT6MQ.SOS.7.0.L.20250819) habe ich folgendes Problem:
  1. WLAN verbunden, Internet funktioniert technisch (IP-Adresse erhalten, ping, curl OK)
  2. Android zeigt durchgestrichenes Netzwerk-Symbol beim öffnen von Apps (Erdkugel ist durchgestrichen), z.B.
    1. Mail App
    2. Intant Messenger App
    3. Webbrowser App
  3. Browser: ERR_NAME_NOT_RESOLVED (ping löst FQDN auf
  4. Logcat zeigt: validated=true, captivePortal=false
  5. Private DNS Modus ist auf dem Status "off"
Die DNS-Auflösung geht mittels ping, siehe hier:
Bash:
➜  ~ adb shell su -c "ping -c 1 example.com"
PING example.com (23.220.75.245) 56(84) bytes of data.
64 bytes from a23-220-75-245.deploy.static.akamaitechnologies.com (23.220.75.245): icmp_seq=1 ttl=47 time=210 ms

--- example.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 210.319/210.319/210.319/0.000 ms
 
Zuletzt bearbeitet:
So, hab mich zusammen mit Claude Sonnet 4.5 tief in das Androidsystem eingegraben und folgende Kenntnisse sind aufgetaucht.
Auf meinem Gerät sind +150 Apps mit der Policy POLICY_REJECT_ALL (policy=262144) eingetragen.
Das ist der Befehl um die gesamte Liste zu erhalten und gleichzeitig zu speichern:
Bash:
adb shell su -c "dumpsys netpolicy | grep 'policy=262144'" > blocked_uids.txt

Mit dem Code könnt ihr auflösen was für Apps sich dahinter verbergen:
Bash:
python3 << 'EOF'
import subprocess
import re

# Lese blockierte UIDs
with open('blocked_uids.txt', 'r') as f:
    uids = re.findall(r'UID=(\d+)', f.read())

print(f"Gefunden: {len(uids)} blockierte UIDs\n")

for uid in uids:  # ALLE statt nur [:30]
    result = subprocess.run(
        ['adb', 'shell', 'su', '-c', f'cmd package list packages --uid {uid}'],
        capture_output=True, text=True
    )

    output = result.stdout.strip()

    if output and ':' in output:
        parts = output.split()
        pkg = parts[0].split(':')[1] if len(parts) > 0 else 'unknown'
    else:
        pkg = 'keine App gefunden'

    print(f"UID {uid}: {pkg}")
EOF

Was ich dann noch getestet habe ist, welchen installer meine Apps haben:
Bash:
adb shell su -c '
for pkg in $(pm list packages | cut -d: -f2); do
  installer=$(dumpsys package $pkg 2>/dev/null | grep "installerPackageName=" | head -1)
  echo "$pkg: $installer"
done
' 2>/dev/null | grep "installerPackageName=null"

Dann habe ich probiert eine App mit dem Wert installerPackageName=null über F-Droid zu installieren, was es ja in shiftOS 5 L schon installiert wurde. Also die App A deinstalliert und über F-Droid installiert. Taadaa, es klappt. Das waren zwei Tage (2x 4 Stunden) Arbeit. Diese schenke ich euch, liebe Shiftphone-Community ❤️

Achso, ja... wie setzte ich F-Droid auf die Whiteliste von der Policy 262144. Die Variable $fdroid_uid ersetzt ihr durch die aus der vorherigen Python3-Code-Ausgabe.
Bash:
adb shell su -c "cmd netpolicy add restrict-background-whitelist $fdroid_uid"

Jetzt ist die Frage wie das Problem für alle anderen Apps auch gelöst werden soll. Dazu gibt es zwei (aus meiner Sicht) schlechte Lösungsansätze. Vielleicht hat der eine hier im Forum noch weitere Ideen.
Ansatz 1: Entsperren aller Apps von der Policy 262144
Ansatz 2: Jede einzelne App neuinstallieren

Eine andere Frage kann @amartinz lösen, falls meine Vermutung stimmen. Hier der Root-Cause Versuch von Sonnet 4.5:

WARUM HAT DAS SHIFTOS-UPDATE DAS AUSGELÖST?​


Theorie 1: Package Manager DB Korruption
Beim Update von Android 13 → 15 wurde /data/system/packages.xml nicht korrekt migriert:
  • Installer-Einträge gingen verloren
  • Android 15 sah installer=null
  • → Setzte automatisch POLICY_REJECT_ALL
Theorie 2: Restricted Mode wurde kurzzeitig aktiviert
Während des Updates war vielleicht kurz restricted_networking_mode=1 aktiv:
  • System scannte alle Apps
  • Markierte Apps ohne Installer als "restricted"
  • Setzte POLICY_REJECT_ALL
  • Mode wurde wieder deaktiviert, aber die Policies blieben

Hier noch der Check für den restricted_networking_mode:
Bash:
adb shell su -c "settings get secure restricted_networking_mode"
Meine Ausgabe war "null"
 
Zuletzt bearbeitet:
Nachtrag:
Ich habe noch geprüft, ob der Ansatz 1 gut wäre und habe die Schnittmenge von allen meiner Apps mit installer=null (und ungleich null) und der Policy POLICY_REJECT_ALL (und ungleich) durchgeführt.

Bash:
python3 << 'EOF'
import subprocess
import re

print("=== ANALYSE: installer=null vs POLICY_REJECT_ALL ===\n")

# Hole Apps mit installer=null
result = subprocess.run(
    ['adb', 'shell', 'su', '-c', 'pm list packages -i'],
    capture_output=True, text=True
)
null_installers = set()
installer_map = {}  # Speichere Installer für alle Pakete
for line in result.stdout.splitlines():
    if ':' in line:
        parts = line.split()
        pkg = parts[0].split(':')[1]
        installer = parts[1].split('=')[1] if len(parts) > 1 and '=' in parts[1] else 'null'
        installer_map[pkg] = installer
        if installer == 'null':
            null_installers.add(pkg)

# Hole UIDs mit REJECT_ALL
result = subprocess.run(
    ['adb', 'shell', 'su', '-c', 'dumpsys netpolicy | grep "policy=262144"'],
    capture_output=True, text=True
)
reject_all_uids = re.findall(r'UID=(\d+)', result.stdout)

# Konvertiere UIDs zu Package-Names
reject_all_pkgs = set()
for uid in reject_all_uids:
    result = subprocess.run(
        ['adb', 'shell', 'su', '-c', f'cmd package list packages --uid {uid}'],
        capture_output=True, text=True
    )
    if result.stdout and ':' in result.stdout:
        pkg = result.stdout.strip().split()[0].split(':')[1]
        reject_all_pkgs.add(pkg)

# Berechne Mengen
intersection = null_installers & reject_all_pkgs
only_null = null_installers - reject_all_pkgs
only_reject = reject_all_pkgs - null_installers

# Ausgabe - ALLE Apps
print("📊 SCHNITTMENGE (installer=null UND REJECT_ALL):")
print("=" * 60)
for pkg in sorted(intersection):
    print(f"  {pkg}")
print(f"\nAnzahl: {len(intersection)} Apps\n")

print("🟢 NUR installer=null (keine POLICY_REJECT_ALL - diese Apps sollten funktionieren!):")
print("=" * 60)
for pkg in sorted(only_null):
    installer = installer_map.get(pkg, 'unknown')
    print(f"  {pkg} (installer={installer})")
print(f"\nAnzahl: {len(only_null)} Apps\n")

print("🔴 NUR REJECT_ALL (haben einen Installer - mysteriös!):")
print("=" * 60)
if only_reject:
    for pkg in sorted(only_reject):
        installer = installer_map.get(pkg, 'NICHT IN LISTE')
        print(f"  {pkg} (installer={installer})")
else:
    print("  (keine)")
print(f"\nAnzahl: {len(only_reject)} Apps\n")

# Zusammenfassung
print("📈 ZUSAMMENFASSUNG:")
print("=" * 60)
print(f"Gesamt installer=null:     {len(null_installers)}")
print(f"Gesamt REJECT_ALL:         {len(reject_all_pkgs)}")
print(f"Schnittmenge (beide):      {len(intersection)}")
print(f"Nur installer=null:        {len(only_null)}")
print(f"Nur REJECT_ALL:            {len(only_reject)}")

# Validiere Hypothese
print("\n🔬 HYPOTHESE-CHECK:")
print("=" * 60)
if len(only_reject) == 0:
    print("✅ BESTÄTIGT: Alle Apps mit REJECT_ALL haben installer=null")
    print("   → installer=null ist die EINZIGE Ursache für REJECT_ALL")
else:
    print(f"⚠️  ÜBERRASCHUNG: {len(only_reject)} Apps haben REJECT_ALL TROTZ Installer!")
    print("   → Es gibt andere Ursachen außer installer=null")
    print("\n   Details der mysteriösen Apps:")
    for pkg in sorted(only_reject):
        installer = installer_map.get(pkg, 'NICHT IN pm list packages -i')
        print(f"     • {pkg}")
        print(f"       Installer: {installer}")

if len(only_null) > 0:
    print(f"\n✅ {len(only_null)} Apps mit installer=null funktionieren trotzdem")
    print("   → installer=null allein reicht nicht für REJECT_ALL")
 
# Zusätzliche Analyse: Welche Installer haben die REJECT_ALL Apps?
print("\n📊 INSTALLER-VERTEILUNG bei REJECT_ALL Apps:")
print("=" * 60)
installer_counts = {}
for pkg in reject_all_pkgs:
    installer = installer_map.get(pkg, 'UNBEKANNT')
    installer_counts[installer] = installer_counts.get(installer, 0) + 1

for installer, count in sorted(installer_counts.items(), key=lambda x: x[1], reverse=True):
    print(f"  {installer}: {count} Apps")
EOF

Das Ergebnis ist, dass in dem Abschnitt "NUR REJECT_ALL (HABEN Installer - mysteriös!):" kein F-Droid als Wert für die gefundenen Apps eingetragen ist, jedoch der Aurora Store (installer=com.aurora.store) in jeder gefunden App dort. Das bedeutet, dass F-Droid das Upgrade irgendwie nicht überstanden hat oder ich schon vorher diese Werte hatte.
Hier der Code für alle Apps mit F-Droid und Aurora mit UID:
Code:
adb shell su -c "pm list packages -U -i" | grep "installer=org.fdroid.fdroid" | sort
adb shell su -c "pm list packages -U -i" | grep "installer=com.aurora.store" | sort

Nun, es liegt doch nicht an installer=null, da ich Apps habe, die einen Wert besizen aber jedoch in der POLICY_REJECT_ALL eingetragen worden sind. Mist, jetzt muss eine andere Theorie her, um den Root-Cause zu erklären.
 
Zuletzt bearbeitet:
Android zeigt durchgestrichenes Netzwerk-Symbol beim öffnen von Apps
Du meinst das hier?
1000110404.png
Das kannst du in der Regel selbst provozieren indem die Netzwerkberechtigung bei den einzelnen Apps entziehst oder gewährst. Normalerweise haben alle Apps bei Installation Netzwerkberechtigungen, aber wer sagt denn, dass der Schalter die durch das Update nicht umgesprungen ist.

Einstellungen => Apps => Alle Apps => Beabsichtigte App => Mobile Datennutzung => Schalter "Netzwerkzugriff erlauben"

Greetz
 
Hallo @Lhotze,
Du meinst das hier?
Anhang anzeigen 6659
Das kannst du in der Regel selbst provozieren indem die Netzwerkberechtigung bei den einzelnen Apps entziehst oder gewährst. Normalerweise haben alle Apps bei Installation Netzwerkberechtigungen, aber wer sagt denn, dass der Schalter die durch das Update nicht umgesprungen ist.

Einstellungen => Apps => Alle Apps => Beabsichtigte App => Mobile Datennutzung => Schalter "Netzwerkzugriff erlauben"

Greetz
danke für deine Nachricht. Ich hab das nun ausprobiert mit einer App und wollte schauen wie das eingetragen wird. Jetzt habe ich diesen Code mit allen POLICY_REJECT_ALL Apps und mit Installer Info:
Bash:
python3 << 'EOF'
import subprocess
import re

print("=== APPS MIT POLICY_REJECT_ALL (262144) ===\n")

# Hole UIDs mit REJECT_ALL
result = subprocess.run(
    ['adb', 'shell', 'su', '-c', 'dumpsys netpolicy | grep "policy=262144"'],
    capture_output=True, text=True
)
reject_all_uids = re.findall(r'UID=(\d+)', result.stdout)

print(f"Gefunden: {len(reject_all_uids)} UIDs mit REJECT_ALL\n")

# Konvertiere UIDs zu Package-Names
reject_all_apps = []
for uid in reject_all_uids:
    result = subprocess.run(
        ['adb', 'shell', 'su', '-c', f'cmd package list packages --uid {uid}'],
        capture_output=True, text=True
    )
    if result.stdout and ':' in result.stdout:
        pkg = result.stdout.strip().split()[0].split(':')[1]
        reject_all_apps.append((uid, pkg))

# Sortiert nach Package-Name
for uid, pkg in sorted(reject_all_apps, key=lambda x: x[1]):
    print(f"UID {uid}: {pkg}")

print(f"\n📈 ZUSAMMENFASSUNG:")
print(f"Anzahl Apps mit REJECT_ALL: {len(reject_all_apps)}")
EOF

Hier noch die langsame Variante mit zusätzlichen Application Labels:
Bash:
python3 << 'EOF'
import subprocess
import re
import os

print("=== APPS MIT POLICY_REJECT_ALL (262144) ===\n")

# Hole UIDs mit REJECT_ALL
result = subprocess.run(
    ['adb', 'shell', 'su', '-c', 'dumpsys netpolicy | grep "policy=262144"'],
    capture_output=True, text=True
)
reject_all_uids = re.findall(r'UID=(\d+)', result.stdout)

print(f"Gefunden: {len(reject_all_uids)} UIDs mit REJECT_ALL\n")

# Konvertiere UIDs zu Package-Names
reject_all_apps = []
for uid in reject_all_uids:
    result = subprocess.run(
        ['adb', 'shell', 'su', '-c', f'cmd package list packages --uid {uid}'],
        capture_output=True, text=True
    )
    if result.stdout and ':' in result.stdout:
        pkg = result.stdout.strip().split()[0].split(':')[1]
        reject_all_apps.append((uid, pkg))

print("Hole App-Labels...\n")

# Hole Labels für alle Packages
pkg_labels = {}
for uid, pkg in reject_all_apps:
    # Hole APK-Pfad
    result = subprocess.run(
        ['adb', 'shell', 'pm', 'path', pkg],
        capture_output=True, text=True
    )
    if result.stdout and ':' in result.stdout:
        apk = result.stdout.strip().split(':')[1].strip()
        
        # Pull APK
        subprocess.run(
            ['adb', 'pull', apk, '/tmp/temp.apk'],
            capture_output=True
        )
        
        # Extrahiere Label mit aapt
        result = subprocess.run(
            ['aapt', 'dump', 'badging', '/tmp/temp.apk'],
            capture_output=True, text=True
        )
        
        label_match = re.search(r"application-label:'([^']+)'", result.stdout)
        if label_match:
            pkg_labels[pkg] = label_match.group(1)
        else:
            pkg_labels[pkg] = pkg  # Fallback: Package-Name
        
        # Cleanup
        try:
            os.remove('/tmp/temp.apk')
        except:
            pass

# Sortiert nach Label ausgeben
print("\n=== ERGEBNIS ===\n")
for uid, pkg in sorted(reject_all_apps, key=lambda x: pkg_labels.get(x[1], x[1])):
    label = pkg_labels.get(pkg, pkg)
    print(f"UID {uid}: {pkg} -> {label}")

print(f"\n📈 ZUSAMMENFASSUNG:")
print(f"Anzahl Apps mit REJECT_ALL: {len(reject_all_apps)}")
EOF

Wenn ich nun manuell App A, laut deiner Beschreibung, die mobile Datennutzungsrechte gebe, dann ist die App A nicht mehr in der POLICY_REJECT_ALL drin. Wenn ich es rückgängigi mache, dann ist sie wieder in der POLICY_REJECT_ALL drin.

Wie geht das über adb shell? Ich habe wenig Zeit die 150+ durchzuklicken. Weiß das einer von euch?
 
Zuletzt bearbeitet:
Ich versuche es mal mit iptables... die Policy mit aktivierten Datennutzung ist 0 (alles aktiv, außer der Punkt unbegrenze Nutzung von mobilen Daten).
 
Update: ShiftOS/Android 15 nutzt eBPF für pro-UID Firewall-Regeln. Das ist moderner und performanter als iptables. Die eBPF-Maps liegen hier:
Bash:
adb shell su -c "ls -la /sys/fs/bpf/"

Somit ist leider die Idee mit iptables weg vom Tisch, aaaber glücklicherweise hat Claude Sonnet 4.5 mir einen anderen Weg vorgeschlagen und der klappt!

Hier der Code der es hinkriegt. Die Werte 1 und 2 schalten es ab. Der Wert 3 schaltet es an.
Bash:
adb shell su -c "service call netpolicy [Wert 1,2 oder 3] i32 [UID-von-der-App] i32 262144"

Was noch offen bleibt ist der Root-Cause. Was wird in der Update-Phase gemacht, das es restriktiv wird? Liegt es an der neuen Android 15 Version?
Claude Sonnet 4.5 Erklärung dazu:

Zusammenfassung der Änderungen 13→15:​

FeatureAndroid 13Android 15
Firewall-Backendiptables + eBPFHauptsächlich eBPF
ndc-FunktionalitätVoll funktionalStark reduziert
service call IDsAndere NummernNeue IDs (1,2,3)
Default RestrictionsLockererStrenger
RESTRICTED_MODERudimentärVoll implementiert
Privacy ControlsBasisErweitert
 
Zuletzt bearbeitet: