Linux CLI Cheat Sheet
An exhaustive Linux CLI reference for network engineers covering routing, DNS, packet capture, firewalling, NAT, TLS, VPNs, logs, hardening, and security triage.
How to Use This Sheet
Linux is often the best observation point in a network: the host knows the selected route, source address, socket state, resolver behavior, firewall state, packet counters, and application error path.
Use this as a field reference for network engineering, architecture validation, security troubleshooting, and change-window evidence.
| Situation | Start here |
|---|---|
| Unknown connectivity failure | ip route get, ss, dig, tcpdump |
| Multi-homed host | ip rule show, ip route show table all, ip route get ... from ... |
| Container, VRF, or tenant issue | ip netns, ip vrf exec, namespace-aware tcpdump |
| Port or application issue | ss -lntup, nc, curl -vk, openssl s_client |
| DNS issue | resolvectl, getent hosts, dig, tcpdump port 53 |
| Firewall or NAT issue | nft list ruleset, conntrack -L, packet capture on both sides |
| Packet evidence needed | Filtered tcpdump, rotating capture, tshark summaries |
| Security triage | listening ports, logins, services, cron, systemd timers, package changes |
Safety rule: during incidents, prefer read-only commands first. Do not flush routes, neighbor tables, connection tracking, firewall rules, or interfaces unless you have approval and rollback.
Core Navigation and Files
pwd # current directory
ls -lah # detailed listing
cd /path/to/dir # change directory
find /var/log -type f -name "*.log" -mtime -2
tree -L 2 /etc # directory tree, if installed
stat file # timestamps, size, inode, permissions
file binary-or-capture.pcap # identify file type
Useful file viewers:
less file.log # paged view
less +F /var/log/syslog # follow, Ctrl+C to pause
tail -f /var/log/syslog # follow live log
tail -n 200 file.log # last 200 lines
head -n 50 file.log # first 50 lines
Search and extract:
grep -Rni "error" /var/log
grep -E "DROP|REJECT|DENIED" /var/log/syslog
awk '{print $1,$2,$3,$5}' file.log
sed -n '100,160p' file.log
cut -d: -f1 /etc/passwd
sort file | uniq -c | sort -nr
Permissions:
ls -l file
chmod 640 file
chmod -R go-rwx private-dir/
chown user:group file
getfacl file # Access Control List, if installed
setfacl -m u:alice:r file
| Octal | Meaning |
|---|---|
7 |
read, write, execute |
6 |
read, write |
5 |
read, execute |
4 |
read only |
0 |
no permission |
Identity, Host, and Time
hostnamectl
uname -a
cat /etc/os-release
uptime
date -Is
timedatectl
whoami
id
who
w
last -a | head
lastlog | head
Time matters for packet capture, logs, certificates, Kerberos, DNS, and distributed troubleshooting.
timedatectl status
chronyc tracking # chrony
chronyc sources -v
ntpq -p # classic NTP, if present
journalctl --since "2026-07-03 10:00" --until "2026-07-03 10:30"
Processes, Services, and Logs
ps aux
ps -ef --forest
pgrep -a nginx
top
htop # if installed
pidstat 1 # sysstat, if installed
kill -TERM <pid>
kill -KILL <pid> # last resort
Systemd:
systemctl status nginx
systemctl is-enabled nginx
systemctl list-units --type=service --state=running
systemctl list-timers --all
systemctl restart nginx
systemctl reload nginx
systemctl cat nginx
Journal:
journalctl -u nginx --since "30 minutes ago"
journalctl -u nginx -f
journalctl -k --since "1 hour ago"
journalctl -p warning..alert --since today
journalctl _PID=<pid>
Traditional logs:
tail -f /var/log/syslog
tail -f /var/log/messages
tail -f /var/log/auth.log
tail -f /var/log/secure
tail -f /var/log/audit/audit.log
Interface and Address State
Prefer ip from iproute2; treat ifconfig, route, and netstat as legacy.
ip -br link
ip -br addr
ip addr show dev eth0
ip -d link show dev eth0
ip -s link show dev eth0
ip link set dev eth0 up
ip link set dev eth0 down
Address changes:
ip addr add 192.0.2.10/24 dev eth0
ip addr del 192.0.2.10/24 dev eth0
ip -6 addr show dev eth0
Counters to watch:
| Counter | Why it matters |
|---|---|
| RX/TX packets | Confirms traffic direction and activity. |
| errors | Physical, driver, duplex, or offload issues. |
| dropped | Queue, policy, driver, or resource pressure. |
| overruns | Host cannot keep up with receive rate. |
| carrier | Physical link instability. |
Driver and link details:
ethtool eth0
ethtool -i eth0
ethtool -S eth0
ethtool -k eth0
ethtool -g eth0
Offload warning: checksum offload, Generic Segmentation Offload (GSO), Generic Receive Offload (GRO), and Large Receive Offload (LRO) can make local captures look different from wire traffic.
VLANs, Bonds, Bridges, Tunnels
VLANs:
ip -d link show type vlan
ip link add link eth0 name eth0.100 type vlan id 100
ip addr add 10.100.0.10/24 dev eth0.100
ip link set eth0.100 up
Bonds:
ip -d link show type bond
cat /proc/net/bonding/bond0
ip link set eth1 master bond0
ip link set eth2 master bond0
Bridges:
bridge link
bridge vlan show
bridge fdb show
ip link show type bridge
ip link add br0 type bridge
ip link set eth1 master br0
Tunnels:
ip tunnel show
ip -d link show type vxlan
ip -d link show type gre
ip link add vxlan100 type vxlan id 100 dev eth0 remote 203.0.113.2 dstport 4789
Routing, Policy Routing, and Source Selection
Always start with what Linux will do from the source host.
ip route show
ip route show table main
ip route show table all
ip route get 203.0.113.10
ip route get 203.0.113.10 from 10.20.30.40
ip -6 route get 2001:db8::10
Route changes:
ip route add 203.0.113.0/24 via 10.0.0.1 dev eth0
ip route replace default via 10.0.0.1 dev eth0
ip route del 203.0.113.0/24
Policy routing:
ip rule show
ip rule add from 10.20.30.40/32 table 100 priority 100
ip route add default via 10.20.30.1 dev eth1 table 100
ip route flush cache
Route output clues:
| Clue | Meaning |
|---|---|
dev eth0 |
selected egress interface |
src 10.20.30.40 |
selected source address |
via 10.20.30.1 |
next hop |
table 100 |
non-main routing table |
metric |
route preference when multiple routes match |
proto dhcp |
route learned from DHCP |
proto static |
configured route |
VRF, Network Namespace, and Container Views
Testing from the wrong namespace is a common mistake.
Network namespaces:
ip netns list
ip netns exec blue ip addr
ip netns exec blue ip route get 203.0.113.10
ip netns exec blue ss -lntup
ip netns exec blue tcpdump -ni any host 203.0.113.10
Create a simple namespace:
ip netns add blue
ip link add veth-blue type veth peer name veth-host
ip link set veth-blue netns blue
ip netns exec blue ip link set lo up
VRF:
ip link show type vrf
ip route show vrf CUSTOMER_A
ip vrf exec CUSTOMER_A ip route get 203.0.113.10
ip vrf exec CUSTOMER_A ping 203.0.113.10
Containers:
docker ps
docker inspect <container>
docker exec -it <container> sh
nsenter -t <pid> -n ip addr
nsenter -t <pid> -n ss -lntup
Kubernetes node view:
kubectl get pods -A -o wide
kubectl describe pod <pod> -n <namespace>
kubectl exec -n <namespace> -it <pod> -- sh
kubectl logs -n <namespace> <pod>
Neighbor Discovery, ARP, and Layer 2
IPv4 ARP and IPv6 Neighbor Discovery determine local adjacency.
ip neigh show
ip neigh show dev eth0
ip neigh get 192.0.2.1 dev eth0
ip neigh flush 192.0.2.1
arping -I eth0 192.0.2.1
IPv6:
ip -6 neigh show
ping -6 ff02::1%eth0
ndisc6 2001:db8::1 eth0 # if installed
Watch for:
| State | Meaning |
|---|---|
REACHABLE |
neighbor confirmed recently |
STALE |
known, but not recently confirmed |
DELAY / PROBE |
kernel is checking reachability |
FAILED |
neighbor resolution failed |
| MAC changes | duplicate IP, failover, proxy ARP, or spoofing |
DNS and Resolver Troubleshooting
Test both DNS protocol behavior and operating-system resolver behavior.
resolvectl status
resolvectl query app.example.com
cat /etc/resolv.conf
cat /etc/nsswitch.conf
getent hosts app.example.com
dig app.example.com
dig A app.example.com
dig AAAA app.example.com
dig MX example.com
dig TXT example.com
dig @8.8.8.8 app.example.com
dig +trace app.example.com
Reverse lookup:
dig -x 203.0.113.10
host 203.0.113.10
DNS packet capture:
tcpdump -ni any port 53
tcpdump -ni any 'udp port 53 or tcp port 53'
Common patterns:
| Symptom | Check |
|---|---|
dig works, application fails |
NSS, /etc/hosts, proxy, app resolver, search domain |
| Internal name resolves externally | split-horizon DNS, VPN DNS, conditional forwarder |
| Slow connection start | first resolver timeout, IPv6 preference, search suffix delay |
| Different answer per resolver | cache, anycast, geo-DNS, stale forwarding |
| Large DNS response fails | TCP/53, EDNS, firewall, MTU |
Connectivity Tests by Layer
Layer 3:
ping -c 4 203.0.113.10
ping -I eth0 -c 4 203.0.113.10
ping -6 -c 4 2001:db8::10
Path:
traceroute 203.0.113.10
traceroute -T -p 443 203.0.113.10
tracepath 203.0.113.10
mtr -rwzc 100 203.0.113.10
Layer 4:
nc -vz 203.0.113.10 443
nc -vzu 203.0.113.10 53
nping --tcp -p 443 203.0.113.10
hping3 -S -p 443 203.0.113.10
Application:
curl -I https://example.com/
curl -vk --connect-timeout 3 https://example.com/
curl --resolve example.com:443:203.0.113.10 https://example.com/
openssl s_client -connect example.com:443 -servername example.com
Interpretation:
| Result | Likely area |
|---|---|
| Ping works, TCP fails | firewall, listener, security group, TCP policy |
| TCP connects, HTTP fails | virtual host, proxy, TLS, application |
| DNS resolves wrong IP | resolver policy, record, cache |
| SYN leaves, no reply | path, firewall, return routing, remote listener |
| SYN, SYN-ACK, RST | local or remote stack rejected after handshake |
MTU, MSS, Fragmentation
Path MTU issues often appear as slow TLS, broken uploads, hanging SSH, or services that work for small payloads only.
ip link show dev eth0
tracepath 203.0.113.10
ping -M do -s 1472 203.0.113.10
ping -M do -s 8972 203.0.113.10
For IPv4 over Ethernet, -s 1472 plus ICMP and IP headers fits a 1500-byte MTU.
TCP Maximum Segment Size (MSS):
tcpdump -ni eth0 'tcp[tcpflags] & tcp-syn != 0'
Look for MSS options in SYN and SYN-ACK packets.
Common causes:
- tunnel overhead not accounted for
- jumbo enabled on one segment only
- blocked ICMP fragmentation-needed messages
- asymmetric path with different MTU
- VPN or overlay reducing usable payload
Socket and Port State
ss -lntup
ss -lnup
ss -ntp state established
ss -ntp state syn-sent
ss -s
lsof -nP -iTCP -sTCP:LISTEN
fuser -v 443/tcp
Socket clues:
| Pattern | Meaning |
|---|---|
127.0.0.1:443 |
local-only listener |
0.0.0.0:443 |
all IPv4 addresses |
[::]:443 |
IPv6 listener, possibly dual-stack |
SYN-SENT |
outbound TCP attempt not completing |
SYN-RECV |
inbound handshake half-open |
TIME-WAIT |
closed TCP sessions retained temporarily |
| no listener | network may be fine; application is absent |
Tune only with care:
sysctl net.ipv4.ip_local_port_range
sysctl net.ipv4.tcp_fin_timeout
sysctl net.ipv4.tcp_tw_reuse
Packet Capture With tcpdump
Basic capture:
tcpdump -ni any
tcpdump -ni eth0 host 203.0.113.10
tcpdump -ni eth0 'host 203.0.113.10 and tcp port 443'
tcpdump -ni eth0 'src 10.0.0.10 and dst 203.0.113.10'
Useful filters:
tcpdump -ni eth0 'icmp'
tcpdump -ni eth0 'icmp6'
tcpdump -ni eth0 'arp'
tcpdump -ni eth0 'port 53'
tcpdump -ni eth0 'tcp[tcpflags] & (tcp-syn|tcp-ack|tcp-rst) != 0'
tcpdump -ni eth0 'tcp[tcpflags] & tcp-rst != 0'
tcpdump -ni eth0 'vlan 100'
Write captures:
tcpdump -ni eth0 -s 0 -w issue.pcap host 203.0.113.10
tcpdump -ni eth0 -s 0 -C 100 -W 10 -w ring.pcap host 203.0.113.10
tcpdump -r issue.pcap
tcpdump -nnr issue.pcap 'tcp port 443'
Evidence checklist:
| Evidence | Meaning |
|---|---|
| request leaves expected interface | source route and egress are correct |
| no reply returns | remote, firewall, path, or return route issue |
| reply returns on different interface | asymmetric routing |
| RST from server | remote service or policy rejected |
| RST from client | local stack or app rejected |
| ICMP unreachable | network or firewall generated explicit failure |
| TLS alert after TCP | TLS policy, SNI, cipher, certificate, or mTLS issue |
tshark and Capture Summaries
When Wireshark is not available on the server, use tshark.
tshark -r issue.pcap
tshark -r issue.pcap -q -z conv,tcp
tshark -r issue.pcap -q -z io,stat,1
tshark -r issue.pcap -Y "tcp.flags.reset == 1"
tshark -r issue.pcap -Y "dns" -T fields -e frame.time -e ip.src -e dns.qry.name
Extract HTTP and TLS clues:
tshark -r issue.pcap -Y "http" -T fields -e http.host -e http.request.uri -e http.response.code
tshark -r issue.pcap -Y "tls.handshake.extensions_server_name" -T fields -e tls.handshake.extensions_server_name
Firewalling With nftables, iptables, firewalld, and ufw
Current Linux distributions often use nftables. Older systems may use iptables.
nftables:
nft list ruleset
nft list tables
nft list table inet filter
nft monitor trace
nft add rule inet filter input tcp dport 443 accept
iptables:
iptables-save
iptables -S
iptables -L -n -v --line-numbers
iptables -t nat -L -n -v --line-numbers
ip6tables-save
firewalld:
firewall-cmd --state
firewall-cmd --get-active-zones
firewall-cmd --list-all
firewall-cmd --zone=public --add-service=https --permanent
firewall-cmd --reload
ufw:
ufw status verbose
ufw allow 443/tcp
ufw deny from 203.0.113.0/24
ufw reload
Troubleshooting order:
- Confirm listener with
ss. - Confirm route with
ip route get. - Capture packet ingress and egress.
- Review firewall counters.
- Review connection tracking state.
NAT and Connection Tracking
Stateful firewalls and NAT depend on connection tracking.
conntrack -S
conntrack -L | head
conntrack -L | grep 203.0.113.10
conntrack -E
conntrack -L -p tcp --dport 443
NAT inspection:
nft list ruleset | grep -iE 'dnat|snat|masquerade'
iptables -t nat -L -n -v --line-numbers
Useful questions:
| Question | Command |
|---|---|
| Was state created? | `conntrack -L |
| Is it unreplied? | look for UNREPLIED |
| Was source translated? | inspect NAT table and capture post-NAT side |
| Was destination translated? | inspect DNAT rule and listener |
| Is return traffic bypassing state? | capture both interfaces |
Avoid clearing all state during production:
conntrack -D -p tcp --dport 443 # targeted delete, still disruptive
Load Balancing and Reverse Proxy Checks
Common local reverse proxy checks:
nginx -t
nginx -T | less
apachectl configtest
haproxy -c -f /etc/haproxy/haproxy.cfg
Backend testing:
curl -vk https://frontend.example.com/
curl -vk --resolve frontend.example.com:443:203.0.113.10 https://frontend.example.com/
curl -v http://127.0.0.1:8080/health
ss -lntup | grep -E ':80|:443|:8080'
Proxy clues:
| Symptom | Check |
|---|---|
502 |
backend down, connect timeout, wrong upstream |
503 |
no healthy backend, maintenance, overload |
504 |
upstream timeout |
| certificate mismatch | SNI, wrong virtual host, wrong listener |
| client IP missing | X-Forwarded-For, PROXY protocol, trusted proxy config |
TLS, Certificates, and PKI
Inspect a remote certificate:
openssl s_client -connect example.com:443 -servername example.com
openssl s_client -connect example.com:443 -servername example.com -showcerts
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -subject -issuer -dates
Inspect local certificate files:
openssl x509 -in cert.pem -noout -text
openssl x509 -in cert.pem -noout -subject -issuer -dates -ext subjectAltName
openssl rsa -in key.pem -check
openssl pkey -in key.pem -check
Match certificate and key:
openssl x509 -noout -modulus -in cert.pem | openssl md5
openssl rsa -noout -modulus -in key.pem | openssl md5
Protocol testing:
openssl s_client -tls1_2 -connect example.com:443 -servername example.com
openssl s_client -tls1_3 -connect example.com:443 -servername example.com
nmap --script ssl-enum-ciphers -p 443 example.com
Certificate failure checks:
| Failure | Check |
|---|---|
| expired certificate | openssl x509 -noout -dates |
| hostname mismatch | Subject Alternative Name (SAN) |
| wrong chain | -showcerts, intermediate CA |
| SNI failure | -servername |
| mutual TLS failure | client certificate, CA trust, policy |
SSH, SCP, rsync, and Tunnels
SSH debug:
ssh -vvv user@host
ssh -o IdentitiesOnly=yes -i ~/.ssh/key user@host
ssh -J jumpuser@jumphost user@target
ssh -o ProxyJump=jumpuser@jumphost user@target
File transfer:
scp file user@host:/tmp/
rsync -avz --progress dir/ user@host:/tmp/dir/
rsync -avz --delete source/ user@host:/srv/app/
Tunnels:
ssh -L 8443:internal.example.com:443 user@jump
ssh -R 2222:localhost:22 user@remote
ssh -D 1080 user@jump
SSH server checks:
ss -lntup | grep ':22'
journalctl -u ssh --since "1 hour ago"
journalctl -u sshd --since "1 hour ago"
sshd -T | less
Security checks:
grep -E 'PermitRootLogin|PasswordAuthentication|PubkeyAuthentication' /etc/ssh/sshd_config
find ~/.ssh -maxdepth 1 -type f -ls
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_*
chmod 644 ~/.ssh/*.pub
VPNs: WireGuard and IPsec
WireGuard:
wg show
wg showconf wg0
ip addr show dev wg0
ip route show table all | grep wg0
journalctl -u wg-quick@wg0 --since "1 hour ago"
WireGuard checks:
| Check | Why |
|---|---|
| latest handshake | confirms peer is alive |
| transfer counters | confirms traffic movement |
| allowed IPs | controls route selection and peer matching |
| endpoint | confirms remote address and port |
| MTU | common tunnel failure point |
IPsec/strongSwan:
ipsec statusall
swanctl --list-sas
swanctl --list-conns
journalctl -u strongswan --since "1 hour ago"
tcpdump -ni any 'udp port 500 or udp port 4500 or esp'
Common VPN failure areas:
- peer identity mismatch
- proposal mismatch
- NAT traversal
- overlapping routes
- asymmetric return path
- MTU/MSS issues
- firewall blocking UDP/500, UDP/4500, ESP, or WireGuard UDP port
HTTP, APIs, and Proxies
HTTP checks:
curl -I https://example.com/
curl -vk https://example.com/
curl -v --connect-timeout 3 https://example.com/
curl -sS -w '\ncode=%{http_code} time=%{time_total} ip=%{remote_ip}\n' https://example.com/
curl -H 'Host: app.example.com' http://203.0.113.10/
Proxy checks:
env | grep -i proxy
curl -v -x http://proxy.example.com:8080 https://example.com/
curl --noproxy '*' https://example.com/
API checks:
curl -sS -X GET https://api.example.com/health
curl -sS -H "Authorization: Bearer <token>" https://api.example.com/me
curl -sS -X POST -H "Content-Type: application/json" -d '{"test":true}' https://api.example.com/test
Timing breakdown:
curl -o /dev/null -sS -w 'dns=%{time_namelookup} connect=%{time_connect} tls=%{time_appconnect} first_byte=%{time_starttransfer} total=%{time_total}\n' https://example.com/
Mail and Messaging Protocol Checks
SMTP:
dig MX example.com
nc -vz mail.example.com 25
openssl s_client -starttls smtp -connect mail.example.com:587 -servername mail.example.com
swaks --to user@example.com --server mail.example.com
IMAP/POP:
openssl s_client -connect imap.example.com:993 -servername imap.example.com
openssl s_client -connect pop.example.com:995 -servername pop.example.com
Messaging and queues:
nc -vz broker.example.com 5672 # AMQP
nc -vz broker.example.com 9092 # Kafka
nc -vz redis.example.com 6379
SNMP, NTP, Syslog, and Management Plane
SNMP:
snmpwalk -v2c -c public 192.0.2.10 sysName
snmpwalk -v3 -l authPriv -u user -a SHA -A authpass -x AES -X privpass 192.0.2.10 sysName
tcpdump -ni any 'udp port 161 or udp port 162'
NTP:
chronyc tracking
chronyc sources -v
ntpq -p
timedatectl status
tcpdump -ni any udp port 123
Syslog:
logger "test syslog message"
tail -f /var/log/syslog
tail -f /var/log/messages
tcpdump -ni any 'udp port 514 or tcp port 514'
Management access:
nc -vz device.example.com 22
nc -vz device.example.com 443
curl -vk https://device.example.com/
Performance, Capacity, and Kernel Counters
CPU and memory:
uptime
free -h
vmstat 1
mpstat 1
pidstat 1
Disk:
df -h
du -sh /var/log/*
lsblk
iostat -xz 1
Network throughput and counters:
ip -s link show dev eth0
nstat -az
netstat -s
sar -n DEV 1
sar -n TCP,ETCP 1
iftop -i eth0 # if installed
nload eth0 # if installed
Kernel network settings:
sysctl net.ipv4.ip_forward
sysctl net.ipv4.conf.all.rp_filter
sysctl net.ipv4.tcp_congestion_control
sysctl net.core.somaxconn
sysctl net.ipv4.tcp_max_syn_backlog
Do not tune kernel parameters blindly. Capture baseline, symptom, change, and rollback.
Security Triage: What Is Running and Listening
Listening services:
ss -lntup
lsof -nP -i
systemctl list-units --type=service --state=running
systemctl list-unit-files --state=enabled
Recent logins:
who
w
last -a | head -50
lastb | head -50 # failed logins, if available
journalctl _COMM=sshd --since "24 hours ago"
grep -i "failed password" /var/log/auth.log
grep -i "accepted" /var/log/auth.log
Users and privilege:
getent passwd
getent group sudo
getent group wheel
sudo -l
find / -perm -4000 -type f 2>/dev/null
find / -perm -2000 -type f 2>/dev/null
Persistence points:
crontab -l
ls -la /etc/cron.*
systemctl list-timers --all
systemctl list-unit-files | grep enabled
find /etc/systemd/system -type f -maxdepth 2 -ls
ls -la ~/.ssh/authorized_keys
Package changes:
rpm -qa --last | head # RHEL-family
dnf history
dpkg -l | head # Debian-family
grep " install " /var/log/dpkg.log
apt history list
Security Controls: SELinux, AppArmor, Audit
SELinux:
getenforce
sestatus
ausearch -m avc -ts recent
journalctl | grep -i denied
semanage port -l | grep http # if policycoreutils installed
AppArmor:
aa-status
journalctl | grep -i apparmor
Audit:
auditctl -s
auditctl -l
ausearch -k <key>
ausearch -m USER_LOGIN -ts today
aureport -au
When a service is listening but access fails locally, check MAC controls before assuming routing or firewall failure.
Hashing, Encoding, and File Integrity
sha256sum file
sha512sum file
md5sum file # compatibility only, not security
gpg --verify file.sig file
base64 file
base64 -d encoded.txt
xxd file | head
strings binary | less
Compare directories:
diff -ru old/ new/
rsync -avnc source/ dest/ # dry-run comparison
find /etc -type f -mtime -2 -ls
Cloud and Metadata Checks
Cloud instances often inherit networking from metadata, DHCP, cloud-init, security groups, and route tables outside the host.
cloud-init status --long
journalctl -u cloud-init --since "1 hour ago"
ip route get 169.254.169.254
curl -sS --connect-timeout 2 http://169.254.169.254/
Common checks:
| Area | Linux evidence |
|---|---|
| wrong private IP | ip addr, cloud console |
| wrong default route | ip route, DHCP lease |
| blocked access | ss, host firewall, cloud security group |
| metadata failure | route to 169.254.169.254, HTTP test |
| DNS mismatch | /etc/resolv.conf, resolvectl, VPC/VNet resolver |
Common Investigation Chains
TCP Service Unreachable
ip route get 203.0.113.10
ss -lntup | grep ':443'
nc -vz 203.0.113.10 443
tcpdump -ni any 'host 203.0.113.10 and tcp port 443'
nft list ruleset
conntrack -L | grep 203.0.113.10
DNS Works on One Host but Not Another
cat /etc/resolv.conf
resolvectl status
getent hosts app.example.com
dig app.example.com
dig @<resolver-ip> app.example.com
tcpdump -ni any port 53
TLS Certificate or SNI Issue
dig app.example.com
openssl s_client -connect app.example.com:443 -servername app.example.com -showcerts
curl -vk https://app.example.com/
tcpdump -ni any 'host app.example.com and tcp port 443'
Suspected Asymmetric Routing
ip route get 203.0.113.10
ip route get 203.0.113.10 from <source-ip>
tcpdump -ni eth0 host 203.0.113.10
tcpdump -ni eth1 host 203.0.113.10
conntrack -L | grep 203.0.113.10
MTU or Tunnel Problem
ip link show dev eth0
ip link show dev wg0
tracepath 203.0.113.10
ping -M do -s 1472 203.0.113.10
tcpdump -ni any 'icmp or host 203.0.113.10'
Linux Host Security Quick Triage
date -Is
hostnamectl
ss -lntup
who
last -a | head -50
systemctl list-units --type=service --state=running
systemctl list-timers --all
find / -perm -4000 -type f 2>/dev/null
journalctl -p warning..alert --since "24 hours ago"
Commands to Treat With Care
These commands can disrupt production. Use targeted scope and rollback.
ip link set eth0 down
ip route flush table main
ip neigh flush all
conntrack -F
nft flush ruleset
iptables -F
systemctl restart networking
systemctl restart NetworkManager
reboot
rm -rf <path>
chmod -R 777 <path>
Before running disruptive commands:
- Capture current state.
- Confirm access path will survive.
- Write rollback.
- Run the smallest targeted change.
- Verify with packet, route, socket, and log evidence.
Minimal Tool Map
| Tool | Primary use |
|---|---|
ip |
interfaces, addresses, routes, policy, namespaces, VRFs |
ss |
sockets, listeners, TCP states |
dig / getent |
DNS protocol and OS resolver behavior |
curl |
HTTP, HTTPS, proxy, timing, headers |
openssl |
TLS, certificates, cipher/protocol checks |
tcpdump |
packet evidence |
tshark |
capture analysis on CLI |
nft / iptables |
local firewall policy |
conntrack |
state table, NAT evidence |
journalctl |
system, service, and kernel logs |
ethtool |
NIC, driver, offload, link counters |
mtr / tracepath |
path quality and MTU hints |
nc / nping / hping3 |
transport reachability probes |
systemctl |
service state and startup behavior |
auditctl / ausearch |
audit policy and security events |
The goal is not to memorize every command.
The goal is to prove the path, state, policy, and application behavior from the Linux system that is actually carrying the traffic.