Nandishwar Singh

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

  1. The four things every machine needs
  2. Interfaces and addresses: ip addr
  3. The gateway: ip route
  4. DNS: names into addresses
  5. Changing things on the fly
  6. Permanent settings: netplan
  7. Testing connectivity
  8. The machine's name
  9. Common mistakes
  10. Practice
  11. 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:

  1. An interface that's up: the network card, real or virtual.
  2. An IP address on that interface, with a prefix that says how big the local network is.
  3. A default gateway: the router that forwards everything not on the local network.
  4. A DNS server, to turn names like ubuntu.com into 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 forever

That'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/64

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-tools

You can install it, but learn the ip and ss versions instead (lesson 21 covers ss). These are the ones you'll use:

OldNew
ifconfigip addr
ifconfig eth0 upip link set eth0 up
route -nip route
netstat -tlnpss -tlnp
arp -aip neigh

Try it

  1. What's your VM's IPv4 address, and what's its interface called?
  2. 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 200

The 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
    cache

Try it

  1. What's your default gateway?
  2. 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: yes

To 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

  1. Look up the IPv4 addresses of archive.ubuntu.com.
  2. 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>
CommandDoes
sudo ip addr add 10.0.0.5/24 dev XAdd an address
sudo ip addr del 10.0.0.5/24 dev XRemove one
sudo ip link set X up / downSwitch an interface on or off
sudo ip route add 10.9.0.0/16 via 10.0.0.1Add a route
sudo ip route del 10.9.0.0/16Remove 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

  1. Write a netplan file that would give eth0 the address 192.168.5.50/24 with the same gateway, but only run sudo netplan generate on 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:

TestIf it fails, the problem is
ip -br addrThe 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.1The gateway or beyond: routing, firewall, the internet connection
ping -c 3 ubuntu.comDNS (if the step above worked)
curl -I https://ubuntu.comThe 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.1

The 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

  1. Work through the table above on your own VM. Which step would fail if /etc/resolv.conf pointed 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

Practice

  1. 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
  1. Create a dummy interface test0 with the address 172.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
  1. Add 10.20.30.40 db.lab to /etc/hosts (with sudo tee -a, lesson 8), check that getent finds it, then remove it with sed (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
  1. 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: 87

SERVER: 127.0.0.53 is the local resolver, which asked the real servers for you.

  1. Send exactly two pings to 1.1.1.1 with 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 ms

Cheat sheet

CommandWhat it does
ip -br addr, ip aAddresses (brief, full)
ip -br linkInterfaces and MAC addresses
ip route, ip route show defaultRouting table, the gateway
ip route get 1.1.1.1Which way a packet would go
ip neighMachines seen on the local network
sudo ip addr add/del 10.0.0.5/24 dev XAdd or remove an address (until reboot)
sudo ip link set X up/downSwitch an interface on or off
sudo ip link add lab0 type dummyA practice interface
/etc/netplan/*.yamlPermanent settings
sudo netplan generate, try, applyCheck, try with auto-rollback, apply
resolvectl status, resolvectl query nameDNS servers in use, look up a name
dig +short nameQuick DNS lookup
getent hosts nameLook up a name like programs do
/etc/hostsLocal names, checked before DNS
ping -c 3 hostIs it reachable?
curl -I https://siteDoes the web server answer?
tracepath -n hostEvery hop on the way
hostnamectlShow or set the machine's name