2 of 3

Network Fault DiagnosisLesson 2 of 3

Addresses, routes and name resolution

Repair NetworkManager profiles, routes and DNS persistently, and understand which source answers a name.

  • nmcli connection show
  • nmcli connection modify
  • nmcli device status
  • ip route get
  • ip route add
  • ip addr
  • nmcli -g
  • /etc/hosts
  • /etc/nsswitch.conf
  • /etc/resolv.conf
  • getent
  • dig
  • nmcli connection reload
  • ip neigh

50 min3 exercises

After this lesson you can

  • Change an address, gateway, DNS server and a static route in a NetworkManager profile so it survives a reboot.
  • Explain which file or server answers a name, in what order, and why dig and getent can disagree.
  • Find a wrong address, a duplicate address, a missing default route and a wrong DNS server from the machine itself.

The idea

Three kinds of settings put a machine on the network: its address (who am I), its routes (how do I reach others), and its resolvers (how do names become addresses). On RHEL all three are owned by NetworkManager, which stores them in profiles (also called connections) and applies them to devices (interfaces).

device (eth0)  <--- activated with --->  connection profile (settings stored in a keyfile)
   |                                           |
   +-- live state: ip addr, ip route           +-- /etc/NetworkManager/system-connections/NAME.nmconnection

The difference between the two halves is the root of most “it worked until the reboot” problems:

  • Commands such as ip addr add, ip route add and echo ... > /etc/resolv.conf change the live state only.
  • nmcli connection modify changes the profile; nmcli connection up (or nmcli device reapply) applies it to the device.

On RHEL 10, profiles are keyfiles, plain INI files. The older ifcfg files in /etc/sysconfig/network-scripts/ are no longer used; if you find one on an upgraded machine, it was migrated or is ignored. After editing a keyfile directly, run nmcli connection reload and bring the connection up again.

Reading and changing a profile

nmcli device status                         # devices and their state
nmcli connection show                       # all profiles
nmcli connection show NAME                  # every setting of a profile
nmcli -f ipv4 connection show NAME          # only the ipv4 group
nmcli connection modify NAME ipv4.method manual ipv4.addresses 192.168.50.12/24 ipv4.gateway 192.168.50.1
nmcli connection modify NAME +ipv4.dns 192.168.50.1      # + adds, - removes
nmcli connection up NAME                    # apply
SettingMeaning
ipv4.methodauto (DHCP), manual (static), disabled, link-local
ipv4.addressesADDR/PREFIX, comma-separated for several
ipv4.gatewayThe default gateway; sets the default route
ipv4.dns, ipv4.dns-searchDNS servers and search domains
ipv4.ignore-auto-dnsIgnore DNS handed out by DHCP
ipv4.routesStatic routes: "10.20.0.0/16 192.168.50.254 100" (network, next hop, optional metric)
ipv4.never-defaultDo not use this connection for the default route
connection.autoconnectActivate at boot

Routes: which way out?

ip route get ADDRESS answers the real question “which route would be used for this destination?”

ip route
ip route get 10.20.1.5
default via 192.168.50.1 dev eth0 proto static metric 100
10.20.0.0/16 via 192.168.50.254 dev eth0 proto static metric 100
192.168.50.0/24 dev eth0 proto kernel scope link src 192.168.50.12 metric 100
10.20.1.5 via 192.168.50.254 dev eth0 src 192.168.50.12 uid 1000
    cache

(Representative output.) The most specific route (longest prefix) wins; default is used when nothing else matches. ip route get also shows the source address that will be used. A missing default route gives Network is unreachable for anything off-subnet; a default route through a gateway that does not answer gives timeouts. Check the gateway: ip neigh show 192.168.50.1 should show a MAC address with state REACHABLE, STALE or DELAY; FAILED or INCOMPLETE means ARP got no answer.

Names: who answers?

A name lookup in an application goes through the C library, which consults sources in the order given in /etc/nsswitch.conf:

hosts:      files myhostname dns
StepSourceNotes
files/etc/hostsFirst match wins; an old line here beats DNS
myhostnameThe machine’s own host name
dnsThe servers in /etc/resolv.confAsked in order; the next one is tried only after a timeout

/etc/resolv.conf on RHEL is written by NetworkManager from the active profile (a header says so). Edits are lost at the next reconnect. Change ipv4.dns and ipv4.dns-search in the profile instead.

Tools differ in what they test:

ToolUsesUse it for
getent hosts NAMEThe full order (nsswitch.conf)“What will applications get?”
dig NAME / dig NAME @SERVERDNS only“What does this DNS server say?”
host NAME, nslookupDNS onlyQuick lookups
ping NAME, curl NAMEThe full orderEnd-to-end

A disagreement between dig and getent always means the answer comes from somewhere other than DNS (/etc/hosts), or from a different DNS server than the one you named with @.

Try it

Static configuration, persistently

CON=$(nmcli -g NAME connection show --active | head -1)
sudo nmcli connection modify "$CON" ipv4.method manual \
  ipv4.addresses 192.168.50.12/24 ipv4.gateway 192.168.50.1 \
  ipv4.dns 192.168.50.1 ipv4.dns-search lab.example \
  +ipv4.routes "10.20.0.0/16 192.168.50.254"
sudo nmcli connection up "$CON"
ip -br addr
cat /etc/resolv.conf
lo               UNKNOWN        127.0.0.1/8 ::1/128
eth0             UP             192.168.50.12/24 fe80::5054:ff:fe12:3456/64
# Generated by NetworkManager
search lab.example
nameserver 192.168.50.1

The stored profile now has the same values:

sudo cat /etc/NetworkManager/system-connections/eth0.nmconnection
[connection]
id=eth0
type=ethernet
interface-name=eth0

[ipv4]
address1=192.168.50.12/24,192.168.50.1
dns=192.168.50.1;
dns-search=lab.example;
method=manual
route1=10.20.0.0/16,192.168.50.254

Name disagreement

getent hosts app.lab.example
dig +short app.lab.example @192.168.50.1
192.168.50.99   app.lab.example
192.168.50.20

The two answers differ because getent read /etc/hosts first (files is before dns) and dig asked the DNS server. Remove the stale line from /etc/hosts, and getent follows. If instead both dig and getent give the wrong address, the DNS server itself is wrong (stale record), and you must fix it there or point to another server.

Duplicate addresses and ARP

Two hosts with the same IP address cause intermittent failures: some packets reach one, some the other. Check:

sudo arping -D -I eth0 -c2 192.168.50.12    # DAD: is another host answering for my address?
ip neigh show | grep 192.168.50.12

A reply to arping -D means a conflict. The neighbour’s MAC address in ip neigh changing back and forth is the same sign.

When it still does not work

SymptomCauseFix
Setting disappears after rebootUsed ip or edited resolv.confPut it in the profile with nmcli connection modify
ipv4.gateway set but no default routeMethod is auto with a different route, or never-default=yesCheck ip route, nmcli connection show NAME | grep default
Two default routesTwo active connectionsLower the metric of the preferred one (ipv4.route-metric), or ipv4.never-default yes on the other
Connection activating foreverDHCP unavailableCheck the link, VLAN, DHCP server; use ipv4.method manual
Slow logins, slow sudoA dead DNS server first in the list; reverse lookups timing outFix the order; UseDNS no for sshd is a workaround only
Name resolves to IPv6, connect failsAAAA record with no IPv6 routecurl -4; fix IPv6 or remove the AAAA record
Profile edited by hand has no effectNot reloadednmcli connection reload && nmcli connection up NAME

Going further

Hostnames. hostnamectl set-hostname node1.lab.example writes /etc/hostname; the static name, transient name and pretty name are separate (hostnamectl status). Services that “cannot find themselves” are usually missing a line in /etc/hosts for their own name. Beyond the exam: bonds, bridges and VLANs are also NetworkManager profiles with a master relationship; nmcli device reapply applies changes without a full reconnect where possible; and systemd-resolved is available but not the default on RHEL.

Practice

0 of 3 done

Do these on your own system. They get harder. Check each result, then tick it off.

  1. Warm-up

    What does NetworkManager have?

    List the connection profiles and which device each is on. For the active one, print its method (ipv4.method), addresses, gateway, DNS servers and whether it connects automatically. Name the file that stores the profile.

    Check your result
    • nmcli connection show lists the profiles and nmcli device status shows connected for one.
    • nmcli -f ipv4.method,ipv4.addresses,ipv4.gateway,ipv4.dns,connection.autoconnect connection show "$CON" prints the values.
    • The file is /etc/NetworkManager/system-connections/<name>.nmconnection.
    Hint

    nmcli -g NAME connection show --active gets the profile name. nmcli connection show NAME prints every setting; -f filters. Profiles are keyfiles under /etc/NetworkManager/system-connections/ on RHEL 10.

    Solution
    nmcli connection show
    nmcli device status
    CON=$(nmcli -g NAME connection show --active | head -1)
    nmcli -f ipv4.method,ipv4.addresses,ipv4.gateway,ipv4.dns,connection.autoconnect connection show "$CON"
    sudo ls -l /etc/NetworkManager/system-connections/
  2. Practice

    Static address, gateway, DNS and a route

    On node2 configure its connection profile with: address 192.168.50.12/24, gateway 192.168.50.1, DNS 192.168.50.1 and search domain lab.example, plus a static route to 10.20.0.0/16 via 192.168.50.254. Apply it without a reboot, then verify the live state, the stored profile and that /etc/resolv.conf shows the DNS server. Prove the changes survive by bringing the connection down and up again.

    Check your result
    • ip -br addr shows 192.168.50.12/24; ip route shows the default via 192.168.50.1 and 10.20.0.0/16 via 192.168.50.254.
    • cat /etc/resolv.conf contains nameserver 192.168.50.1 and search lab.example.
    • sudo grep -E 'address|gateway|dns|route' /etc/NetworkManager/system-connections/*.nmconnection shows the same values.
    Hint

    nmcli connection modify NAME ipv4.method manual ipv4.addresses ... ipv4.gateway ... ipv4.dns ... ipv4.dns-search ... +ipv4.routes "10.20.0.0/16 192.168.50.254" then nmcli connection up NAME. Using ip addr add or ip route add changes only the running state.

    Solution
    CON=$(nmcli -g NAME connection show --active | head -1)
    sudo nmcli connection modify "$CON" ipv4.method manual \
      ipv4.addresses 192.168.50.12/24 ipv4.gateway 192.168.50.1 \
      ipv4.dns 192.168.50.1 ipv4.dns-search lab.example \
      +ipv4.routes "10.20.0.0/16 192.168.50.254"
    sudo nmcli connection up "$CON"
    ip -br addr; ip route; cat /etc/resolv.conf
    sudo nmcli connection down "$CON"; sudo nmcli connection up "$CON"; ip route
  3. Challenge

    dig works, the application fails

    Setup (node1):

    echo "192.168.50.99 app.lab.example" | sudo tee -a /etc/hosts
    CON=$(nmcli -g NAME connection show --active | head -1)
    sudo nmcli connection modify "$CON" ipv4.ignore-auto-dns yes ipv4.dns 192.168.50.254
    sudo nmcli connection up "$CON"

    dig +short app.lab.example @192.168.50.1 returns the right address 192.168.50.20, but curl http://app.lab.example/ goes to the wrong place and host/dig without a server just time out. Show (a) what the resolver order is, (b) which source answers for the name, (c) what resolv.conf really contains and who wrote it, and fix both faults so that getent hosts app.lab.example returns 192.168.50.20 and survives nmcli connection up.

    Check your result
    • getent hosts app.lab.example prints 192.168.50.20.
    • grep app.lab.example /etc/hosts prints nothing; nmcli -g ipv4.dns connection show "$CON" is 192.168.50.1.
    • grep -E '^hosts:' /etc/nsswitch.conf is understood: files comes before dns.
    Hint

    getent hosts follows nsswitch.conf; dig talks only to DNS. /etc/resolv.conf is generated by NetworkManager: do not edit it, change the profile (ipv4.dns). A line in /etc/hosts wins over DNS because files is first.

    Solution
    grep -E '^hosts:' /etc/nsswitch.conf
    getent hosts app.lab.example; dig +short app.lab.example @192.168.50.1
    head -3 /etc/resolv.conf
    sudo sed -i '/app.lab.example/d' /etc/hosts
    sudo nmcli connection modify "$CON" ipv4.ignore-auto-dns no ipv4.dns 192.168.50.1
    sudo nmcli connection up "$CON"
    getent hosts app.lab.example