dotfiles/network-manager-resolvd-config.md
2025-11-18 16:39:36 +01:00

11 KiB
Raw Permalink Blame History

Excellent question. The fact that this happens sometimes is the key to understanding the problem. It points to a race condition or a conflict between the different services managing your network, specifically NetworkManager and systemd-resolved, based on the information your router is providing.

Here's a breakdown of the moving parts and why they sometimes fail to cooperate.

The Actors on Your System

  1. The Router (The Source of Truth):

    • When you connect to Wi-Fi, your router provides network configuration information.
    • For IPv4, it uses DHCP to give you an IP address, a gateway, and DNS servers.
    • For IPv6, it uses Router Advertisements (RAs) and/or DHCPv6. RAs can include information about which DNS servers to use.
    • The Core Issue: Some routers, especially consumer-grade ones, are poorly configured. They advertise their own link-local (fe80::...) address as the DNS server in their IPv6 RAs. This is technically valid but problematic for many client systems.
  2. NetworkManager (The Connection Manager):

    • Its job is to manage network interfaces (like wlp1s0). It brings the Wi-Fi up, handles authentication, and listens for the configuration data from your router (both DHCP and RAs).
    • When it receives the DNS server information, it needs to pass it on to the system's resolver.
  3. systemd-resolved (The DNS Resolver):

    • This is the service that actually performs the DNS lookups for your applications (like your web browser). It's designed to be a central clearinghouse for DNS. It maintains a list of all DNS servers learned from all network interfaces, caches results, and can handle advanced protocols like DNS-over-TLS.

The Conflict: Who Controls /etc/resolv.conf?

The problem arises from how NetworkManager and systemd-resolved are configured to interact, and which one gets the final say over the /etc/resolv.conf file. There are two common modes:

  1. Mode A: NetworkManager is in control (Your likely situation).

    • In this setup, NetworkManager takes the DNS server information it receives from the router and writes it directly into /etc/resolv.conf.
    • The file comment # Generated by NetworkManager is the evidence for this.
    • When your router sends that bad fe80::1%wlp1s0 address, NetworkManager dutifully writes it into the file, and your system's DNS breaks.
  2. Mode B: systemd-resolved is in control (The modern, recommended setup).

    • NetworkManager is configured to pass all the DNS information it learns to systemd-resolved via an internal system bus (D-Bus).
    • systemd-resolved then manages the DNS servers internally.
    • /etc/resolv.conf is then symlinked to a file managed by systemd-resolved (like /run/systemd/resolve/stub-resolv.conf), which contains only nameserver 127.0.0.53. This points all system queries to the local systemd-resolved daemon, which then intelligently forwards them to the correct upstream servers.

Why "Sometimes"? The Race Condition

The fact that it's intermittent strongly suggests a race condition between your IPv4 and IPv6 configuration on startup or reconnect.

  • Scenario 1 (Everything Works): Your system connects, the IPv4 DHCP negotiation finishes first. NetworkManager gets a valid IPv4 DNS server (e.g., 8.8.8.8 or your ISP's) and writes it to /etc/resolv.conf. A moment later, the problematic IPv6 RA arrives, but NetworkManager might prioritize or already be using the working IPv4 server.
  • Scenario 2 (DNS Breaks): Your system connects, but the IPv6 Router Advertisement is processed first. NetworkManager receives the fe80::1%wlp1s0 address and writes it to /etc/resolv.conf. DNS is broken from the start. A few moments later, the IPv4 address might arrive, but NetworkManager might not update the config file, leaving the broken one in place. This can also happen after waking from suspend. Such intermittent failures are a known class of bugs github.com.

As one user on a forum described a similar situation, "After doing a -Syu and reboot, I no longer have access to the internet system-wide. I can ping 8.8.8.8 but not ping google.com" this is the classic symptom you are experiencing forum.endeavouros.com.


How to Verify and Fix This Permanently

The best solution is to switch to the modern setup where systemd-resolved is in full control.

Step 1: Check Your Current resolv.conf Setup

Run this command to see what /etc/resolv.conf really is:

ls -l /etc/resolv.conf
  • If it shows a file (-rw-r--r-- ...), you are in the problematic Mode A.
  • If it shows a symlink (lrwxrwxrwx ... -> ../run/systemd/resolve/stub-resolv.conf), you are in Mode B, but NetworkManager might still be misconfigured.

Step 2: Configure NetworkManager to Use systemd-resolved

  1. Edit the main NetworkManager configuration file:

    sudo nano /etc/NetworkManager/NetworkManager.conf
    
  2. In the [main] section, add or uncomment the dns line and set it to systemd-resolved:

    [main]
    plugins=ifupdown,keyfile
    dns=systemd-resolved
    
    [ifupdown]
    managed=false
    
  3. Save the file and exit.

  1. First, ensure the service is running:

    sudo systemctl enable systemd-resolved.service
    sudo systemctl start systemd-resolved.service
    
  2. Next, remove the static file and create the correct symlink. This forces the system to use the local systemd-resolved stub resolver.

    # IMPORTANT: Back up the old file first
    sudo mv /etc/resolv.conf /etc/resolv.conf.bak
    
    # Create the symlink
    sudo ln -s /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
    

Step 4: Restart and Verify

Restart NetworkManager to apply all the changes.

sudo systemctl restart NetworkManager

Now, your DNS should work reliably. Check your resolv.conf to confirm it points to 127.0.0.53. To see the actual DNS servers your system is now using (which it gets from NetworkManager), use the resolvectl command:

resolvectl status

This will give you a detailed report, showing the DNS servers for each interface (like wlp1s0). Even if the problematic fe80:: address is listed there, systemd-resolved is smart enough to ignore or fall back from it if it doesn't work, preventing a total DNS outage.

Excellent! You've correctly identified that you're in "Mode A," where NetworkManager writes directly to /etc/resolv.conf. Switching to the modern approach where systemd-resolved handles everything is the most robust and permanent solution.

Let's walk through the process step-by-step. This is a standard and safe procedure on most modern Linux distributions.


Step-by-Step Guide to Switch to systemd-resolved

We are going to reconfigure your system so that:

  1. NetworkManager passes DNS information to systemd-resolved.
  2. systemd-resolved manages all DNS lookups.
  3. /etc/resolv.conf points to the local systemd-resolved service.

Step 1: Configure NetworkManager

First, we need to tell NetworkManager to stop managing /etc/resolv.conf by itself and start sending its DNS information to systemd-resolved.

  1. Open the NetworkManager.conf file with a text editor and sudo privileges:

    sudo nano /etc/NetworkManager/NetworkManager.conf
    
  2. Find the [main] section. Add a dns line and set it to systemd-resolved. If the line already exists but is set to something else (like default), change it.

    Your file should look like this:

    [main]
    plugins=ifupdown,keyfile
    dns=systemd-resolved
    
    [ifupdown]
    managed=false
    

    (Note: You might have other settings in the [main] section. Just make sure the dns=systemd-resolved line is present and correct.)

  3. Save the file and exit the editor (in nano, press Ctrl+O, then Enter to save, and Ctrl+X to exit).

Step 2: Enable and Start systemd-resolved

Now, let's make sure the systemd-resolved service is active and will start automatically on boot.

# Enable the service to start on every boot
sudo systemctl enable systemd-resolved.service

# Start the service right now
sudo systemctl start systemd-resolved.service

This is the most important step. We will replace the static file that NetworkManager used to write with a symbolic link to the resolv.conf file that systemd-resolved provides.

  1. Important: Back up your current resolv.conf file. This lets you easily revert if something goes wrong.

    sudo mv /etc/resolv.conf /etc/resolv.conf.bak
    

    This command safely renames the file.

  2. Create the new symbolic link:

    sudo ln -s /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
    

    This links /etc/resolv.conf to the "stub" resolver file, which correctly points all DNS queries to the local systemd-resolved daemon.

Step 4: Restart NetworkManager and Verify

Finally, restart NetworkManager to apply all the changes and verify that everything is working.

  1. Restart the service:

    sudo systemctl restart NetworkManager
    
  2. Verify the symlink: Check that /etc/resolv.conf is now a link.

    ls -l /etc/resolv.conf
    

    The output should look like this (colors and dates will vary):

    lrwxrwxrwx 1 root root 39 Nov 18 10:30 /etc/resolv.conf -> /run/systemd/resolve/stub-resolv.conf
    
  3. Verify the content: Check what's inside the new resolv.conf.

    cat /etc/resolv.conf
    

    The output should show 127.0.0.53 as the nameserver. This is the local systemd-resolved stub resolver.

    # This file is managed by man:systemd-resolved(8). Do not edit.
    ...
    nameserver 127.0.0.53
    options edns0 trust-ad
    
  4. Check the REAL DNS servers: Use resolvectl to see which DNS servers systemd-resolved is actually using (which it learned from NetworkManager).

    resolvectl status
    

    This will give you a detailed report. Look for the section corresponding to your Wi-Fi interface (wlp1s0). You will see the actual IP addresses of the DNS servers it is using. Even if the problematic fe80:: address is listed, systemd-resolved is much more resilient and will fall back to other working servers.

  5. Final Test:

    ping archlinux.org
    

    If you get a reply, congratulations! Your DNS is now being managed robustly by systemd-resolved.


How to Revert (If Needed)

If anything goes wrong, you can easily go back to the old setup:

  1. Restore the old resolv.conf:

    sudo mv /etc/resolv.conf.bak /etc/resolv.conf
    
  2. Edit NetworkManager.conf again:

    sudo nano /etc/NetworkManager/NetworkManager.conf
    

    Remove the dns=systemd-resolved line, or change it back to dns=default.

  3. Restart NetworkManager:

    sudo systemctl restart NetworkManager