244 lines
11 KiB
Markdown
244 lines
11 KiB
Markdown
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](https://github.com/systemd/systemd/issues/21123).
|
||
|
||
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](https://forum.endeavouros.com/t/no-internet-dns-issues-after-update-networkmanager-systemd-resolved-on-kde/69865).
|
||
|
||
---
|
||
|
||
### 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:
|
||
|
||
```bash
|
||
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:
|
||
```bash
|
||
sudo nano /etc/NetworkManager/NetworkManager.conf
|
||
```
|
||
|
||
2. In the `[main]` section, add or uncomment the `dns` line and set it to `systemd-resolved`:
|
||
```ini
|
||
[main]
|
||
plugins=ifupdown,keyfile
|
||
dns=systemd-resolved
|
||
|
||
[ifupdown]
|
||
managed=false
|
||
```
|
||
|
||
3. Save the file and exit.
|
||
|
||
#### Step 3: Enable `systemd-resolved` and Create the Correct Symlink
|
||
|
||
1. First, ensure the service is running:
|
||
```bash
|
||
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.
|
||
```bash
|
||
# 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.
|
||
|
||
```bash
|
||
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:
|
||
|
||
```bash
|
||
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:
|
||
```bash
|
||
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:**
|
||
```ini
|
||
[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.
|
||
|
||
```bash
|
||
# 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
|
||
```
|
||
|
||
#### Step 3: Recreate `/etc/resolv.conf` as a Symlink
|
||
|
||
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.
|
||
```bash
|
||
sudo mv /etc/resolv.conf /etc/resolv.conf.bak
|
||
```
|
||
This command safely renames the file.
|
||
|
||
2. Create the new symbolic link:
|
||
```bash
|
||
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:
|
||
```bash
|
||
sudo systemctl restart NetworkManager
|
||
```
|
||
|
||
2. **Verify the symlink:** Check that `/etc/resolv.conf` is now a link.
|
||
```bash
|
||
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`.
|
||
```bash
|
||
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`).
|
||
```bash
|
||
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:**
|
||
```bash
|
||
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`:**
|
||
```bash
|
||
sudo mv /etc/resolv.conf.bak /etc/resolv.conf
|
||
```
|
||
|
||
2. **Edit `NetworkManager.conf` again:**
|
||
```bash
|
||
sudo nano /etc/NetworkManager/NetworkManager.conf
|
||
```
|
||
Remove the `dns=systemd-resolved` line, or change it back to `dns=default`.
|
||
|
||
3. **Restart NetworkManager:**
|
||
```bash
|
||
sudo systemctl restart NetworkManager
|
||
```
|