Linux: nmcli, networkctl, resolvectl, ss, ethtool and the config files
ip shows and changes the live kernel state, but something else decides what that state should be at boot and when a cable is plugged in. On desktops that is NetworkManager; on servers it is systemd-networkd, Netplan, ifupdown or the legacy network-scripts. This page covers those managers, the DNS resolver, and the diagnostic tools that surround them.
Which manager is running?
systemctl is-active NetworkManager systemd-networkd
nmcli general status 2>/dev/null
networkctl list 2>/dev/null
ls /etc/netplan/ /etc/network/interfaces /etc/sysconfig/network-scripts/ 2>/dev/null
resolvectl status 2>/dev/null | head -5| Distribution | Default manager | Config location | DNS resolver |
|---|---|---|---|
| Ubuntu Desktop 18.04+ | NetworkManager (via Netplan renderer) | /etc/netplan/*.yaml, NM profiles in /etc/NetworkManager/system-connections/ | systemd-resolved |
| Ubuntu Server 18.04+ | systemd-networkd (via Netplan) | /etc/netplan/*.yaml | systemd-resolved |
| Debian 12 | ifupdown; NetworkManager on desktops | /etc/network/interfaces | /etc/resolv.conf (plain) |
| Fedora, RHEL 8/9, Rocky, Alma | NetworkManager | /etc/NetworkManager/system-connections/*.nmconnection (RHEL 8 still supports network-scripts) | NetworkManager writes /etc/resolv.conf; systemd-resolved on Fedora 33+ |
| Arch | None by default; user picks NetworkManager, systemd-networkd or iwd | depends | depends |
| openSUSE | wicked (server) or NetworkManager (desktop) | /etc/sysconfig/network/ifcfg-* | netconfig |
| Alpine | ifupdown-ng / BusyBox | /etc/network/interfaces | /etc/resolv.conf |
| Raspberry Pi OS (Bookworm+) | NetworkManager | NM profiles | NM |
| Raspberry Pi OS (Bullseye and earlier) | dhcpcd | /etc/dhcpcd.conf | dhcpcd |
Interface names
systemd's predictable network interface names replaced eth0/wlan0 in 2013 so that names stay stable across reboots and hardware changes. The prefix says the type, the rest says where the hardware is.
| Name | Meaning |
|---|---|
en, wl, ww | Ethernet, wireless LAN, wireless WAN (mobile broadband) |
eno1 | Onboard device, index 1 from firmware |
ens3 | PCI hotplug slot 3 (common in VMs) |
enp3s0 | PCI bus 3, slot 0 |
enp0s31f6 | PCI bus 0, slot 31, function 6 |
wlp2s0 | Wireless, PCI bus 2, slot 0 |
enx001122334455 | Named by MAC address (USB adapters) |
eth0, wlan0 | Kernel default names: containers, old distributions, Raspberry Pi OS, or net.ifnames=0 on the kernel command line |
lo | Loopback |
docker0, br-…, veth… | Docker bridge and container ends |
virbr0, vnet0 | libvirt/KVM |
tun0, tap0, wg0, ppp0, tailscale0 | VPNs and tunnels |
To get the old names back, add net.ifnames=0 biosdevname=0 to the kernel command line. To name an interface yourself, create a .link file in /etc/systemd/network/ matching on MAC and setting Name=lan0.
NetworkManager and nmcli
nmcli is the command-line client. It manages devices (hardware) and connections (profiles that can be applied to a device). Changes made with nmcli con mod are saved to disk and survive reboots.
Viewing
nmcli # overview: every device with addresses, routes, DNS
nmcli general status
nmcli device status # devices and their state
nmcli device show enp3s0 # full detail for one device
nmcli connection show # saved profiles
nmcli connection show "Wired connection 1" # every property of a profile
nmcli -g ip4.address device show enp3s0 # one field, script-friendly
nmcli -t -f DEVICE,STATE device # terse output$ nmcli device status
DEVICE TYPE STATE CONNECTION
enp3s0 ethernet connected Wired connection 1
wlp2s0 wifi disconnected --
docker0 bridge connected (externally) docker0
lo loopback connected (externally) loStatic IP with nmcli
sudo nmcli connection modify "Wired connection 1" \
ipv4.method manual \
ipv4.addresses 192.168.1.50/24 \
ipv4.gateway 192.168.1.1 \
ipv4.dns "1.1.1.1 1.0.0.1" \
ipv4.dns-search home.arpa
sudo nmcli connection up "Wired connection 1" # applyBack to DHCP
sudo nmcli connection modify "Wired connection 1" ipv4.method auto ipv4.addresses "" ipv4.gateway "" ipv4.dns ""
sudo nmcli connection up "Wired connection 1"Renew DHCP, restart networking
sudo nmcli connection down "Wired connection 1" && sudo nmcli connection up "Wired connection 1"
sudo nmcli device reapply enp3s0
sudo nmcli device disconnect enp3s0 && sudo nmcli device connect enp3s0
sudo nmcli networking off && sudo nmcli networking on
sudo systemctl restart NetworkManagerWi-Fi
nmcli device wifi list
nmcli device wifi list --rescan yes
sudo nmcli device wifi connect "MySSID" password "secret"
sudo nmcli device wifi connect "MySSID" password "secret" hidden yes
nmcli connection show --active
sudo nmcli connection delete "MySSID"
nmcli radio wifi off && nmcli radio wifi on
sudo nmcli device wifi hotspot ifname wlp2s0 ssid MyHotspot password "12345678"
nmcli -s connection show "MySSID" | grep psk # show the saved passwordOther useful modifications
# clone or randomise MAC
sudo nmcli con mod "Wired connection 1" ethernet.cloned-mac-address 02:11:22:33:44:55
sudo nmcli con mod "MySSID" wifi.cloned-mac-address random
# ignore DHCP-supplied DNS and use your own
sudo nmcli con mod "Wired connection 1" ipv4.ignore-auto-dns yes ipv4.dns 1.1.1.1
# disable IPv6 on a profile
sudo nmcli con mod "Wired connection 1" ipv6.method disabled
# MTU
sudo nmcli con mod "Wired connection 1" ethernet.mtu 1400
# route metric (lower = preferred)
sudo nmcli con mod "Wired connection 1" ipv4.route-metric 50
# add a static route
sudo nmcli con mod "Wired connection 1" +ipv4.routes "10.0.0.0/8 192.168.1.254"
# don't use this connection as the default route
sudo nmcli con mod "Wired connection 1" ipv4.never-default yes
# tell NetworkManager to leave an interface alone
sudo nmcli device set enp3s0 managed no
# add a new profile from scratch
sudo nmcli con add type ethernet ifname enp3s0 con-name lan ipv4.method manual ipv4.addresses 192.168.1.50/24 ipv4.gateway 192.168.1.1
# interactive editor
nmcli connection edit "Wired connection 1"The text UI nmtui offers the same operations in a menu, which is easier for one-off changes over SSH.
systemd-networkd and networkctl
systemd-networkd reads .network, .netdev and .link files from /etc/systemd/network/. It is common on servers, Arch, and Ubuntu Server (through Netplan).
networkctl list
networkctl status # overview with addresses, gateway, DNS
networkctl status enp3s0 # one interface, including DHCP lease and driver
networkctl lldp # LLDP neighbours (switch port names)
sudo networkctl reconfigure enp3s0
sudo networkctl renew enp3s0 # renew DHCP
sudo networkctl reload # re-read config files
sudo networkctl up enp3s0 / down enp3s0 # systemd 248+$ networkctl list
IDX LINK TYPE OPERATIONAL SETUP
1 lo loopback carrier unmanaged
2 enp3s0 ether routable configured
3 wlp2s0 wlan off unmanaged
3 links listed.# /etc/systemd/network/20-wired.network
[Match]
Name=enp3s0
[Network]
DHCP=yes
# or static:
# Address=192.168.1.50/24
# Gateway=192.168.1.1
# DNS=1.1.1.1
# DNS=1.0.0.1
[DHCPv4]
UseDNS=yes
RouteMetric=100Netplan (Ubuntu)
Netplan is a YAML front end that generates configuration for either NetworkManager or systemd-networkd, chosen by the renderer key. Files live in /etc/netplan/ and are applied in lexical order.
# /etc/netplan/50-cloud-init.yaml (Ubuntu Server example)
network:
version: 2
renderer: networkd
ethernets:
enp3s0:
dhcp4: true
dhcp6: true
# static alternative:
# enp3s0:
# dhcp4: false
# addresses: [192.168.1.50/24]
# routes:
# - to: default
# via: 192.168.1.1
# nameservers:
# addresses: [1.1.1.1, 1.0.0.1]
# search: [home.arpa]sudo netplan get # show the merged config
sudo netplan try # apply with automatic rollback after 120 s unless confirmed
sudo netplan apply
sudo netplan --debug apply
netplan status # Ubuntu 22.10+: live state per interfaceYAML indentation errors are the number one cause of Invalid YAML or Error in network definition. Use two spaces, no tabs. The older gateway4: key is deprecated in favour of routes:. The cloud-init file will be regenerated on cloud instances unless you disable cloud-init networking with a file in /etc/cloud/cloud.cfg.d/.
ifupdown (Debian)
# /etc/network/interfaces
auto lo
iface lo inet loopback
auto enp3s0
iface enp3s0 inet dhcp
# static alternative
# iface enp3s0 inet static
# address 192.168.1.50/24
# gateway 192.168.1.1
# dns-nameservers 1.1.1.1 1.0.0.1 # needs the resolvconf packagesudo ifdown enp3s0 && sudo ifup enp3s0
sudo ifup -a
sudo systemctl restart networking
ifquery --stateLegacy network-scripts (RHEL 7 and earlier)
# /etc/sysconfig/network-scripts/ifcfg-eth0
TYPE=Ethernet
BOOTPROTO=none
NAME=eth0
DEVICE=eth0
ONBOOT=yes
IPADDR=192.168.1.50
PREFIX=24
GATEWAY=192.168.1.1
DNS1=1.1.1.1
DNS2=1.0.0.1sudo ifdown eth0 && sudo ifup eth0
sudo systemctl restart network # RHEL 7
sudo nmcli connection reload # RHEL 8, which reads ifcfg files through NetworkManagerRHEL 9 removed the network-scripts package; profiles migrated to .nmconnection keyfiles. nmcli connection migrate converts them.
DHCP clients
If no manager is running, or you are in a rescue shell, drive the DHCP client directly.
# ISC dhclient (Debian/Ubuntu until 24.04, RHEL until 8)
sudo dhclient -r enp3s0 # release
sudo dhclient enp3s0 # obtain
sudo dhclient -v enp3s0 # verbose: see DISCOVER/OFFER/REQUEST/ACK
cat /var/lib/dhcp/dhclient.leases
# dhcpcd (Raspberry Pi OS Bullseye, Arch, Alpine)
sudo dhcpcd -k enp3s0 # release
sudo dhcpcd enp3s0
sudo dhcpcd -n enp3s0 # rebind/renew
dhcpcd -U enp3s0 # dump lease variables
# systemd-networkd's built-in client
sudo networkctl renew enp3s0
# NetworkManager's built-in client (default since NM 1.20)
sudo nmcli device reapply enp3s0
# BusyBox udhcpc
sudo udhcpc -i eth0Watching the exchange with sudo tcpdump -i enp3s0 -n port 67 or port 68 is the definitive way to see whether a DHCP server is answering at all.
DNS: resolvectl and resolv.conf
On any system running systemd-resolved (Ubuntu, Fedora, many others), /etc/resolv.conf is a symlink pointing at a stub file that lists only 127.0.0.53. The real upstream servers are shown by resolvectl.
resolvectl status # servers per interface, DNSSEC, DNS-over-TLS state
resolvectl dns # just the servers
resolvectl domain # search domains
resolvectl query example.com
resolvectl query -t MX example.com
resolvectl statistics # cache hits and misses
sudo resolvectl flush-caches
sudo resolvectl dns enp3s0 1.1.1.1 1.0.0.1 # set servers for this boot
sudo resolvectl domain enp3s0 home.arpa
sudo resolvectl revert enp3s0
ls -l /etc/resolv.conf
# older name for the same tool
systemd-resolve --status
sudo systemd-resolve --flush-caches$ resolvectl status
Global
Protocols: -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
resolv.conf mode: stub
Link 2 (enp3s0)
Current Scopes: DNS
Protocols: +DefaultRoute -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
Current DNS Server: 192.168.1.1
DNS Servers: 192.168.1.1
DNS Domain: homeTo make systemd-resolved use DNS-over-TLS, set DNSOverTLS=yes and DNS=1.1.1.1#cloudflare-dns.com in /etc/systemd/resolved.conf, then sudo systemctl restart systemd-resolved. Without systemd-resolved, /etc/resolv.conf is a plain file with nameserver, search and options lines, and there is no cache to flush unless you run nscd, dnsmasq or unbound. Flush DNS on Linux →
Name lookup order is set in /etc/nsswitch.conf on the hosts: line: typically files mdns4_minimal [NOTFOUND=return] dns, meaning hosts file, then mDNS for .local, then DNS. getent hosts example.com resolves a name the way applications do; dig and nslookup bypass all of that and talk to DNS directly.
Sockets: ss (and netstat)
ss -tulpn # TCP+UDP listening sockets with process (sudo for all PIDs)
ss -tan # all TCP, numeric
ss -tan state established
ss -tp dst 192.168.1.10
ss -s # summary counts
ss -tln sport = :22
ss -x # Unix domain sockets
ss -i # TCP internals: cwnd, rtt, retransmits
ss -K dst 203.0.113.5 # kill connections (needs CONFIG_INET_DIAG_DESTROY)$ sudo ss -tulpn
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
udp UNCONN 0 0 127.0.0.53%lo:53 0.0.0.0:* users:(("systemd-resolve",pid=612,fd=13))
tcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=891,fd=3))
tcp LISTEN 0 511 *:80 *:* users:(("nginx",pid=1203,fd=6))The flags mirror netstat's: t TCP, u UDP, l listening, p process, n numeric, a all. netstat -tulpn still works if net-tools is installed but is slower on busy hosts because it reads /proc/net/tcp rather than using netlink.
ethtool: link speed, duplex, driver, offloads
sudo ethtool enp3s0 # speed, duplex, auto-negotiation, link detected
ethtool -i enp3s0 # driver and firmware version
ethtool -S enp3s0 # detailed NIC statistics
ethtool -k enp3s0 # offload features (tso, gro, checksum)
sudo ethtool -K enp3s0 tso off gro off # turn offloads off (for capture accuracy or driver bugs)
sudo ethtool -s enp3s0 speed 100 duplex full autoneg off
sudo ethtool -s enp3s0 autoneg on
sudo ethtool -p enp3s0 10 # blink the port LED for 10 seconds to find the cable
ethtool -g enp3s0 # ring buffer sizes
sudo ethtool -G enp3s0 rx 4096
sudo ethtool -s enp3s0 wol g # Wake-on-LAN magic packet
ethtool --show-eee enp3s0Settings for enp3s0:
Supported ports: [ TP ]
Supported link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Speed: 1000Mb/s
Duplex: Full
Auto-negotiation: on
Port: Twisted Pair
Link detected: yesSpeed: 100Mb/s on a gigabit port with Duplex: Half means a cable fault (one pair broken) or a bad switch port; it is the classic cause of "my network is slow and ifconfig shows errors".
Wi-Fi: iw and iwconfig
iw dev # wireless interfaces
iw dev wlp2s0 link # SSID, BSSID, signal, bitrate
iw dev wlp2s0 info
sudo iw dev wlp2s0 scan | grep -E 'SSID|signal|freq'
iw dev wlp2s0 station dump # per-station stats (AP mode or connected)
iw reg get # regulatory domain
sudo iw reg set GB
iw list # hardware capabilities: bands, channels, modes
rfkill list # is the radio blocked?
sudo rfkill unblock wifi
iwconfig # legacy wireless-tools; may not be installed
iwgetid -r # just the SSID (wireless-tools)To connect without NetworkManager, use wpa_supplicant with wpa_passphrase, or iwd's iwctl (iwctl station wlan0 scan, iwctl station wlan0 connect SSID).
hostname and friends
hostname # short name
hostname -f # FQDN
hostname -I # all addresses on one line (capital i); useful in scripts
hostname -i # address per /etc/hosts; often 127.0.1.1 and not what you want
hostnamectl # static, transient and pretty names, plus OS info
sudo hostnamectl set-hostname server1
cat /etc/hostname /etc/hostsReading /proc and /sys directly
Everything the tools show comes from the kernel's virtual filesystems. In a minimal container or rescue image with no tools at all, these still work:
cat /proc/net/dev # counters per interface
cat /sys/class/net/enp3s0/address # MAC
cat /sys/class/net/enp3s0/operstate # up / down
cat /sys/class/net/enp3s0/speed # Mb/s
cat /sys/class/net/enp3s0/mtu
cat /sys/class/net/enp3s0/carrier # 1 = link
ls /sys/class/net/ # interface names
cat /proc/net/route # routes in hex
cat /proc/net/arp # ARP cache
cat /proc/net/if_inet6 # IPv6 addresses
cat /proc/sys/net/ipv4/ip_forward # forwarding on?
cat /proc/net/wirelessDiagnostics toolkit
| Tool | Package | Use |
|---|---|---|
ping, ping -6 | iputils | Reachability; ping -M do -s 1472 host tests MTU |
traceroute, tracepath, mtr | traceroute, iputils, mtr | Path and per-hop loss; mtr -rw host for a report; tracepath needs no root and shows path MTU |
dig, host, nslookup | bind-utils / dnsutils | DNS queries; dig +short, dig @1.1.1.1 example.com AAAA, dig -x 1.1.1.1 |
arping | iputils | ARP-level ping: sudo arping -I enp3s0 192.168.1.1; also finds duplicate IPs with -D |
nc / ncat | netcat / nmap-ncat | Port test: nc -zv host 443 |
curl -v, wget | curl, wget | HTTP-level tests; curl -4 / -6 forces a family |
tcpdump | tcpdump | Capture: sudo tcpdump -i enp3s0 -n host 192.168.1.1; -w file.pcap for Wireshark |
nmap | nmap | Scan your own network: nmap -sn 192.168.1.0/24 lists live hosts |
lsof -i | lsof | Which process owns which socket |
iftop, nload, bmon, vnstat | respective | Live and historical bandwidth per interface |
nft list ruleset, iptables -L -n -v | nftables, iptables | Firewall rules |
ufw status verbose, firewall-cmd --list-all | ufw, firewalld | Firewall front ends |
journalctl -u NetworkManager -f | systemd | Watch what NetworkManager is doing |
dmesg -w | grep -i -E "link|eth|wlan" | util-linux | Driver messages: link up/down, resets |