Linux Tutorial / Diagnose Network Connectivity Step by Step

Diagnose Linux connectivity by checking interfaces and addresses, routes, name resolution, transport connections, and application responses in that order. A single ping result does not establish whether an entire network or web service is working.

For addresses and default routes, see IP addresses, DNS, and ports. For an SSH-only failure, also inspect the host, port, and keys in SSH and file transfer.

System configuration exercises use a conventional Ubuntu 26.04 LTS or Rocky Linux 9 VM as the reference environment. Containers, WSL, and other releases can differ in service and package configuration. Prepare console recovery and record your versions using the virtual machine setup lesson.

Record the scope before changing anything

Record the source machine, destination name, port, start time, and exact error. Compare one site with several sites, one client with another, and IPv4 with IPv6 where relevant. Note VPN and proxy differences and recent changes. Before restarting networking on a remote server, establish console access or another management path.

Inspect interfaces, addresses, and routes

ip -brief link
ip -brief address
ip route
ip -6 route

Administrative UP status does not prove destination reachability. Inspect link information such as LOWER_UP, the expected addresses, and the applicable route. In a VM, check that the virtual NIC is connected and that NAT or bridged networking matches your plan. Do not assume that the interface is named eth0.

After resolving the destination, ip route get ACTUAL_IPV4_ADDRESS shows the selected interface, next hop, and source address. “Network is unreachable” points toward routing rather than DNS. A selected route still does not prove that the next hop or destination is responding.

Treat ping as one reachability signal

ping -c 3 127.0.0.1
ping -c 3 example.com

The first command tests loopback ICMP Echo; the second resolves a name and sends Echo requests to that destination. ICMP can be filtered while web access still works. Conversely, a reply does not validate a web port, certificate, or HTTP response. Use a small number of requests to an approved lab destination.

Separate resolution failures from connection failures

getent ahosts example.com
curl -I -v --connect-timeout 5 --max-time 15 https://example.com/
printf "exit=%s\n" "$?"

If getent returns no address, investigate name-service configuration. Curl verbose output separates address selection, connection, TLS, and response handling. Exit codes commonly include 6 for name-resolution failure, 7 for connection failure, 28 for timeout, and 60 for certificate validation failure. Disabling certificate verification with -k is not a repair.

By default, curl may exit successfully after transferring an HTTP 404 or 500 response. Use --fail-with-body on a supported version, or --fail, when HTTP errors should produce failure status. Read both HTTP status and process exit status. Redact cookies, headers, and private addresses before sharing verbose output.

Check the listening address on the server

ss -lnt
ss -lnu
sudo ss -lntp

A listener on 127.0.0.1:8080 accepts direct connections only locally. 0.0.0.0:8080 covers IPv4 interfaces; whether [::]:8080 also handles IPv4 depends on socket and system settings. Process details may require privileges. A bound UDP socket is not equivalent to a validated request-response exchange.

Make one change supported by the evidence

Observation Investigate first
Local requests also fail Service state, configuration, listener
Local works, remote fails Bind address, host firewall, cloud rules
Connection works, certificate fails Hostname, certificate chain, clock
HTTP error response Web/application logs and request path

Record the original setting, change one item, and repeat the same test from the same client to the same destination. Revert an ineffective change before testing another hypothesis. This preserves evidence and helps avoid creating a second fault.

To distinguish an HTTP failure without an external site, confirm that python3 and curl are installed in the practice VM, installing them through its package manager if needed. Run the following server in one terminal. If port 18080 is busy, choose another free port and change it in both commands.

lab=$(mktemp -d "$HOME/linux-http-check.XXXXXX") &&
python3 -m http.server 18080 --bind 127.0.0.1 --directory "$lab"

After the server starts, run this in another terminal in the same VM. Expect HTTP 404 and curl status 22: a TCP connection and HTTP response were received, but the requested file is absent. Stop the server with Ctrl+C, then repeat. With no listener, curl normally reports connection failure (7); an environment that waits until the connection timeout can instead report 28. Read status immediately and check that no other server has taken the port.

curl --fail --show-error --connect-timeout 2 --max-time 5 http://127.0.0.1:18080/missing-file
printf "exit=%s\n" "$?"

Official references