Linux runs most of the world's servers and many routers and firewalls, and Android phones are built on the Linux kernel. When a Linux machine has a network problem, the tools to find it are usually already installed. This lesson covers the modern set: the ip command for settings, ping and traceroute for reachability, dig for DNS and ss for connections. It mirrors Essential Windows network commands, so you can compare them side by side.
Before you start: the terminal
You type these commands in a terminal (also called a shell). On a desktop, open the “Terminal” app; on a server, you usually connect with SSH. The $ at the start of each example is the prompt, so don't type it.
man ipshows the manual for a command (ip helpshows a short summary). Press q to leave the manual.sudoin front of a command runs it as the administrator (root). You mainly need it to change settings.- Interface names vary:
eth0,enp3s0,ens18andwlp2s0(Wi-Fi) are all common. Runip linkto see yours. - If
digortracerouteis missing, install it. On Ubuntu or Debian, runsudo apt install dnsutils traceroute.
The commands at a glance
| Linux | Question it answers | Windows equivalent | macOS equivalent |
|---|---|---|---|
ip addr | What IP addresses does each interface have? | ipconfig | ifconfig |
ip link | Is each interface up, and does it have a link? | Get-NetAdapter | ifconfig, networksetup |
ip route | Where is traffic sent? What is the default gateway? | route print | netstat -rn |
ip neigh | Which MAC address belongs to each local IP? | arp -a | arp -a |
ping -c 4 | Can I reach it, and how fast? | ping | ping -c 4 |
traceroute, tracepath | Which routers are on the path? | tracert | traceroute |
dig, nslookup | What does DNS say about this name? | nslookup | dig, nslookup |
ss -tulpn | Which ports are listening, and which program owns them? | netstat -ano | lsof -i -P, netstat -an |
The examples use one Linux web server, web01, at 192.168.10.30/24 with MAC 02:00:00:00:00:30. Its default gateway is 192.168.10.1, its DNS server is 192.168.10.5, and it communicates with a remote server, web.example.com, at 203.0.113.10.
- 1. ip link, ip addr: is eth0 up with a cable link, and what IP address does it have?
- 2. ip route, ip neigh: the default route points to 192.168.10.1, and the ARP cache holds its MAC address.
- 3. dig, nslookup: ask the DNS server for web.example.com's address.
- 4. ping, traceroute: test the path and list each router hop.
- 5. ss -tulpn: shows that the nginx web server is listening for incoming web traffic.
ip addr: what are my addresses?
ip addr (short form: ip a) lists every interface with its MAC address and IP addresses. It is the Linux version of ipconfig.
Syntaxip addr [show dev eth0] ip -br addr (brief, one line each)
$ 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 valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 02:00:00:00:00:30 brd ff:ff:ff:ff:ff:ff inet 192.168.10.30/24 brd 192.168.10.255 scope global dynamic eth0 valid_lft 85912sec preferred_lft 85912sec inet6 fe80::ff:fe00:30/64 scope link valid_lft forever preferred_lft forever
lo is the loopback interface (127.0.0.1, the machine talking to itself). eth0 is the real network card. link/ether is its MAC address. inet 192.168.10.30/24 is the IPv4 address and mask in CIDR form (/24 = 255.255.255.0; see Subnet mask basics). dynamic means the address came from DHCP, and valid_lft is how much time the lease has left. inet6 fe80:: is an automatic IPv6 link-local address.$ ip -br addr lo UNKNOWN 127.0.0.1/8 ::1/128 eth0 UP 192.168.10.30/24 fe80::ff:fe00:30/64
-br) shows one line per interface, with its state and addresses, so it is easier to scan on machines with many interfaces. An interface with no IPv4 address, or one starting with 169.254, didn't get an address from DHCP.ip link: is the interface up?
ip link shows interfaces at Layer 2 only: their state, MAC address and MTU (the largest packet that fits in one frame). Use it for the physical and Ethernet steps of a troubleshooting method.
Syntaxip link [show dev eth0] ip -s link (with counters) sudo ip link set eth0 up
$ ip link show eth0 2: eth0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc fq_codel state DOWN mode DEFAULT group default qlen 1000 link/ether 02:00:00:00:00:30 brd ff:ff:ff:ff:ff:ff
UP inside the brackets means the interface is enabled in software, but NO-CARRIER and state DOWN mean there is no signal on the cable. Check the cable and the switch port. A healthy interface shows UP,LOWER_UP and state UP. If UP is missing completely, the interface is administratively down; enable it with sudo ip link set eth0 up.$ ip -s link show eth0 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000 link/ether 02:00:00:00:00:30 brd ff:ff:ff:ff:ff:ff RX: bytes packets errors dropped missed mcast 1843204931 2210456 0 0 0 1204 TX: bytes packets errors dropped carrier collsns 211874452 904311 0 0 0 0
-s adds counters. RX is received traffic and TX is sent traffic. Here, errors, dropped and collsns are all 0, which is healthy. Errors or collisions that keep rising point to a bad cable or a duplex mismatch.$ sudo ethtool eth0 | grep -E 'Speed|Duplex|Link detected' Speed: 1000Mb/s Duplex: Full Link detected: yes
ethtool shows the negotiated speed and duplex. Here, it is 1 Gbps full duplex, which is what you want on a modern network. Link detected: yes confirms the cable link.ip route: where does traffic go?
ip route (short form: ip r) shows the routing table. The most important line is the default route, which names the default gateway.
Syntaxip route ip route get 203.0.113.10 (which route would be used?)
$ ip route default via 192.168.10.1 dev eth0 proto dhcp src 192.168.10.30 metric 100 192.168.10.0/24 dev eth0 proto kernel scope link src 192.168.10.30 metric 100
default via 192.168.10.1 is the default gateway, learned from DHCP (proto dhcp). The second line says that the local subnet 192.168.10.0/24 is reached directly through eth0, with no gateway. If there is no default line, the machine can only reach its own subnet.$ ip route get 203.0.113.10 203.0.113.10 via 192.168.10.1 dev eth0 src 192.168.10.30 uid 1000 cache
ip route get answers “how would I reach this exact address?”. Here, the answer is via the gateway 192.168.10.1, out of eth0, from the source address 192.168.10.30. This is very useful on machines with several interfaces or a VPN.ip neigh: the ARP table
ip neigh (neighbour) shows the ARP cache: which MAC address belongs to each IP address on the local network. It replaces arp -a.
Syntaxip neigh sudo ip neigh flush dev eth0 (clear the cache)
$ ip neigh 192.168.10.1 dev eth0 lladdr 02:00:00:00:00:01 REACHABLE 192.168.10.5 dev eth0 lladdr 02:00:00:00:00:05 STALE 192.168.10.40 dev eth0 FAILED
| State | Meaning |
|---|---|
REACHABLE | Confirmed recently; the MAC address (lladdr) is valid |
STALE | Known, but not confirmed recently. This is normal; it is checked again on next use |
FAILED | ARP requests got no reply: the host is off, unplugged or on another VLAN |
INCOMPLETE | ARP request sent, still waiting for a reply |
💡 If the gateway shows FAILED, the machine can't reach anything outside its subnet. Remote hosts such as 203.0.113.10 never appear here, because the machine only needs the gateway's MAC address to reach them.
Learn more: ARP for Local and Remote Destinations
ping: can I reach it?
ping sends ICMP echo requests and reports each echo reply. On Linux, it runs until you press Ctrl+C, so use -c to set a count.
Syntaxping [-c count] [-i interval] [-s size] [-4] target
$ ping -c 4 192.168.10.1 PING 192.168.10.1 (192.168.10.1) 56(84) bytes of data. 64 bytes from 192.168.10.1: icmp_seq=1 ttl=255 time=0.412 ms 64 bytes from 192.168.10.1: icmp_seq=2 ttl=255 time=0.388 ms 64 bytes from 192.168.10.1: icmp_seq=3 ttl=255 time=0.401 ms 64 bytes from 192.168.10.1: icmp_seq=4 ttl=255 time=0.395 ms --- 192.168.10.1 ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3054ms rtt min/avg/max/mdev = 0.388/0.399/0.412/0.009 ms
56(84) bytes means 56 bytes of data, or 84 bytes including the ICMP and IP headers. icmp_seq numbers each request, so a gap (1, 2, 4) shows exactly which one was lost. The summary gives the packet loss and the minimum, average and maximum round-trip times; mdev shows how much the times vary (jitter).$ ping -c 3 192.168.10.40 PING 192.168.10.40 (192.168.10.40) 56(84) bytes of data. From 192.168.10.30 icmp_seq=1 Destination Host Unreachable From 192.168.10.30 icmp_seq=2 Destination Host Unreachable From 192.168.10.30 icmp_seq=3 Destination Host Unreachable --- 192.168.10.40 ping statistics --- 3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2041ms
.40 failed (the FAILED entry in ip neigh above), so the echo requests were never sent. If the message came from a router's address, that router could not deliver the packet, for example because it had no route. If there is no output for any sequence number and then 100% loss, the requests simply timed out.traceroute and tracepath: which way does it go?
Both commands list each router between you and the target by sending probes with a rising TTL (time to live, a hop counter in the IP header). Each router lowers the TTL by 1. A router that drops a probe because its TTL reached 0 sends back an ICMP “time exceeded” message from its own address. Linux traceroute sends UDP probes to high ports by default (Windows tracert uses ICMP). -I switches to ICMP and -T to TCP, which often gets through firewalls that block the others.
Learn more: Traceroute
Syntaxtraceroute [-n] [-I | -T -p 443] target tracepath [-n] target
$ traceroute -n web.example.com traceroute to web.example.com (203.0.113.10), 30 hops max, 60 byte packets 1 192.168.10.1 0.512 ms 0.478 ms 0.461 ms 2 198.51.100.1 7.913 ms 8.102 ms 7.884 ms 3 198.51.100.45 11.627 ms 11.802 ms 12.015 ms 4 * * * 5 203.0.113.1 18.944 ms 19.101 ms 18.876 ms 6 203.0.113.10 19.512 ms 19.388 ms 19.640 ms
-n skips name lookups, so the output is faster. Hop 4 shows stars, but later hops answer, so that router simply doesn't reply to probes. Stars that continue all the way to hop 30 mean traffic is probably being dropped after the last hop that answered (or the target itself doesn't reply to probes).$ tracepath -n web.example.com 1?: [LOCALHOST] pmtu 1500 1: 192.168.10.1 0.498ms 1: 192.168.10.1 0.455ms 2: 198.51.100.1 8.011ms 3: 198.51.100.45 11.904ms 4: no reply 5: 203.0.113.1 19.032ms 6: 203.0.113.10 19.488ms reached Resume: pmtu 1500 hops 6 back 6
reached on the last line means the target answered. tracepath is often installed when traceroute isn't, and it needs no special permissions. It also reports the path MTU (pmtu): the largest packet that fits through every link. A smaller pmtu than expected (for example, over a VPN) can explain “small pages load, but large ones hang”.dig: what does DNS say?
dig (domain information groper) is the most detailed DNS tool. It shows the full answer, how long it may be cached and which server replied. The online DNS Lookup tool shows the same kind of result, seen from the internet.
Syntaxdig [@server] name [A|AAAA|MX|TXT|NS] [+short]
$ dig web.example.com ; <<>> DiG 9.18.28-0ubuntu0.24.04.1-Ubuntu <<>> web.example.com ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 41872 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 65494 ;; QUESTION SECTION: ;web.example.com. IN A ;; ANSWER SECTION: web.example.com. 300 IN A 203.0.113.10 ;; Query time: 14 msec ;; SERVER: 127.0.0.53#53(127.0.0.53) (UDP) ;; WHEN: Mon Oct 05 09:14:22 UTC 2026 ;; MSG SIZE rcvd: 60
status: NOERROR means the lookup worked. The ANSWER SECTION holds the result: an A record (IPv4 address) of 203.0.113.10, cacheable for 300 seconds (the TTL). SERVER shows which server answered; 127.0.0.53 is the local systemd-resolved service, which forwards queries to the real DNS server.$ dig @192.168.10.5 webb.example.com ; <<>> DiG 9.18.28-0ubuntu0.24.04.1-Ubuntu <<>> @192.168.10.5 webb.example.com ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 5530 ;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1 ;; QUESTION SECTION: ;webb.example.com. IN A ;; AUTHORITY SECTION: example.com. 3600 IN SOA ns1.example.com. hostmaster.example.com. 2026100501 7200 3600 1209600 3600 ;; Query time: 22 msec ;; SERVER: 192.168.10.5#53(192.168.10.5) (UDP) ;; WHEN: Mon Oct 05 09:16:40 UTC 2026 ;; MSG SIZE rcvd: 104
@192.168.10.5 asks that server directly, skipping the local service. There is no ANSWER section, and the status explains why: NXDOMAIN means the name does not exist (webb is a typo for web). The AUTHORITY section only names the zone that gave this “no such name” answer. Add +short to any dig command to print only the answer. SERVFAIL would mean the server failed to get an answer, and connection timed out; no servers could be reached means the DNS server didn't respond at all.| status | Meaning | Likely fix |
|---|---|---|
NOERROR with an answer | The name was resolved | DNS is fine; look elsewhere |
NOERROR, empty answer | The name exists, but has no record of that type | Ask for the right type (A, AAAA, MX) |
NXDOMAIN | The name doesn't exist | Check the spelling, or the DNS zone |
SERVFAIL | The server couldn't get an answer | Problem at the DNS server or the domain's own servers |
| Timed out | No DNS server replied | Wrong DNS server address, or it is unreachable |
nslookup on Linux
nslookup also works on Linux and macOS, and its output looks almost the same as on Windows. It is useful when you switch between systems, but dig gives more detail.
$ nslookup web.example.com Server: 127.0.0.53 Address: 127.0.0.53#53 Non-authoritative answer: Name: web.example.com Address: 203.0.113.10
127.0.0.53, run resolvectl status (or look at /etc/resolv.conf on systems without systemd-resolved).ss -tulpn: what is listening?
ss (socket statistics) lists network sockets: the endpoints that programs use to send and receive data. It replaces the old netstat. The letters mean: -t TCP, -u UDP, -l listening only, -p show the program, and -n numbers instead of names. On a server, it answers “is my service actually running and listening on the right port?”.
Syntaxsudo ss -tulpn ss -tn (established TCP connections)
$ 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)) udp UNCONN 0 0 192.168.10.30%eth0:68 0.0.0.0:* users:(("systemd-network",pid=588,fd=22)) tcp LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:* users:(("systemd-resolve",pid=612,fd=14)) tcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=901,fd=3)) tcp LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=1123,fd=6)) tcp LISTEN 0 4096 127.0.0.1:5432 0.0.0.0:* users:(("postgres",pid=1040,fd=7)) tcp LISTEN 0 128 [::]:22 [::]:* users:(("sshd",pid=901,fd=4))
0.0.0.0:80 means nginx (the web server) accepts connections on port 80 on every IPv4 address, so it is reachable from the network. 0.0.0.0:22 is SSH. 127.0.0.1:5432 means the PostgreSQL database listens only on loopback, so other machines cannot connect to it, which is often exactly what you want. UDP port 68 is the DHCP client.Learn more: Common Ports to Know
⚠️ The classic “works locally, but not from outside” problem: a service listening on 127.0.0.1 instead of 0.0.0.0 (or the server's IP address). Everything looks healthy on the server itself, but no other machine can connect. The other common cause is a host firewall (ufw, firewalld or nftables) blocking the port; check with sudo ufw status or sudo nft list ruleset.
macOS equivalents
macOS is based on BSD Unix, not Linux, so some commands are different. It has no ip or ss command by default. ping, traceroute, dig and nslookup work almost the same as on Linux.
| Task | Linux | macOS |
|---|---|---|
| Addresses and interfaces | ip addr | ifconfig (Wi-Fi is usually en0) |
| Only the IP address of one interface | ip -br addr show eth0 | ipconfig getifaddr en0 |
| Routing table / gateway | ip route | netstat -rn or route -n get default |
| ARP cache | ip neigh | arp -a |
| DNS servers in use | resolvectl status | scutil --dns |
| Flush DNS cache | resolvectl flush-caches | sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder |
| Listening ports | ss -tulpn | sudo lsof -i -P -n | grep LISTEN |
| Renew DHCP | sudo dhclient -r && sudo dhclient or nmcli | sudo ipconfig set en0 DHCP |
Putting it together: “the website is down”
Users can't reach the website on web01. Here's what you check from the server itself:
ip -br addr:eth0 UP 192.168.10.30/24. The address is correct.ip route:default via 192.168.10.1. The default gateway is set.ping -c 4 192.168.10.1: 0% packet loss. The LAN works.sudo ss -tulpn | grep :80: no output. Nothing is listening on port 80.systemctl status nginx: the web server stopped after a bad configuration change.
Fix the configuration, start nginx, run ss again to see 0.0.0.0:80 LISTEN, and then confirm from a user's browser. The network was never the problem, and the commands proved it in less than a minute.
When the commands mislead you
- Silent hops: many routers don't answer traceroute probes. Only stars that continue to the end of the trace point to a real problem.
- Ping blocked: cloud servers and firewalls often drop ICMP, so a failed ping doesn't prove a host is down. Test the real port too, for example with
nc -vz 203.0.113.10 443or the Port Checker. - The local DNS service:
127.0.0.53hides which server really answered. Ask the server directly withdig @server. - Wrong interface: machines with Docker, VPNs or several network cards have many interfaces. Use
ip route getto see which one is really used.
Common mistakes
It is often not installed on modern Linux distributions. Use ip addr instead.
Linux ping runs until you stop it. Press Ctrl+C, or use ping -c 4.
The Process column stays empty for services owned by other users, so you can't see which program owns the port.
UP means the interface is enabled in software. LOWER_UP means there is a cable link. You need both.
ip addr,ip link,ip routeandip neighreplace ifconfig, route and arp.NO-CARRIERmeans no cable signal. Nodefault vialine means no default gateway.- Use
ping -c 4to test reachability, andtraceroute -nortracepathto find where a path stops. dig: read thestatus(NOERROR, NXDOMAIN, SERVFAIL) and the ANSWER section.sudo ss -tulpnshows which program listens on which port, and whether it is on0.0.0.0or only127.0.0.1.
Check yourself
A server has no network access. ip link shows eth0 with <NO-CARRIER,BROADCAST,MULTICAST,UP> and state DOWN. What is the problem?
ip route on a server shows only "192.168.10.0/24 dev eth0 proto kernel scope link". What can't this machine do?
A user says shop.example.com doesn't work. dig @192.168.10.5 shop.example.com returns status: NXDOMAIN. What does that tell you?
sudo ss -tulpn shows a database listening on 127.0.0.1:5432. Another server can't connect to it. Why?
You are troubleshooting a Mac and need to see its routing table and default gateway. Which command do you use?
Related lessons
Use these commands step by step in a structured troubleshooting method, and compare them with their Windows equivalents.
Learn more: A Troubleshooting MethodEssential Windows Network Commands
These lessons explain the theory behind the output:
Learn more: ARP FundamentalsDNSPort Numbers and SocketsViewing Connections on Your Computer
Then use the commands on real faults:
Learn more: Layer 1 and 2 ProblemsIP and Gateway Problems