If you use AdGuard CLI (adguard-cli) on Arch Linux or an Arch-based distribution like Garuda Linux, you might have encountered a frustrating issue: your desktop environment constantly displays a yellow warning icon or a "Limited Connectivity" / "No Internet" notification, even though your web browser opens websites without any trouble.
Checking the network status in your terminal confirms the symptom:
$ nmcli networking connectivity check Error: Timeout was reached.
In this post, we will break down why this happens deep within the Linux networking stack and how to solve it permanently in under two minutes.
1. How NetworkManager Probes for Internet
Linux desktop environments (KDE Plasma, GNOME, XFCE) rely on NetworkManager to check for active internet access and detect captive portals (like hotel or airport Wi-Fi).
Every few minutes, NetworkManager sends a lightweight HTTP request to an external endpoint:
- Test URL:
http://ping.archlinux.org/nm-check.txt - Expected Response:
NetworkManager is online
To verify that a specific physical network card (such as your Wi-Fi card wlp2s0) is actually connected, NetworkManager attaches a special Linux kernel socket flag called SO_BINDTODEVICE to the probe request.
What SO_BINDTODEVICE does: It binds the socket strictly to the physical network interface. The kernel enforces that all packets from this socket must only exit through that specific hardware card.
2. Why AdGuard CLI Triggers a Deadlock
When adguard-cli runs in system-wide auto mode (proxy_mode: 'auto'), its root helper sets up transparent firewall redirection rules (iptables / nftables) to intercept outgoing traffic.
By default, AdGuard intercepts this port range in ~/.local/share/adguard-cli/proxy.yaml:
filtered_ports: '80:5221,5300:49151'
Because port 80 is included, the firewall intercepts NetworkManager's probe and attempts to redirect it to AdGuard's local proxy listening on 127.0.0.1:3129 (the loopback interface).
The Kernel Routing Conflict:
- NetworkManager sends a probe to port 80 with the socket bound to the Wi-Fi card (
wlp2s0). - The firewall redirects the packet to
127.0.0.1(the loopback interfacelo). - The Linux kernel detects a conflict: A socket strictly bound to
wlp2s0is not permitted to communicate with the loopback interfacelo. - The kernel drops the packet immediately.
Why App Bypass Rules Fail: AddingNetworkManagerto theapps:bypass section insideproxy.yamldoes not fix this because AdGuard's user-space app bypass is only evaluated after a packet reaches port 3129. Since the kernel drops the packet during firewall redirection, AdGuard never sees it.
3. The Solution: Exclude Port 80 from Interception
NetworkManager tests connectivity using plain HTTP (port 80). Meanwhile, virtually all modern web browsing, ads, trackers, and telemetry operate over encrypted HTTPS (port 443).
By shifting AdGuard's filtered port range from 80 to 81:
- Port 80 traffic bypasses firewall redirection completely, allowing NetworkManager's probe to reach
ping.archlinux.orgdirectly through your Wi-Fi interface. - 100% of your ad-blocking protection remains intact, because HTTPS (port 443) and all other application ports remain fully filtered.
Step-by-Step Fix
Step 1: Edit AdGuard's Configuration
Open your AdGuard CLI configuration file in your text editor:
nano ~/.local/share/adguard-cli/proxy.yaml
Find the filtered_ports: setting (around line 10) and change 80 to 81:
# Before: filtered_ports: '80:5221,5300:49151' # After: filtered_ports: '81:5221,5300:49151'
Save and close the file (in Nano: press Ctrl + O, then Enter, then Ctrl + X).
Step 2: Restart AdGuard CLI
Restart the daemon so the root helper flushes the old firewall rules and applies the new port range:
adguard-cli restart
Step 3: Verify Full Connectivity
Ask NetworkManager to re-run the connectivity test:
nmcli networking connectivity check
It will now return:
full
You can also check the general network status:
nmcli general status
STATE CONNECTIVITY WIFI-HW WIFI WWAN-HW WWAN METERED connected full enabled enabled missing enabled no (guessed)
Alternative Fix: Disable NetworkManager Connectivity Checks
If you don't need captive portal detection (for example, on a home desktop) and prefer not to modify AdGuard, you can tell NetworkManager to stop probing altogether:
- Create a drop-in override file:
sudo nano /etc/NetworkManager/conf.d/20-connectivity.conf
- Add the following lines:
[connectivity] enabled=false
- Restart NetworkManager:
sudo systemctl restart NetworkManager
Key Takeaways
SO_BINDTODEVICEbinds a socket strictly to a physical network card. Redirecting such packets to127.0.0.1via NAT creates an invalid route that the Linux kernel drops by design.- Proxy-level application bypasses cannot process packets that are rejected at the kernel routing stage.
- Excluding port 80 from
filtered_portssolves the issue cleanly while keeping all your HTTPS ad blocking and privacy protection active.
Comments
Post a Comment