Networking Deep Dive cheat sheet
81 commands from every lesson of Networking Deep Dive, on one page.
Link layer
ip -br link | Interfaces, state and MAC addresses |
ip neigh | ARP/neighbour table (IP → MAC) |
sudo tcpdump -eni eth0 arp | Watch ARP requests and replies, with MACs |
cat /proc/net/bonding/bond0 | Bond mode and member link status |
ip -d link show eth0.100 | VLAN details (id, parent) |
MTU
ip link show eth0 | grep mtu | Interface MTU |
ping -M do -s 1472 10.0.0.20 | Test a full 1500-byte packet without fragmentation |
tracepath 10.0.0.20 | Discover the path MTU |
Routing
ip route | Main routing table |
ip route get 10.96.0.10 | Which route and source address a destination uses |
ip rule | Policy routing rules (which table to consult) |
ip route show table all | head | Routes in every table |
NAT & conntrack
sudo iptables -t nat -S | head -40 | NAT rules (iptables-based kube-proxy) |
sudo nft list ruleset | less | All nftables rules |
sudo conntrack -L | head | Tracked connections (conntrack-tools) |
sudo conntrack -S | Per-CPU stats, including drops and insert failures |
sysctl net.netfilter.nf_conntrack_count net.netfilter.nf_conntrack_max | Current vs maximum tracked connections |
See connections
ss -tan state established | wc -l | How many established connections |
ss -tan | awk 'NR>1 {print $1}' | sort | uniq -c | Connections per state |
ss -ti dst 10.0.5.20 | Per-connection RTT, cwnd, retransmits |
nstat -az | grep -E 'TcpRetransSegs|ListenOverflows|ListenDrops' | Kernel TCP counters |
Capture
sudo tcpdump -ni any 'tcp port 443 and (tcp[tcpflags] & (tcp-syn|tcp-rst) != 0)' | Only SYNs and RSTs |
sysctl net.ipv4.tcp_congestion_control | Congestion control algorithm (cubic, bbr…) |
Build it by hand
sudo ip netns add pod1 | Create a network namespace (a 'pod') |
sudo ip link add veth-pod1 type veth peer name veth-host1 | A virtual cable with two ends |
sudo ip link set veth-pod1 netns pod1 | Plug one end into the namespace |
sudo ip link add br0 type bridge && sudo ip link set veth-host1 master br0 | Plug the other end into a bridge |
sudo ip netns exec pod1 ip addr | Run a command inside the namespace |
Inspect a real node
ip -br link | grep -E 'veth|cali|lxc|cni' | Host-side ends of pod veth pairs (names depend on the CNI) |
sudo nsenter -t <pid> -n ip route | A pod's routes, from the node |
ls /etc/cni/net.d/ /opt/cni/bin/ | CNI config and plugin binaries |
Identify the CNI
ls /etc/cni/net.d/ | Which CNI config is active on a node |
kubectl get pods -n kube-system -o wide | grep -E 'calico|cilium|flannel|kindnet|aws-node' | CNI agent pods |
kubectl get nodes -o jsonpath='{.items[*].spec.podCIDR}' | Per-node pod CIDRs (if the CNI uses them) |
CNI-specific tools
cilium status / cilium connectivity test | Cilium health and an end-to-end test suite |
hubble observe --namespace shop | Cilium: live flow logs |
calicoctl node status | Calico: BGP peering status |
Which mode am I in?
kubectl -n kube-system get cm kube-proxy -o yaml | grep mode | kube-proxy mode (empty = platform default) |
curl -s localhost:10249/proxyMode | Ask kube-proxy on a node |
cilium status | grep KubeProxyReplacement | Cilium replacing kube-proxy? |
Inspect the rules
sudo iptables -t nat -L KUBE-SERVICES -n | head | iptables mode Service rules |
sudo ipvsadm -Ln | IPVS mode virtual servers and backends |
sudo nft list table ip kube-proxy | head -50 | nftables mode rules |
cilium service list | eBPF service table (Cilium) |
Inspect
kubectl exec <pod> -- cat /etc/resolv.conf | The pod's resolver config |
kubectl -n kube-system get cm coredns -o yaml | The Corefile (CoreDNS configuration) |
kubectl -n kube-system logs -l k8s-app=kube-dns | CoreDNS logs (enable the 'log' plugin to see queries) |
Test
kubectl run dns --rm -it --image=busybox:1.36 --restart=Never -- nslookup web.shop | Resolve a Service |
dig +search web | Resolve using search domains (where dig is available) |
dig @10.96.0.10 web.shop.svc.cluster.local | Ask CoreDNS directly by its Service IP |
MetalLB
kubectl get ipaddresspools,l2advertisements,bgpadvertisements -n metallb-system | MetalLB configuration |
kubectl get svc -A --field-selector spec.type=LoadBalancer | LoadBalancer Services and their external IPs |
kubectl -n metallb-system logs -l component=speaker | Which node announces which IP |
Client IP
externalTrafficPolicy: Local | Keep the source IP at L4 (no SNAT hop) |
X-Forwarded-For / Forwarded | Client IP carried in HTTP headers by L7 proxies |
PROXY protocol v1/v2 | Client IP prepended to the TCP stream by L4 proxies |
openssl s_client
openssl s_client -connect host:443 -servername host </dev/null | Handshake details and the served chain |
… -showcerts | Print every certificate the server sends |
… | openssl x509 -noout -subject -issuer -dates -ext subjectAltName | Summarise the leaf certificate |
… -alpn h2,http/1.1 | Which application protocol the server picks |
openssl verify -CAfile ca.crt server.crt | Does this chain validate against this CA? |
curl
curl -v https://host/ | TLS version, cipher, certificate, then HTTP |
curl --cacert ca.crt https://host/ | Trust a specific (private) CA |
curl --cert client.crt --key client.key https://host/ | Present a client certificate (mTLS) |
Test protocol versions
curl -sI --http1.1 https://host/ | head -1 | Force HTTP/1.1 |
curl -sI --http2 https://host/ | head -1 | Try HTTP/2 (via ALPN) |
curl -sI --http3 https://host/ | head -1 | Try HTTP/3 (needs a curl built with HTTP/3 support) |
curl -w '%{http_version} %{time_connect} %{time_starttransfer}\n' -o /dev/null -s https://host/ | Version and timing |
grpcurl
grpcurl -plaintext localhost:50051 list | Services exposed (needs server reflection) |
grpcurl -plaintext localhost:50051 describe orders.v1.Orders | Methods and messages |
grpcurl -plaintext -d '{"id": "42"}' localhost:50051 orders.v1.Orders/GetOrder | Call a method with JSON input |
grpcurl -plaintext localhost:50051 grpc.health.v1.Health/Check | Standard health check |
Kubernetes
readinessProbe: grpc: {port: 50051} | Native gRPC health probes |
clusterIP: None | Headless Service so clients can see every pod (client-side balancing) |
One command per layer
dig +short shop.example.com | DNS: does the name resolve to the right address? |
nc -vz <ip> 443 | TCP: can I connect at all? |
openssl s_client -connect <ip>:443 -servername shop.example.com </dev/null | TLS: which certificate, which chain? |
curl -v --resolve shop.example.com:443:<ip> https://shop.example.com/ | HTTP: status, headers, timings |
kubectl get endpointslices -n shop | Service: are there ready backends? |
kubectl -n shop exec deploy/web -- wget -qO- -T 3 http://api:8080/health | Pod-to-pod: does the internal hop work? |
ping -M do -s 1422 <pod-ip> | MTU: do full-size packets survive the overlay? |