Networking Basics covers the four questions to ask when a network is broken. This page is the reference for the tool that answers three of them. ip replaced ifconfig, route and arp — which came from net-tools and have been deprecated for well over a decade — with one command that handles everything the kernel knows about networking.
One command, several objects
Every invocation is ip OBJECT COMMAND. Learn the objects and the rest is consistent.
| Object | Deals with | Replaces |
|---|---|---|
address / a | IP addresses on interfaces | ifconfig |
link / l | The interfaces themselves — up, down, MTU, MAC | ifconfig |
route / r | Where packets go | route |
neighbour / n | The ARP and NDP cache | arp |
rule | Which routing table to consult | — |
netns | Network namespaces | — |
tunnel, link add | Tunnels, bridges, VLANs, veth pairs | brctl, vconfig |
The two flags that make it readable
ip -br -c a # brief, coloured: one line per interface
ip -br -c l # the same for links
ip -4 -br a # IPv4 only
ip -6 -br a # IPv6 only
ip -j -p a # JSON, for scripts — pipe into jqip -br -c a is the line to put in your fingers. The default output wraps across four lines per interface and buries the address you wanted; the brief form gives you name, state and addresses in one row each. Add it as an alias and never type the long form again.
-j emits JSON, which makes ip genuinely scriptable for the first time — no more parsing whitespace with awk. Pipe it into jq.
Addresses
ip a show dev eth0
sudo ip a add 192.168.1.50/24 dev eth0
sudo ip a add 192.168.1.51/24 dev eth0 # a second address is fine
sudo ip a del 192.168.1.51/24 dev eth0
sudo ip a flush dev eth0 # remove all — careful over SSHThe prefix length is not optional and is not decoration. ip a add 192.168.1.50 dev eth0 with no /24 is taken as /32, giving you an address that can talk to nothing on its own subnet — a confusing failure that looks like a routing problem.
Links
ip -br l # every interface and its state
sudo ip l set dev eth0 up # or down
sudo ip l set dev eth0 mtu 1400
sudo ip l set dev eth0 address 02:11:22:33:44:55
ip -s l show dev eth0 # packet counts, errors, dropsip -s l is the underused one. Rising errors or dropped counters point at a cable, a duplex mismatch or an overloaded interface — a physical problem, not a configuration one, and worth checking before you rewrite anything.
The state field distinguishes DOWN (administratively off) from NO-CARRIER (on, but nothing is plugged in or the switch port is dead). Those are different problems with different fixes.
Routes, and the single most useful command here
ip r # the routing table
ip r get 1.1.1.1 # which route WOULD be used, and from where
ip r get 192.168.1.20
sudo ip r add default via 192.168.1.1 dev eth0
sudo ip r add 10.20.0.0/16 via 192.168.1.254
sudo ip r del 10.20.0.0/16
ip r show table all # including tables you did not know existedip r get is the command to reach for first. It does not send a packet — it asks the kernel which route it would choose for that destination, which interface it would leave by, and which source address it would use. When traffic is going somewhere unexpected, this answers it in one line, and it accounts for policy rules and multiple tables that reading ip r by eye would miss.
Where two routes could match, the more specific prefix wins; where they are equally specific, the lower metric wins. That is the whole algorithm, and it explains most surprises — including the one where a VPN adds two /1 routes to override your default without deleting it.
Neighbours
ip n # the ARP cache
ip n show dev eth0
sudo ip n flush dev eth0 # after replacing hardware or an IP moves
sudo ip n add 192.168.1.9 lladdr 00:11:22:33:44:55 dev eth0 nud permanentAn entry stuck in FAILED or INCOMPLETE means the host is not answering on the local segment at all — a layer-2 problem, so no amount of routing configuration will help. Flushing is the standard fix after an address moves between machines and something is still holding the old MAC.
Nothing you do here survives a reboot
ip changes the kernel’s live state and writes nothing to disk. Every address, route and interface change is gone at the next reboot — and often sooner, because whichever network manager is running may reassert its own configuration within seconds. Use ip to diagnose and to test; make it permanent in the tool your distribution actually uses.
| System | Where configuration lives |
|---|---|
| Ubuntu Server | Netplan — YAML in /etc/netplan/, then netplan apply |
| Fedora, RHEL, Rocky, Alma | NetworkManager — nmcli, or files in /etc/NetworkManager/ |
| Most desktops | NetworkManager — nmcli or the applet |
| Debian, minimal servers | /etc/network/interfaces, or systemd-networkd |
| Arch, containers, appliances | systemd-networkd — /etc/systemd/network/*.network |
# which one is actually in charge?
systemctl is-active NetworkManager systemd-networkd networking
nmcli device status # if NetworkManager
sudo netplan get # if netplan
networkctl status # if systemd-networkdTwo managers fighting over one interface produces settings that revert every few seconds. Establishing which one owns the interface is the first step in any configuration change, not the last.
Not locking yourself out
Changing addresses or routes on a remote machine is the classic way to lose access to it. Give yourself an automatic way back before you touch anything:
sudo shutdown -r +10 # reboot in ten minutes unless cancelled
# ...make the change, confirm you can still connect from a NEW session...
sudo shutdown -c # cancel itSince ip changes nothing on disk, a reboot restores the previous working configuration. Test with a second SSH session rather than the one you are already in — an existing connection often survives a change that stops any new one being made.
Namespaces
ip netns list
sudo ip netns add test
sudo ip netns exec test ip -br a # run a command inside it
sudo ip -n test l set lo upEach namespace has its own interfaces, addresses, routes and firewall rules. This is the mechanism containers use for networking — though container runtimes create their namespaces outside ip netns, so ip netns list will not show Docker’s. Reach those with nsenter -t <pid> -n instead.
Symptom to command
| Symptom | Run |
|---|---|
| No address at all | ip -br a, then check DHCP or the config tool |
| Address present, nothing reachable | ip r — is there a default route? |
| Traffic leaving the wrong interface | ip r get <destination> |
| Local hosts unreachable, remote fine | ip n — ARP failures |
| Works, but slow or lossy | ip -s l — errors and drops |
| Settings revert by themselves | A network manager owns the interface |
| Large transfers hang, small ones work | MTU. Test with ping -M do -s 1472 |
Quick reference
ip -br -c a # everything, readably
ip r # routing table
ip r get 8.8.8.8 # which route would be used
ip -s l show dev eth0 # errors and drops
ip n # ARP cache
sudo ip a add 10.0.0.5/24 dev eth0
sudo ip r add default via 10.0.0.1
sudo ip l set dev eth0 up
ip -j -p a # JSON outputRelated
- Networking Basics — ip, ss, ping and dig, and the order to try them in
- Networking Explained — what addresses, routes and ports actually are
- Linux Firewalls — the other half of what happens to a packet
- Containers — network namespaces, and why Docker’s are invisible here
