Skip to content

Portal | Level: L1: Foundations | Topics: Networking Troubleshooting Tools, Linux Networking Tools, TCP/IP | Domain: Networking

Networking Troubleshooting Tools - Primer

Why This Matters

Every outage starts with the same question: "Can you reach it?" The answer depends on which tool you use and whether you understand what it actually tests. A ping succeeding tells you almost nothing about why your application cannot connect. A ping failing might not mean the host is down. Network troubleshooting is a layered discipline, and each tool operates at a specific layer. Choosing the wrong tool wastes time. Misreading the output costs more.

This primer covers every major network diagnostic tool you will encounter in production Linux environments. Each section explains what the tool tests, how to read the output, and the flags you will actually use.


ping / ping6

What It Tests

ICMP Echo Request/Reply. Tests L3 reachability and round-trip time. Does not test TCP/UDP connectivity, application health, or firewall rules that may allow ICMP but block your service port.

Essential Usage

# Basic reachability test
$ ping -c 4 10.0.0.1
PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=0.432 ms
64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.387 ms
64 bytes from 10.0.0.1: icmp_seq=3 ttl=64 time=0.401 ms
64 bytes from 10.0.0.1: icmp_seq=4 ttl=64 time=0.395 ms

--- 10.0.0.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 0.387/0.403/0.432/0.016 ms

# IPv6
$ ping6 -c 4 fe80::1%eth0

# Set packet size (useful for MTU testing)
$ ping -c 4 -s 1472 -M do 10.0.0.1

# Flood ping for quick loss detection (requires root)
$ ping -f -c 1000 10.0.0.1

# Set TTL to limit hops
$ ping -c 4 -t 5 10.0.0.1

# Set interval (0.2 seconds between packets)
$ ping -c 10 -i 0.2 10.0.0.1

Reading the Output

Field Meaning
ttl=64 Time to live. Decremented by each hop. Starting TTL of 64 typically means Linux, 128 means Windows, 255 means network equipment.
time=0.432 ms Round-trip time. Under 1ms on the same LAN. Over 100ms on intercontinental links.
icmp_seq Sequence number. Gaps indicate packet loss.
mdev Standard deviation of RTT. High mdev with normal average means jitter.
0% packet loss Summary. Any non-zero packet loss on a LAN deserves investigation.

Key Flags

Flag Purpose
-c N Send N packets then stop
-i N Interval between packets (seconds, fractions allowed)
-s N Payload size in bytes (default 56, total ICMP packet = N + 8)
-M do Set DF (Don't Fragment) bit — critical for MTU testing
-f Flood mode — sends as fast as possible (root only)
-t N Set TTL
-W N Timeout for each reply in seconds
-I iface Bind to specific interface or source IP

traceroute / tracepath / mtr

What They Test

Path analysis. Show every L3 hop between source and destination. Identify where latency spikes or packet loss occurs along the path.

traceroute

# Default (UDP probes)
$ traceroute 8.8.8.8
traceroute to 8.8.8.8 (8.8.8.8), 30 hops max, 60 byte packets
 1  gateway (10.0.0.1)  0.452 ms  0.411 ms  0.389 ms
 2  isp-pe1.example.net (203.0.113.1)  2.103 ms  2.087 ms  2.114 ms
 3  core-rtr.example.net (198.51.100.1)  5.221 ms  5.198 ms  5.247 ms
 4  dns.google (8.8.8.8)  11.334 ms  11.301 ms  11.356 ms

# TCP probes (bypass ICMP-blocking firewalls)
$ traceroute -T -p 443 8.8.8.8

# ICMP probes
$ traceroute -I 8.8.8.8

# Show AS numbers
$ traceroute -A 8.8.8.8

# Don't resolve hostnames (faster)
$ traceroute -n 8.8.8.8

Each hop shows three RTT values (three probes by default). An asterisk (*) means that probe got no reply — this is often ICMP rate limiting at that hop, not packet loss.

tracepath

# MTU discovery along path (no root required)
$ tracepath 10.0.0.50
 1?: [LOCALHOST]                      pmtu 1500
 1:  gateway                           0.452ms
 1:  gateway                           0.411ms
 2:  10.0.1.1                          1.203ms asymm  3
 2:  10.0.1.1                          1.187ms reached
     Resume: pmtu 1500 hops 2 back 3

tracepath discovers the Path MTU without needing root. The asymm flag indicates asymmetric routing (return path has a different hop count).

mtr (My Traceroute)

# Interactive mode (default)
$ mtr 8.8.8.8

# Report mode (run N cycles, then print summary)
$ mtr -r -c 100 8.8.8.8
Start: 2026-03-19T10:00:00+0000
HOST: web01                Loss%   Snt   Last   Avg  Best  Wrst StDev
  1.|-- gateway            0.0%   100    0.4   0.4   0.3   0.8   0.1
  2.|-- isp-pe1            0.0%   100    2.1   2.2   1.9   4.1   0.3
  3.|-- core-rtr           2.0%   100    5.2   5.3   5.0   8.7   0.5
  4.|-- dns.google         2.0%   100   11.3  11.4  11.0  15.2   0.6

# TCP mode on port 443
$ mtr -T -P 443 -r -c 100 8.8.8.8

# Show AS numbers
$ mtr -z -r -c 100 8.8.8.8

# JSON output
$ mtr -j -c 50 8.8.8.8

# Wide report (show both hostnames and IPs)
$ mtr -rw -c 100 8.8.8.8

mtr combines traceroute and ping into a continuous probe. It is the single best tool for diagnosing intermittent path issues because it accumulates statistics over many cycles.

Reading mtr output: Loss at an intermediate hop that does not carry through to subsequent hops is ICMP rate limiting, not real packet loss. Real loss affects the hop where it occurs and all hops beyond it.


dig / nslookup / host

What They Test

DNS resolution. Query nameservers for specific record types, trace delegation chains, and test resolver behavior.

dig

# Basic A record lookup
$ dig example.com
;; ANSWER SECTION:
example.com.        3600    IN    A    93.184.216.34

# Specific record types
$ dig example.com AAAA        # IPv6
$ dig example.com MX          # Mail
$ dig example.com NS          # Nameservers
$ dig example.com TXT         # TXT records (SPF, DKIM, etc.)
$ dig example.com SOA         # Start of Authority
$ dig example.com CNAME       # Canonical name
$ dig _sip._tcp.example.com SRV  # Service records

# Short output (just the answer)
$ dig +short example.com
93.184.216.34

# Query a specific nameserver
$ dig @8.8.8.8 example.com

# Trace the full delegation chain
$ dig +trace example.com
.                       518400  IN  NS  a.root-servers.net.
com.                    172800  IN  NS  a.gtld-servers.net.
example.com.            172800  IN  NS  ns1.example.com.
example.com.            3600    IN  A   93.184.216.34

# Reverse lookup
$ dig -x 93.184.216.34

# Show all sections (question, answer, authority, additional)
$ dig +noall +answer +authority example.com

# TCP instead of UDP (for large responses or debugging)
$ dig +tcp example.com

# Check DNSSEC
$ dig +dnssec example.com

# Query with no recursion (test authoritative server directly)
$ dig +norecurse @ns1.example.com example.com

Reading dig Output

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12345
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
Field Meaning
status: NOERROR Query succeeded. NXDOMAIN = name does not exist. SERVFAIL = server error. REFUSED = server refused query.
qr This is a response (query response)
rd Recursion desired (you asked for it)
ra Recursion available (server supports it)
aa Authoritative answer (server is authoritative for this zone)
ANSWER: 1 Number of answer records
Query time: 23 msec How long the DNS lookup took
SERVER: 10.0.0.2#53 Which resolver answered

nslookup

# Basic lookup
$ nslookup example.com
Server:     10.0.0.2
Address:    10.0.0.2#53

Non-authoritative answer:
Name:   example.com
Address: 93.184.216.34

# Query specific server
$ nslookup example.com 8.8.8.8

# Specific record type
$ nslookup -type=MX example.com

host

# Compact output
$ host example.com
example.com has address 93.184.216.34
example.com has IPv6 address 2606:2800:220:1:248:1893:25c8:1946
example.com mail is handled by 0 .

# Reverse lookup
$ host 93.184.216.34

# Specific record type
$ host -t MX example.com

# Verbose output
$ host -v example.com

ss / netstat

What They Test

Socket statistics. Show active network connections, listening ports, and connection states on the local host.

ss (modern, preferred)

# All TCP listening sockets with process info
$ ss -tlnp
State    Recv-Q   Send-Q   Local Address:Port    Peer Address:Port   Process
LISTEN   0        128      0.0.0.0:22            0.0.0.0:*           users:(("sshd",pid=1234,fd=3))
LISTEN   0        511      0.0.0.0:80            0.0.0.0:*           users:(("nginx",pid=5678,fd=6))
LISTEN   0        128      127.0.0.1:5432        0.0.0.0:*           users:(("postgres",pid=9012,fd=5))

# All established connections
$ ss -tn state established

# Connections to a specific port
$ ss -tn dport = :443

# Connections from a specific source
$ ss -tn src 10.0.0.0/24

# Show timer information (retransmits, keepalive)
$ ss -tnoi

# UDP sockets
$ ss -ulnp

# Unix domain sockets
$ ss -xlnp

# Summary statistics
$ ss -s
Total: 352
TCP:   47 (estab 12, closed 8, orphaned 0, timewait 8)
Transport Total     IP        IPv6
RAW       0         0         0
UDP       6         4         2
TCP       39        27        12
INET      45        31        14
FRAG      0         0         0

# Show memory usage per socket
$ ss -tm

# Filter by connection state
$ ss -tn state time-wait
$ ss -tn state close-wait
$ ss -tn state fin-wait-1

Key ss Flags

Flag Purpose
-t TCP sockets
-u UDP sockets
-l Listening sockets only
-n Numeric (don't resolve names)
-p Show process using socket (needs root)
-o Show timer information
-i Show internal TCP information (RTT, cwnd, ssthresh)
-m Show socket memory usage
-s Summary statistics
-4 / -6 IPv4 / IPv6 only

Connection States That Matter

State Meaning Action
ESTABLISHED Active connection Normal
LISTEN Waiting for connections Normal for servers
TIME-WAIT Connection closed, waiting for stale packets Normal, but thousands indicate high connection churn
CLOSE-WAIT Remote closed, local has not Application bug — not closing sockets
FIN-WAIT-1 Local closed, waiting for remote ACK Remote may be hung or network issue
SYN-SENT Sent SYN, waiting for SYN-ACK Connection attempt in progress — many indicate unreachable target
SYN-RECV Received SYN, sent SYN-ACK Normal briefly. Many indicate SYN flood

netstat (legacy)

# Equivalent of ss -tlnp
$ netstat -tlnp

# All connections with process info
$ netstat -anp

# Routing table
$ netstat -rn

netstat is deprecated on modern Linux. It reads /proc/net/tcp which is slower than ss's netlink approach. Use ss.


tcpdump

What It Tests

Packet capture. See the actual packets on the wire. The definitive tool for "what is really happening" when higher-level tools disagree.

Essential Usage

# Capture on a specific interface
$ tcpdump -i eth0

# Capture without resolving names (faster, less confusing)
$ tcpdump -nn -i eth0

# Capture with verbose output
$ tcpdump -nn -v -i eth0

# Write to a file for Wireshark analysis
$ tcpdump -nn -i eth0 -w /tmp/capture.pcap

# Read a saved capture
$ tcpdump -nn -r /tmp/capture.pcap

# Capture N packets then stop
$ tcpdump -nn -c 100 -i eth0

# Capture with timestamps (microsecond precision)
$ tcpdump -nn -tttt -i eth0

BPF Filter Expressions

Filters are the most important tcpdump skill. Without filters, the output is a firehose.

# Filter by host
$ tcpdump -nn -i eth0 host 10.0.0.5

# Filter by source or destination
$ tcpdump -nn -i eth0 src host 10.0.0.5
$ tcpdump -nn -i eth0 dst host 10.0.0.5

# Filter by port
$ tcpdump -nn -i eth0 port 443
$ tcpdump -nn -i eth0 dst port 5432

# Filter by protocol
$ tcpdump -nn -i eth0 tcp
$ tcpdump -nn -i eth0 udp
$ tcpdump -nn -i eth0 icmp

# Filter by network
$ tcpdump -nn -i eth0 net 10.0.0.0/24

# Combine filters with and/or/not
$ tcpdump -nn -i eth0 'host 10.0.0.5 and port 443'
$ tcpdump -nn -i eth0 'src host 10.0.0.5 and dst port 80'
$ tcpdump -nn -i eth0 'not port 22'
$ tcpdump -nn -i eth0 'tcp and (port 80 or port 443)'

# TCP flags
$ tcpdump -nn -i eth0 'tcp[tcpflags] & tcp-syn != 0'    # SYN packets
$ tcpdump -nn -i eth0 'tcp[tcpflags] & tcp-rst != 0'    # RST packets
$ tcpdump -nn -i eth0 'tcp[tcpflags] = tcp-syn'         # SYN only (no ACK)

# Packet size
$ tcpdump -nn -i eth0 'greater 1000'     # Packets > 1000 bytes
$ tcpdump -nn -i eth0 'less 100'         # Packets < 100 bytes

Reading tcpdump Output

14:22:01.123456 IP 10.0.0.5.43210 > 10.0.0.1.443: Flags [S], seq 1234567890, win 65535, options [mss 1460,sackOK,TS val 123 ecr 0,nop,wscale 7], length 0
14:22:01.123789 IP 10.0.0.1.443 > 10.0.0.5.43210: Flags [S.], seq 987654321, ack 1234567891, win 65535, options [mss 1460,sackOK,TS val 456 ecr 123,nop,wscale 7], length 0
14:22:01.123890 IP 10.0.0.5.43210 > 10.0.0.1.443: Flags [.], ack 1, win 512, length 0
Flag Meaning
[S] SYN
[S.] SYN-ACK
[.] ACK
[P.] PSH-ACK (data push)
[F.] FIN-ACK (connection close)
[R] RST (reset)
[R.] RST-ACK

The three lines above are a TCP three-way handshake: SYN, SYN-ACK, ACK. If you see SYN followed by RST instead of SYN-ACK, the connection was refused (nothing listening). If you see SYN with no response, the port is filtered or the host is down.


curl / wget for Network Testing

What They Test

Application-layer (L7) connectivity. HTTP response codes, TLS negotiation, DNS resolution, and timing breakdowns.

curl

# Basic connectivity test
$ curl -v https://api.example.com/health

# Show only HTTP response code
$ curl -s -o /dev/null -w "%{http_code}" https://api.example.com/health

# Full timing breakdown
$ curl -s -o /dev/null -w "\
    DNS:        %{time_namelookup}s\n\
    Connect:    %{time_connect}s\n\
    TLS:        %{time_appconnect}s\n\
    TTFB:       %{time_starttransfer}s\n\
    Total:      %{time_total}s\n" \
    https://api.example.com/health
    DNS:        0.004s
    Connect:    0.015s
    TLS:        0.045s
    TTFB:       0.089s
    Total:      0.091s

# Resolve to specific IP (bypass DNS)
$ curl --resolve api.example.com:443:10.0.0.5 https://api.example.com/health

# Set timeout
$ curl --connect-timeout 5 --max-time 10 https://api.example.com/health

# Use specific interface or source IP
$ curl --interface eth1 https://api.example.com/health

# Ignore TLS certificate errors (testing only)
$ curl -k https://self-signed.example.com/

# Send request with specific headers
$ curl -H "Host: api.example.com" http://10.0.0.5/health

# TCP connect only (no HTTP)
$ curl -v telnet://10.0.0.5:5432

wget

# Download with retry
$ wget --tries=3 --timeout=10 https://example.com/file.tar.gz

# Spider mode (check if URL is reachable, don't download)
$ wget --spider https://api.example.com/health

# Mirror a site (testing CDN/proxy)
$ wget --mirror --no-parent https://docs.example.com/

nmap

What It Tests

Port scanning and service detection. Discover open ports, identify services, and fingerprint operating systems.

Essential Usage

# TCP SYN scan (default, fast, stealthy — requires root)
$ nmap -sS 10.0.0.5
Starting Nmap 7.94 ( https://nmap.org )
Nmap scan report for 10.0.0.5
PORT     STATE    SERVICE
22/tcp   open     ssh
80/tcp   open     http
443/tcp  open     https
3306/tcp filtered mysql

# Scan specific ports
$ nmap -p 22,80,443 10.0.0.5

# Scan port range
$ nmap -p 1-1024 10.0.0.5

# Scan all 65535 ports
$ nmap -p- 10.0.0.5

# Service version detection
$ nmap -sV 10.0.0.5
PORT    STATE SERVICE VERSION
22/tcp  open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.6
80/tcp  open  http    nginx 1.24.0
443/tcp open  https   nginx 1.24.0

# OS detection
$ nmap -O 10.0.0.5

# Aggressive scan (OS + version + scripts + traceroute)
$ nmap -A 10.0.0.5

# UDP scan (slow but necessary for DNS, SNMP, NTP)
$ nmap -sU -p 53,161,123 10.0.0.5

# TCP connect scan (no root required)
$ nmap -sT 10.0.0.5

# Scan a subnet
$ nmap -sn 10.0.0.0/24    # Ping sweep, no port scan

# Fast scan (top 100 ports)
$ nmap -F 10.0.0.5

# Output to file
$ nmap -oN scan.txt 10.0.0.5     # Normal
$ nmap -oX scan.xml 10.0.0.5     # XML
$ nmap -oG scan.grep 10.0.0.5    # Grepable

Port States

State Meaning
open Port is accepting connections
closed Port is reachable but nothing is listening (RST response)
filtered No response — firewall is dropping packets
unfiltered Port is reachable but nmap cannot determine open/closed
open|filtered No response — could be open or filtered (common with UDP)

nc / ncat (Netcat)

What It Tests

Raw TCP/UDP connectivity. Test if a port is reachable, transfer files, or listen on a port.

Essential Usage

# Test TCP connectivity to a port
$ nc -zv 10.0.0.5 443
Connection to 10.0.0.5 443 port [tcp/https] succeeded!

# Test with timeout
$ nc -zv -w 3 10.0.0.5 5432

# Scan a port range
$ nc -zv 10.0.0.5 80-90

# Listen on a port (ad-hoc server for testing)
$ nc -l -p 8080

# Send data to a listener
$ echo "test" | nc 10.0.0.5 8080

# Simple file transfer
# Receiver:
$ nc -l -p 9000 > received_file
# Sender:
$ nc 10.0.0.5 9000 < file_to_send

# UDP mode
$ nc -u 10.0.0.5 53

# Keep listening after client disconnects (ncat)
$ ncat -lk -p 8080

# Act as a simple HTTP responder (debugging)
$ while true; do echo -e "HTTP/1.1 200 OK\r\n\r\nOK" | nc -l -p 8080; done

ip (iproute2)

What It Tests

Network interface configuration, routing tables, neighbor (ARP) tables, and link state. The modern replacement for ifconfig, route, and arp.

ip addr — Interface Addresses

# Show all addresses
$ ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536
    inet 127.0.0.1/8 scope host lo
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500
    link/ether 52:54:00:ab:cd:ef brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.5/24 brd 10.0.0.255 scope global eth0
    inet6 fe80::5054:ff:feab:cdef/64 scope link

# Show specific interface
$ ip addr show dev eth0

# Add an address
$ ip addr add 10.0.0.100/24 dev eth0

# Remove an address
$ ip addr del 10.0.0.100/24 dev eth0

# Brief output
$ ip -br addr
lo               UNKNOWN        127.0.0.1/8 ::1/128
eth0             UP             10.0.0.5/24 fe80::5054:ff:feab:cdef/64

ip route — Routing Table

# Show routing table
$ ip route show
default via 10.0.0.1 dev eth0 proto dhcp metric 100
10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.5 metric 100
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1

# Show route for a specific destination
$ ip route get 8.8.8.8
8.8.8.8 via 10.0.0.1 dev eth0 src 10.0.0.5 uid 0
    cache

# Add a static route
$ ip route add 192.168.1.0/24 via 10.0.0.1 dev eth0

# Delete a route
$ ip route del 192.168.1.0/24

# Show routing table for a specific table
$ ip route show table all
# Show link status
$ ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP

# Bring interface up/down
$ ip link set eth0 up
$ ip link set eth0 down

# Change MTU
$ ip link set eth0 mtu 9000

# Brief output
$ ip -br link
lo               UNKNOWN        00:00:00:00:00:00 <LOOPBACK,UP,LOWER_UP>
eth0             UP             52:54:00:ab:cd:ef <BROADCAST,MULTICAST,UP,LOWER_UP>

# Show interface statistics
$ ip -s link show dev eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500
    RX: bytes  packets  errors  dropped overrun mcast
    1234567    9876     0       0       0       0
    TX: bytes  packets  errors  dropped carrier collsns
    7654321    8765     0       0       0       0

ip neigh — Neighbor (ARP) Table

# Show ARP table
$ ip neigh show
10.0.0.1 dev eth0 lladdr 52:54:00:11:22:33 REACHABLE
10.0.0.10 dev eth0 lladdr 52:54:00:44:55:66 STALE

# Flush entries for an interface
$ ip neigh flush dev eth0

# Add a static entry
$ ip neigh add 10.0.0.5 lladdr aa:bb:cc:dd:ee:ff dev eth0

ethtool

What It Tests

NIC hardware status: link speed, duplex, driver, ring buffer sizes, offload features, and hardware error counters.

Essential Usage

# Show NIC settings
$ ethtool eth0
Settings for eth0:
    Speed: 10000Mb/s
    Duplex: Full
    Auto-negotiation: on
    Link detected: yes

# Show driver info
$ ethtool -i eth0
driver: virtio_net
version: 1.0.0
firmware-version:

# Show NIC statistics (error counters)
$ ethtool -S eth0
NIC statistics:
     rx_packets: 9876543
     tx_packets: 8765432
     rx_errors: 0
     tx_errors: 0
     rx_dropped: 12
     tx_dropped: 0
     rx_crc_errors: 0

# Show ring buffer sizes
$ ethtool -g eth0
Ring parameters for eth0:
Pre-set maximums:
RX:     1024
TX:     1024
Current hardware settings:
RX:     256
TX:     256

# Increase ring buffers (reduce drops under load)
$ ethtool -G eth0 rx 1024 tx 1024

# Show offload features
$ ethtool -k eth0
tcp-segmentation-offload: on
generic-receive-offload: on
rx-checksumming: on

# Toggle an offload feature
$ ethtool -K eth0 tso off

iperf3

What It Tests

Network bandwidth between two endpoints. Measures throughput, jitter, and packet loss for both TCP and UDP.

Essential Usage

# Server side
$ iperf3 -s
-----------------------------------------------------------
Server listening on 5201
-----------------------------------------------------------

# Client — basic TCP test
$ iperf3 -c 10.0.0.5
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.00  sec  11.2 GBytes  9.60 Gbits/sec    0    sender
[  5]   0.00-10.00  sec  11.2 GBytes  9.59 Gbits/sec         receiver

# UDP test with target bandwidth
$ iperf3 -c 10.0.0.5 -u -b 1G
[ ID] Interval           Transfer     Bitrate         Jitter    Lost/Total Datagrams
[  5]   0.00-10.00  sec  1.16 GBytes  1.00 Gbits/sec  0.011 ms   0/851203 (0%)

# Reverse test (server sends to client)
$ iperf3 -c 10.0.0.5 -R

# Bidirectional test
$ iperf3 -c 10.0.0.5 --bidir

# Multiple parallel streams
$ iperf3 -c 10.0.0.5 -P 4

# Specific test duration
$ iperf3 -c 10.0.0.5 -t 30

# Set TCP window size
$ iperf3 -c 10.0.0.5 -w 512K

# Bind to specific port
$ iperf3 -s -p 9000
$ iperf3 -c 10.0.0.5 -p 9000

# JSON output
$ iperf3 -c 10.0.0.5 -J

Reading iperf3 Output

Field Meaning
Transfer Total data transferred
Bitrate Throughput in bits/second
Retr TCP retransmits (0 is ideal, nonzero indicates congestion or loss)
Jitter UDP variation in packet arrival time
Lost/Total UDP packet loss ratio

openssl s_client

What It Tests

TLS/SSL connectivity. Certificate chain verification, protocol negotiation, cipher selection, and certificate expiration.

Essential Usage

# Connect and show certificate chain
$ openssl s_client -connect api.example.com:443
CONNECTED(00000003)
depth=2 C = US, O = DigiCert Inc, CN = DigiCert Global Root G2
verify return:1
depth=1 C = US, O = DigiCert Inc, CN = DigiCert SHA2 Extended Validation Server CA
verify return:1
depth=0 CN = api.example.com
verify return:1
---
Certificate chain
 0 s:CN = api.example.com
   i:CN = DigiCert SHA2 Extended Validation Server CA
 1 s:CN = DigiCert SHA2 Extended Validation Server CA
   i:CN = DigiCert Global Root G2
---

# Show certificate details
$ openssl s_client -connect api.example.com:443 2>/dev/null | openssl x509 -noout -text

# Check expiration date
$ openssl s_client -connect api.example.com:443 2>/dev/null | openssl x509 -noout -dates
notBefore=Jan  1 00:00:00 2026 GMT
notAfter=Dec 31 23:59:59 2026 GMT

# Check certificate for a specific hostname (SNI)
$ openssl s_client -connect 10.0.0.5:443 -servername api.example.com

# Test specific TLS version
$ openssl s_client -connect api.example.com:443 -tls1_2
$ openssl s_client -connect api.example.com:443 -tls1_3

# Show negotiated cipher
$ openssl s_client -connect api.example.com:443 2>/dev/null | grep "Cipher is"
    Cipher is TLS_AES_256_GCM_SHA384

# Check STARTTLS (SMTP)
$ openssl s_client -connect mail.example.com:25 -starttls smtp

# Verify against a specific CA bundle
$ openssl s_client -connect api.example.com:443 -CAfile /etc/ssl/certs/ca-certificates.crt

lsof -i

What It Tests

Open network file descriptors. Shows which processes have which network connections open. Complements ss with file-descriptor-level detail.

Essential Usage

# All network connections
$ lsof -i

# TCP connections only
$ lsof -i TCP

# Specific port
$ lsof -i :443
COMMAND   PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
nginx    5678  root    6u  IPv4  12345      0t0  TCP *:https (LISTEN)
nginx    5679  www     8u  IPv4  23456      0t0  TCP web01:https->client:43210 (ESTABLISHED)

# Specific host
$ lsof -i @10.0.0.5

# Specific host and port
$ lsof -i @10.0.0.5:5432

# Show PIDs only (useful for scripting)
$ lsof -t -i :80

# Connections in a specific state
$ lsof -i TCP -s TCP:ESTABLISHED
$ lsof -i TCP -s TCP:LISTEN

# IPv4 only
$ lsof -i 4

# IPv6 only
$ lsof -i 6

arping

What It Tests

Layer 2 reachability. Sends ARP requests and reports responses. Tests whether a host is reachable at the Ethernet level, independent of IP routing and firewall rules.

Essential Usage

# Basic ARP ping
$ arping -c 3 -I eth0 10.0.0.1
ARPING 10.0.0.1 from 10.0.0.5 eth0
Unicast reply from 10.0.0.1 [52:54:00:11:22:33]  0.842ms
Unicast reply from 10.0.0.1 [52:54:00:11:22:33]  0.791ms
Unicast reply from 10.0.0.1 [52:54:00:11:22:33]  0.803ms

# Detect duplicate IP addresses (DAD)
$ arping -D -c 3 -I eth0 10.0.0.25
# Exit code 0 = no duplicate, 1 = duplicate detected

# Use broadcast ARP (not unicast)
$ arping -b -c 3 -I eth0 10.0.0.1

# Gratuitous ARP (announce own address)
$ arping -A -c 3 -I eth0 10.0.0.5

arping is essential when ping fails but you suspect the host is on the same L2 segment. If arping gets replies but ping does not, the issue is above Layer 2 (firewall, IP misconfiguration, or routing).


Putting It All Together: Tool Selection

Symptom First Tool Why
"Host unreachable" ping, then ip route get Confirm L3 reachability and check routing
"Connection refused" ss -tlnp on target, nc -zv from source Verify something is listening
"Connection timeout" tcpdump on both ends See if SYNs arrive, if SYN-ACKs return
"Slow response" curl -w timing, then mtr Isolate DNS, connect, TLS, or path latency
"DNS not resolving" dig +trace, check /etc/resolv.conf Trace delegation, verify resolver config
"Intermittent drops" mtr -r -c 200 Accumulate loss statistics per hop
"TLS error" openssl s_client Inspect cert chain, protocol, cipher
"Bandwidth seems low" iperf3 between endpoints Measure actual throughput
"What is using port X" ss -tlnp, lsof -i :X Find the process
"NIC errors" ethtool -S, ip -s link Check hardware error counters
"Can't reach gateway" arping -I eth0 gateway_ip Test L2 before L3
"MTU issues" ping -c 1 -s 1472 -M do target Test path MTU

The layered approach matters: always start at the lowest layer that could be broken and work up. Testing L7 when L3 is down wastes time. Testing L3 when L2 is down hides the real problem.


Wiki Navigation

Prerequisites