Home / Learn Linux / Lesson 18
Network basics: ip, static IPs and troubleshooting
Read your addresses and routes, set a static IP with netplan, and find out why a connection fails.
- Lesson
- 18 of 30
- Time
- About 45 minutes
On this page
- The four things every machine needs
- Interfaces and addresses: ip addr
- The gateway: ip route
- DNS: names into addresses
- Changing things on the fly
- Permanent settings: netplan
- Testing connectivity
- The machine's name
- Common mistakes
- Practice
- Cheat sheet
The four things every machine needs
To talk to the network, a Linux machine needs four things. When something doesn't connect, it's almost always one of them:
- An interface that's up: the network card, real or virtual.
- An IP address on that interface, with a prefix that says how big the local network is.
- A default gateway: the router that forwards everything not on the local network.
- A DNS server, to turn names like
ubuntu.cominto addresses.
This lesson shows how to see each one, change it, and test it.
Interfaces and addresses: ip addr
ip is the modern tool for all of this. ip addr (or just ip a) shows every interface and its addresses:
$ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host noprefixroute
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 52:55:55:5f:1e:b4 brd ff:ff:ff:ff:ff:ff
altname enx5255555f1eb4
inet 192.168.5.15/24 metric 200 brd 192.168.5.255 scope global dynamic eth0
valid_lft 2558sec preferred_lft 2558sec
inet6 fe80::5055:55ff:fe5f:1eb4/64 scope link proto kernel_ll
valid_lft forever preferred_lft foreverThat's a lot. -br (brief) gives one line per interface, which is usually all you want:
$ ip -br addr
lo UNKNOWN 127.0.0.1/8 ::1/128
eth0 UP 192.168.5.15/24 metric 200 fe80::5055:55ff:fe5f:1eb4/64lois the loopback interface: the machine talking to itself, always127.0.0.1.eth0is the network card. On your VM it may be calledens3orenp0s1instead. Names depend on the hardware, so always check withipbefore using one.192.168.5.15/24is the IPv4 address with its prefix./24means the first 24 bits (the first three numbers,192.168.5) are the network, so any192.168.5.xis on the same local network and can be reached directly.- The
fe80::address is IPv6, which Linux sets up by itself. UPmeans the interface is switched on.
ip link shows the interfaces without addresses, including each MAC address, the card's own hardware address:
$ ip -br link
lo UNKNOWN 00:00:00:00:00:00 <LOOPBACK,UP,LOWER_UP>
eth0 UP 52:55:55:5f:1e:b4 <BROADCAST,MULTICAST,UP,LOWER_UP>ifconfig and netstat
Older guides use ifconfig and netstat. They come from a package called net-tools that's been out of date for years, and Ubuntu 26.04 doesn't install it:
$ ifconfig
Command 'ifconfig' not found, but can be installed with:
sudo apt install net-toolsYou can install it, but learn the ip and ss versions instead (lesson 21 covers ss). These are the ones you'll use:
| Old | New |
|---|---|
ifconfig | ip addr |
ifconfig eth0 up | ip link set eth0 up |
route -n | ip route |
netstat -tlnp | ss -tlnp |
arp -a | ip neigh |
Try it
- What's your VM's IPv4 address, and what's its interface called?
- What's the MAC address of that interface?
Answer
$ ip -4 -br addr lo UNKNOWN 127.0.0.1/8 eth0 UP 192.168.5.15/24 metric 200 $ ip -br link show eth0 eth0 UP 52:55:55:5f:1e:b4 <BROADCAST,MULTICAST,UP,LOWER_UP>
The gateway: ip route
ip route shows the routing table: where packets go.
$ ip route
default via 192.168.5.2 dev eth0 proto dhcp src 192.168.5.15 metric 200
192.168.5.0/24 dev eth0 proto kernel scope link src 192.168.5.15 metric 200
192.168.5.2 dev eth0 proto dhcp scope link src 192.168.5.15 metric 200The line that matters most is default via 192.168.5.2: anything not on the local network goes to that router. proto dhcp says it was set automatically by DHCP, the service that hands out addresses on most networks. The 192.168.5.0/24 line says the local network is reached directly through eth0.
ip route get answers "which way would a packet to this address go?":
$ ip route get 1.1.1.1
1.1.1.1 via 192.168.5.2 dev eth0 src 192.168.5.15 uid 1000
cacheTry it
- What's your default gateway?
- Which interface and source address would be used to reach
8.8.8.8?
Answer
$ ip route show default default via 192.168.5.2 dev eth0 proto dhcp src 192.168.5.15 metric 200 $ ip route get 8.8.8.8 8.8.8.8 via 192.168.5.2 dev eth0 src 192.168.5.15 uid 1000 cache
DNS: names into addresses
Ubuntu runs a small local DNS service, systemd-resolved. Programs ask it at 127.0.0.53, and it asks the real DNS servers. That's why /etc/resolv.conf looks odd:
$ grep -v "^#" /etc/resolv.conf
nameserver 127.0.0.53
options edns0 trust-ad
search .To see which servers it really uses, ask resolvectl:
$ resolvectl status eth0
Link 2 (eth0)
Current Scopes: DNS
Protocols: +DefaultRoute -LLMNR -mDNS -DNSOverTLS
DNSSEC=no/unsupported
Current DNS Server: 192.168.5.2
DNS Servers: 192.168.5.2
Default Route: yesTo look a name up:
$ resolvectl query ubuntu.com ubuntu.com: 185.125.190.21 -- link: eth0 185.125.190.29 -- link: eth0 185.125.190.20 -- link: eth0 -- Information acquired via protocol DNS in 183ms. -- Data is authenticated: no; Data was acquired via local or encrypted transport: no -- Data from: network $ dig +short ubuntu.com 185.125.190.21 185.125.190.29 185.125.190.20
dig is the tool for DNS problems: without +short it prints the whole answer, including which server replied and how long the record may be cached. Lesson 30 uses it to check a domain points at your server.
/etc/hosts comes first
Before asking DNS, Linux checks /etc/hosts, a plain list of addresses and names. It's how a machine knows its own name, and you can add your own entries to name machines on your network:
$ cat /etc/hosts 127.0.0.1 localhost # The following lines are desirable for IPv6 capable hosts ::1 ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters ff02::3 ip6-allhosts 127.0.1.1 linux $ getent hosts linux 127.0.1.1 linux
getent hosts looks a name up exactly the way programs do: /etc/hosts first, then DNS.
Try it
- Look up the IPv4 addresses of
archive.ubuntu.com. - Which DNS server does your VM ask?
Answer
$ dig +short archive.ubuntu.com 91.189.91.81 91.189.92.24 91.189.91.83 91.189.91.82 91.189.92.23 185.125.190.81 185.125.190.82 185.125.190.83 91.189.92.22 $ resolvectl dns eth0 Link 2 (eth0): 192.168.5.2
Changing things on the fly
ip can change everything you've looked at, but those changes only last until the next reboot. That makes them great for testing. Don't experiment on eth0 when you're connected through it, though: take its address away and you cut off your own connection. Make a pretend interface to practise on instead. A dummy interface is a virtual card that isn't connected to anything:
$ sudo ip link add lab0 type dummy $ sudo ip addr add 10.20.30.1/24 dev lab0 $ sudo ip link set lab0 up $ ip -br addr show lab0 lab0 UNKNOWN 10.20.30.1/24 fe80::f426:abff:fefb:38fe/64 $ ip route | grep lab0 10.20.30.0/24 dev lab0 proto kernel scope link src 10.20.30.1
Linux added a route for 10.20.30.0/24 through lab0 by itself, because that's the network the address belongs to. Now change it and take it down again:
$ sudo ip addr add 10.20.30.2/24 dev lab0 $ ip -br addr show lab0 lab0 UNKNOWN 10.20.30.1/24 10.20.30.2/24 fe80::f426:abff:fefb:38fe/64 $ sudo ip addr del 10.20.30.1/24 dev lab0 $ sudo ip link set lab0 down $ ip -br addr show lab0 lab0 DOWN 10.20.30.2/24 $ sudo ip link del lab0 $ ip -br link lo UNKNOWN 00:00:00:00:00:00 <LOOPBACK,UP,LOWER_UP> eth0 UP 52:55:55:5f:1e:b4 <BROADCAST,MULTICAST,UP,LOWER_UP>
| Command | Does |
|---|---|
sudo ip addr add 10.0.0.5/24 dev X | Add an address |
sudo ip addr del 10.0.0.5/24 dev X | Remove one |
sudo ip link set X up / down | Switch an interface on or off |
sudo ip route add 10.9.0.0/16 via 10.0.0.1 | Add a route |
sudo ip route del 10.9.0.0/16 | Remove it |
Permanent settings: netplan
Ubuntu keeps its network settings in YAML files in /etc/netplan. When the machine boots, netplan reads them and sets everything up. Your VM got its file from cloud-init when it was created:
$ ls -l /etc/netplan total 4 -rw------- 1 root root 298 Oct 21 11:06 50-cloud-init.yaml $ sudo cat /etc/netplan/50-cloud-init.yaml network: version: 2 ethernets: eth0: match: macaddress: "52:55:55:5f:1e:b4" optional: true nameservers: addresses: - 192.168.5.2 dhcp-identifier: "mac" dhcp4: true dhcp4-overrides: route-metric: 200 set-name: "eth0"
YAML uses indentation to show structure, so spaces matter: always spaces, never tabs, and each level two spaces deeper. dhcp4: true means "get an address automatically". Only root can read the file (rw-------), because some netplan files hold Wi-Fi passwords, and netplan warns you if a file is more open than that.
A static IP
Servers usually need an address that never changes, so other machines and DNS records can rely on it. You set it in a new file. Netplan merges every file in the directory, in name order, so 60-static.yaml adds to and overrides 50-cloud-init.yaml. This one fixes the VM at the address it already has, which is the safe way to practise:
$ sudo tee /etc/netplan/60-static.yaml > /dev/null << EOF > network: > version: 2 > ethernets: > eth0: > dhcp4: false > addresses: > - 192.168.5.15/24 > routes: > - to: default > via: 192.168.5.2 > nameservers: > addresses: [192.168.5.2, 1.1.1.1] > EOF $ sudo chmod 600 /etc/netplan/60-static.yaml $ sudo netplan generate
netplan generate checks the files and converts them, without changing anything. If you made a YAML mistake, it says so here. Then apply it:
$ sudo netplan apply $ ip -br addr show eth0 eth0 UP 192.168.5.15/24 fe80::5055:55ff:fe5f:1eb4/64 $ ip route show default default via 192.168.5.2 dev eth0 proto static
The route now says proto static instead of proto dhcp: the machine no longer asks for an address.
On a real server you'd use your own network's free address, gateway and DNS servers. And on a remote server, use sudo netplan try instead of apply: it applies the change, then rolls it back automatically after two minutes unless you press Enter to confirm. If the new settings cut you off, you can't press Enter, so the old settings come back by themselves. That has saved many people a trip to the data centre.
To go back to DHCP, delete the file and apply again:
$ sudo rm /etc/netplan/60-static.yaml $ sudo netplan apply $ ip route show default default via 192.168.5.2 dev eth0 proto dhcp src 192.168.5.15 metric 200
Try it
- Write a netplan file that would give
eth0the address192.168.5.50/24with the same gateway, but only runsudo netplan generateon it. Don't apply it, because the VM would move to an address your Mac doesn't know about. Then delete it.
Answer
$ sudo tee /etc/netplan/60-test.yaml > /dev/null << EOF > network: > version: 2 > ethernets: > eth0: > dhcp4: false > addresses: [192.168.5.50/24] > routes: > - to: default > via: 192.168.5.2 > EOF $ sudo chmod 600 /etc/netplan/60-test.yaml $ sudo netplan generate $ sudo rm /etc/netplan/60-test.yaml
No output from generate means the file is valid. addresses: [ ... ] on one line is the same as the indented list.
Testing connectivity
When "the network is down", test the four things in order, from the closest outwards. Each step tells you where to look:
| Test | If it fails, the problem is |
|---|---|
ip -br addr | The interface is down or has no address |
ping -c 3 192.168.5.2 (your gateway) | The local network or the cable/virtual switch |
ping -c 3 1.1.1.1 | The gateway or beyond: routing, firewall, the internet connection |
ping -c 3 ubuntu.com | DNS (if the step above worked) |
curl -I https://ubuntu.com | The service itself, or something blocking web traffic |
$ ping -c 3 192.168.5.2 PING 192.168.5.2 (192.168.5.2) 56(84) bytes of data. 64 bytes from 192.168.5.2: icmp_seq=1 ttl=64 time=0.102 ms 64 bytes from 192.168.5.2: icmp_seq=2 ttl=64 time=0.104 ms 64 bytes from 192.168.5.2: icmp_seq=3 ttl=64 time=0.116 ms --- 192.168.5.2 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2078ms rtt min/avg/max/mdev = 0.102/0.107/0.116/0.006 ms $ ping -c 3 1.1.1.1 PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data. 64 bytes from 1.1.1.1: icmp_seq=1 ttl=64 time=0.217 ms 64 bytes from 1.1.1.1: icmp_seq=2 ttl=64 time=0.119 ms 64 bytes from 1.1.1.1: icmp_seq=3 ttl=64 time=0.131 ms --- 1.1.1.1 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2078ms rtt min/avg/max/mdev = 0.119/0.155/0.217/0.043 ms $ ping -c 3 ubuntu.com PING ubuntu.com (185.125.190.21) 56(84) bytes of data. 64 bytes from 185.125.190.21: icmp_seq=1 ttl=64 time=0.079 ms 64 bytes from 185.125.190.21: icmp_seq=2 ttl=64 time=0.095 ms 64 bytes from 185.125.190.21: icmp_seq=3 ttl=64 time=0.104 ms --- ubuntu.com ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2079ms rtt min/avg/max/mdev = 0.079/0.092/0.104/0.010 ms
-c 3 sends three pings and stops (without it, ping runs until Ctrl+C). time= is the round trip in milliseconds, and the last line summarises how many came back. Some servers ignore pings on purpose, so a failed ping to a website doesn't always mean it's down.
curl -I fetches just the headers of a web page, which proves DNS, routing and the web server all work in one go:
$ curl -sI https://ubuntu.com
HTTP/2 200
server: nginx/1.14.0 (Ubuntu)
date: Wed, 21 Oct 2026 12:44:49 GMT
content-type: text/html; charset=utf-8
content-length: 187522
...HTTP/2 200, or a 301 redirect, means a working website answered.
Finding where it breaks: tracepath
tracepath shows every router a packet passes on its way to a destination, one numbered line per hop with how long it took. When a site is unreachable, the last hop that answers tells you roughly where the problem is: your network, your provider's, or the far end. Run it yourself:
$ tracepath -n 1.1.1.1The output isn't shown here, because it lists the real routers between this test machine and the internet. Yours will show your own home router and your provider's network. -n skips looking up names, which makes it faster. (traceroute is the older tool that does the same, and isn't installed by default.)
Try it
- Work through the table above on your own VM. Which step would fail if
/etc/resolv.confpointed at a DNS server that didn't exist?
Answer
All the steps up to ping -c 3 1.1.1.1 would pass, and ping ubuntu.com would fail with an error like Temporary failure in name resolution. Addresses work, names don't: that's DNS.
The machine's name
hostnamectl shows and changes the machine's name. On its own it also prints the operating system, the kernel and what kind of machine it is:
$ hostnamectl hostname linux $ hostnamectl | grep -E "Operating System|Kernel|Virtualization" Virtualization: apple Operating System: Ubuntu 26.04.1 LTS Kernel: Linux 7.0.0-28-generic Hardware Model: Apple Virtualization Generic Platform
Changing the name also needs an /etc/hosts entry, so the machine can still find itself.
To rename a server: sudo hostnamectl set-hostname web1, then change the 127.0.1.1 line in /etc/hosts to web1. New shells show the new name in the prompt.
Common mistakes
- Testing names before addresses.
ping ubuntu.comfailing could be DNS or the whole network. Ping an IP first. - **Changing
eth0over SSH.**ip addr delorip link set downon the interface you're connected through cuts you off. Usenetplan tryfor anything permanent. - Tabs in netplan files. YAML needs spaces.
netplan generatetells you the line. - **Expecting
ipchanges to survive a reboot.** They don't. Put them in netplan. - Using the interface name from a guide. It's
eth0here, maybeens3orenp0s1for you. Always checkip -br link. - **Looking for
ifconfig.** It's not installed.ip addr.
Practice
- In one command each: show only IPv4 addresses, show only the default route, and show which DNS servers are in use.
Answer
$ ip -4 -br addr lo UNKNOWN 127.0.0.1/8 eth0 UP 192.168.5.15/24 metric 200 $ ip route show default default via 192.168.5.2 dev eth0 proto dhcp src 192.168.5.15 metric 200 $ resolvectl dns Global: Link 2 (eth0): 192.168.5.2
- Create a dummy interface
test0with the address172.16.0.1/16, check the route Linux added for it, then delete it.
Answer
$ sudo ip link add test0 type dummy $ sudo ip addr add 172.16.0.1/16 dev test0 $ sudo ip link set test0 up $ ip route | grep test0 172.16.0.0/16 dev test0 proto kernel scope link src 172.16.0.1 $ sudo ip link del test0
- Add
10.20.30.40 db.labto/etc/hosts(withsudo tee -a, lesson 8), check thatgetentfinds it, then remove it withsed(lesson 12).
Answer
$ echo "10.20.30.40 db.lab" | sudo tee -a /etc/hosts 10.20.30.40 db.lab $ getent hosts db.lab 10.20.30.40 db.lab $ sudo sed -i '/db\.lab/d' /etc/hosts $ getent hosts db.lab; echo $? 10.20.30.40 db.lab 0
- Show the full DNS answer for
ubuntu.com, and find the line that says which server answered.
Answer
$ dig ubuntu.com
...
ubuntu.com. 0 IN A 185.125.190.21
;; Query time: 2 msec
;; SERVER: 127.0.0.53#53(127.0.0.53) (UDP)
;; WHEN: Wed Oct 21 12:44:57 UTC 2026
;; MSG SIZE rcvd: 87SERVER: 127.0.0.53 is the local resolver, which asked the real servers for you.
- Send exactly two pings to
1.1.1.1with a one-second timeout, and print only the summary.
Answer
$ ping -c 2 -W 1 1.1.1.1 | tail -n 2
2 packets transmitted, 2 received, 0% packet loss, time 1065ms
rtt min/avg/max/mdev = 0.116/0.118/0.121/0.002 msCheat sheet
| Command | What it does |
|---|---|
ip -br addr, ip a | Addresses (brief, full) |
ip -br link | Interfaces and MAC addresses |
ip route, ip route show default | Routing table, the gateway |
ip route get 1.1.1.1 | Which way a packet would go |
ip neigh | Machines seen on the local network |
sudo ip addr add/del 10.0.0.5/24 dev X | Add or remove an address (until reboot) |
sudo ip link set X up/down | Switch an interface on or off |
sudo ip link add lab0 type dummy | A practice interface |
/etc/netplan/*.yaml | Permanent settings |
sudo netplan generate, try, apply | Check, try with auto-rollback, apply |
resolvectl status, resolvectl query name | DNS servers in use, look up a name |
dig +short name | Quick DNS lookup |
getent hosts name | Look up a name like programs do |
/etc/hosts | Local names, checked before DNS |
ping -c 3 host | Is it reachable? |
curl -I https://site | Does the web server answer? |
tracepath -n host | Every hop on the way |
hostnamectl | Show or set the machine's name |
← Signals and jobs: kill, bg, fg and nohupSSH: connecting, keys and a safer server →