Skip to content

Network panel shows fake "Ethernet" instead of Wi-Fi when a VPN/tunnel owns the default route (hides Wi-Fi QR share button) #10107

Description

@sal-he

Summary

omarchy-network-status (and therefore the Network bar panel) misclassifies a VPN/tunnel interface as a wired Ethernet connection whenever that tunnel has installed itself as the default route for internet-bound traffic — even when the only real network device is Wi-Fi. This hides Wi-Fi-only UI, e.g. the panel's "Show QR code" Wi-Fi-sharing button, which only renders when info.type === "wifi".

Steps to reproduce

  1. Connect only to Wi-Fi (no Ethernet cable/adapter attached).
  2. Enable a VPN/tunnel client that takes over the default route for the internet probe target, e.g. Cloudflare WARP (warp-cli connect) or similar.
  3. Open the Network panel from the bar.

Expected

The panel shows the Wi-Fi network as the primary connection (SSID, signal, and the "Show QR code" share button).

Actual

The panel shows a fabricated "Ethernet (10gbit)" hero instead, with no way to reach the Wi-Fi QR-share button from the panel.

Root cause

omarchy-network-status --verbose (and the non-verbose print_status) picks the "primary" device via:

device=$(ip route get "$internet_probe" 2>/dev/null | awk '{ for (i = 1; i <= NF; i++) if ($i == "dev") { print $(i + 1); exit } }')

When a VPN client (Cloudflare WARP, in this case) is active, it installs itself as the route for that probe, so $device becomes the VPN's virtual interface (e.g. CloudflareWARP) instead of the real Wi-Fi adapter.

The script then classifies any non-wireless device as Ethernet:

if [[ ! -d /sys/class/net/$device/wireless ]]; then
  printf 'ethernet\t%s\t\t\n' "$device"
  return
fi

A tunnel interface has no wireless sysfs entry either, so it falls through to the ethernet branch. It then reads /sys/class/net/$device/speed, and virtual tunnel drivers commonly report a fixed placeholder (10000), which is where the bogus "10gbit" comes from.

Reproduced on this machine:

$ ip route get 1.1.1.1
1.1.1.1 dev CloudflareWARP table 65743 src 172.16.0.2 uid 1000

$ ls /sys/class/net/CloudflareWARP/wireless
ls: cannot access '/sys/class/net/CloudflareWARP/wireless': No such file or directory

$ cat /sys/class/net/CloudflareWARP/speed
10000

$ nmcli -t -f DEVICE,TYPE,STATE device status
wlp3s0:wifi:connected:Blue
CloudflareWARP:tun:connected (externally):CloudflareWARP
tailscale0:tun:connected (externally):tailscale0

Only wlp3s0 is a real network device; CloudflareWARP and tailscale0 are virtual tunnels, but the script has no way to tell them apart from a genuine wired NIC.

Suggested fix

Real network hardware exposes a device symlink to its backing PCI/USB device; virtual tunnel interfaces do not:

$ ls -la /sys/class/net/wlp3s0/device
lrwxrwxrwx 1 root root 0 ... /sys/class/net/wlp3s0/device -> ../../../0000:03:00.0

$ ls /sys/class/net/CloudflareWARP/device
ls: cannot access '/sys/class/net/CloudflareWARP/device': No such file or directory

Gating the ethernet classification on [[ -e /sys/class/net/$device/device ]] (or otherwise excluding devices without that symlink) would fix both print_status and print_verbose without needing to special-case specific VPN products.

The Network panel's bar-tray icon logic (Panel.qml's kind property, based on Quickshell's native NetworkManager DeviceType.Wired) does not have this bug — only the omarchy-network-status shell script's route-based detection does — which is why the tray icon correctly shows Wi-Fi while the opened panel's hero incorrectly shows Ethernet.

System

  • Omarchy: 4.0.2-1
  • Kernel: 7.1.9-arch1-2
  • NetworkManager: 1.58.1-1
  • Trigger: Cloudflare WARP client active and set as default route (also reproducible with Tailscale in a similar "exit node"/default-route configuration, though not tested directly)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions