Investigate a connection one layer at a time: local interfaces, routes, sockets, reachability, the application protocol and authenticated remote access.

Series: Previous: monitoring · Part 5 of 6 · Next: packages
Applies to: Linux iproute2, iputils, curl, GNU Wget and OpenSSH. Network targets are examples; probe only endpoints you own or are authorized to test. Output is illustrative.

The subsystem: interfaces, routes and sockets

The kernel sends packets through interfaces using routing decisions and maintains sockets for communicating processes. DNS translates names into addresses, but successful name resolution does not establish that an application is healthy. Firewalls, proxies, load balancers and service policies can each change the path.

In an enterprise incident, “the network is down” is too broad to act on. A useful report says which host, destination, protocol and operation failed, with bounded timings. Tools here inspect different layers; none alone establishes end-to-end health.

ip: inspect local addresses and routing decisions

ip -brief address show
ip route show
ip route get 192.0.2.10

192.0.2.10 is a documentation address. ip route get asks the kernel how it would route there; it does not send a probe to that host. Illustrative output includes 192.0.2.10 via 192.168.1.1 dev eth0 src 192.168.1.20. Actual interface names and routes differ. The same tool can change addresses and routes, but these show/get examples are observations only.

ss and netstat: inspect sockets

ss -ltn
ss -ltnp
netstat -ltn

ss comes from iproute2 and is generally the first choice on current Linux systems; legacy netstat may be absent. -l selects listening sockets, -t selects TCP and -n keeps numeric addresses/ports. -p requests process information, which permissions may restrict. A listener on 127.0.0.1:8080 differs from one on 0.0.0.0:8080; a listening socket still does not prove the application’s response is correct.

ping: test ICMP reachability, with limits

ping -c 3 -W 2 127.0.0.1

The loopback address tests a local path. -c limits the request count and, for iputils, -W controls the response wait. You might see 3 packets transmitted, 3 received. Missing replies from a remote host do not prove it is offline: ICMP can be filtered while HTTPS works. Successful ping does not prove a TCP port or API endpoint is healthy.

curl: inspect an application response

For an approved HTTPS endpoint:

curl --proto '=https' --fail --silent --show-error \
  --connect-timeout 5 --max-time 15 \
  --output /dev/null \
  --write-out 'HTTP %{http_code}; total %{time_total}s\n' \
  https://service.example.com/health

Replace the reserved example hostname with your approved service. This makes a GET, discards the response body and reports status/timing. It can still cause normal server logging or application work. Certificate verification stays enabled; do not hide a trust problem with -k. A transport failure returns nonzero; --fail also returns nonzero for HTTP errors. A 200 response does not validate response-body semantics.

wget: retrieve a reviewed artifact

wget --https-only --timeout=15 --tries=1 \
  --output-document=release-notes.txt \
  https://downloads.example.com/release-notes.txt

This writes a local file and can overwrite that destination; use a fresh workspace. Wget suits straightforward retrieval, while curl gives convenient protocol and timing controls. Verify an artifact against a trusted signature or independently obtained checksum before using it. Neither a successful download nor a TLS connection establishes that a program is safe to execute. Do not pipe a downloaded script directly into a shell.

ssh: run a bounded observation on an approved host

ssh -o BatchMode=yes -o StrictHostKeyChecking=yes \
  -o ConnectTimeout=5 operations@server.example.com 'uptime'

This requires an existing account, configured authentication and a previously verified host key in known_hosts. It runs uptime remotely, not locally. BatchMode avoids unattended password prompts; strict host-key checking refuses an unknown or changed key. Verify new fingerprints through your organization’s trusted channel rather than accepting them blindly. Do not disable host-key checks to make a script pass.

scp: transfer a file over SSH

scp -o BatchMode=yes -o StrictHostKeyChecking=yes \
  ./report.txt operations@server.example.com:/srv/approved-inbox/report.txt

This is a remote write and needs approval for the destination. Modern OpenSSH scp uses SFTP by default; older clients may use the legacy SCP protocol. Authentication and host verification still matter. Check the remote path, file sensitivity and overwrite policy before sending anything. scp copies data; it does not activate a release, validate its contents or implement rollback.

Practical script: a local endpoint triage report

A service is not responding. Collect local interface/socket evidence and make one bounded HTTP request. The script accepts an approved loopback HTTP service at port 8080, suitable for a lab. It neither edits networking nor connects over SSH.

Save as endpoint-triage.sh; start a disposable server from an empty lab directory in another terminal with python3 -m http.server 8080 --bind 127.0.0.1. Run bash endpoint-triage.sh. Stop your server with Ctrl-C afterward. The HTTP server is for the local exercise only.

#!/usr/bin/env bash
set -euo pipefail
for tool in ip ss ping curl; do
  command -v "$tool" >/dev/null || { printf 'Missing tool: %s\n' "$tool" >&2; exit 2; }
done
printf 'Local interfaces:\n'
ip -brief address show
printf '\nRouting table:\n'
ip route show
printf '\nListening TCP sockets:\n'
ss -ltn
status=0
printf '\nLoopback ICMP check:\n'
if ping -c 2 -W 1 127.0.0.1; then
  :
else
  printf 'ICMP check failed; inspect permissions/policy separately from HTTP.\n' >&2
  status=1
fi
printf '\nLocal HTTP check:\n'
if curl --noproxy '*' --proto '=http' --fail --silent --show-error \
  --connect-timeout 2 --max-time 5 --output /dev/null \
  --write-out 'HTTP %{http_code}; total %{time_total}s\n' \
  http://127.0.0.1:8080/; then
  printf 'The local HTTP request succeeded.\n'
else
  printf 'HTTP request failed; inspect the listener and application.\n' >&2
  status=1
fi
exit "$status"

With a running lab server, the HTTP line should contain HTTP 200; timing varies. Without it, curl reports a connection error and the script returns nonzero. If ping is restricted but HTTP succeeds, the report preserves both observations instead of collapsing them into a single “network down” conclusion. This does not validate DNS, TLS, remote routing or a production API.

References

iproute2 source and documentation, ip manual, ss manual, iputils ping, curl manual, GNU Wget, OpenSSH ssh, OpenSSH scp.