ss & ip Commands
Quick Reference
# Socket Statistics (ss)
ss -tulnp # TCP/UDP listening ports with process
ss -tan # All TCP connections (numeric)
ss -s # Summary statistics
# IP Addresses (ip addr)
ip addr # Show all addresses
ip -br addr # Brief format
ip addr add 192.168.1.100/24 dev eth0 # Add address
# Interfaces (ip link)
ip link # Show all interfaces
ip link set eth0 up # Bring interface up
ip link set eth0 down # Bring interface down
# Routing (ip route)
ip route # Show routing table
ip route get 8.8.8.8 # Show route to destination
ip route add 10.0.0.0/8 via 192.168.1.1 # Add route
# Neighbors/ARP (ip neigh)
ip neigh # Show ARP table
ip neigh flush dev eth0 # Clear ARP cache for interface
Part 1: ss (Socket Statistics)
ss is the modern replacement for netstat, providing faster and more detailed socket information.
Why ss Over netstat?
| Feature | netstat | ss |
|---|---|---|
Speed |
Slow (reads /proc) |
Fast (uses netlink) |
Memory Info |
Limited |
Detailed (recv-Q, send-Q) |
Filter Syntax |
Basic |
Powerful expressions |
IPv6 Support |
Basic |
Full |
Socket States |
Limited display |
All kernel states |
Basic Usage
# All sockets
ss
# All TCP sockets
ss -t
# All UDP sockets
ss -u
# All UNIX domain sockets
ss -x
# All RAW sockets
ss -w
Essential Options
| Option | Description |
|---|---|
|
TCP sockets |
|
UDP sockets |
|
Listening sockets only |
|
All sockets (listening + established) |
|
Numeric (no DNS resolution) |
|
Show process using socket |
|
Extended info (uid, inode) |
|
Memory usage |
|
Internal TCP info |
|
Timer information |
|
Summary statistics |
|
IPv4 only |
|
IPv6 only |
Common Combinations
Show Listening Services
# TCP listening with process names (most common)
ss -tulnp
# Output:
# Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
# tcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=1234,fd=3))
# tcp LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=5678,fd=6))
Filtering Connections
By State
# TCP connection states
ss -tan state established # Active connections
ss -tan state listening # Listening sockets
ss -tan state time-wait # TIME_WAIT connections
ss -tan state close-wait # CLOSE_WAIT (potential issue)
ss -tan state syn-sent # Outgoing connection attempts
ss -tan state syn-recv # Incoming connection attempts
ss -tan state fin-wait-1 # Closing connections
ss -tan state fin-wait-2 # Closing connections
# Exclude states
ss -tan state all exclude listening
ss -tan state all exclude established
TCP State Reference:
LISTEN
|
v
SYN_RECV <------ SYN_SENT
| |
v v
ESTABLISHED <-> ESTABLISHED
| |
v v
FIN_WAIT_1 <---- CLOSE_WAIT
| |
v v
FIN_WAIT_2 LAST_ACK
| |
v v
TIME_WAIT -----> CLOSED
|
v
CLOSED
By Port
# Specific source port
ss -tan 'sport = :22'
ss -tan 'sport = :ssh'
# Specific destination port
ss -tan 'dport = :443'
ss -tan 'dport = :https'
# Port ranges
ss -tan 'sport >= :1024'
ss -tan 'dport < :1024'
# Multiple ports (OR)
ss -tan '( sport = :22 or sport = :80 )'
# Port not equal
ss -tan 'sport != :22'
By Address
# Source address
ss -tan 'src 192.168.1.100'
# Destination address
ss -tan 'dst 10.0.0.0/8'
# Localhost only
ss -tan 'src 127.0.0.0/8'
# Combined (address AND port)
ss -tan 'dst 192.168.1.1 and dport = :443'
Complex Filters
# Connections to specific subnet on HTTPS
ss -tan 'dst 10.50.0.0/16 and dport = :443'
# High-numbered source ports to SSH
ss -tan 'sport > :32768 and dport = :22'
# Established connections from specific IP
ss -tan 'src 192.168.1.50 and state established'
# All connections except localhost
ss -tan 'not src 127.0.0.0/8 and not dst 127.0.0.0/8'
Output Formats
Numeric vs Resolved
# Numeric (faster, no DNS)
ss -n
# Resolve service names only
ss -r
# Fully resolved (slow)
ss # default behavior without -n
Statistics Summary
ss -s
# Output:
# Total: 234
# TCP: 56 (estab 12, closed 2, orphaned 0, timewait 2)
# Transport Total IP IPv6
# RAW 0 0 0
# UDP 8 6 2
# TCP 54 40 14
# INET 62 46 16
# FRAG 0 0 0
Scripting Examples
List All Open Ports
# Simple port list
ss -tuln | awk 'NR>1 {print $5}' | cut -d: -f2 | sort -nu
# With service names
ss -tulnp | awk 'NR>1 {split($5,a,":"); print a[length(a)]}' | sort -nu
Monitor Connection Count
# Count by state
ss -tan | awk 'NR>1 {count[$1]++} END {for(s in count) print s, count[s]}'
# Watch connections in real-time
watch -n1 'ss -s'
# Log connection changes
while true; do
echo "$(date): $(ss -tan state established | wc -l) established"
sleep 5
done
Part 2: ip Command
ip from iproute2 is the modern replacement for ifconfig, route, arp, and netstat -i.
ip vs Legacy Commands
| Task | Legacy | Modern (ip) |
|---|---|---|
Show interfaces |
|
|
Show routing |
|
|
Show ARP |
|
|
Add address |
|
|
Set interface up |
|
|
Add route |
|
|
Global Options
| Option | Description |
|---|---|
|
Brief output (one line per interface) |
|
Color output |
|
IPv4 only |
|
IPv6 only |
|
Statistics |
|
Details |
|
Human-readable |
|
JSON output |
|
One-line output (for scripting) |
|
Resolve names |
ip link (Interface Management)
View Interfaces
# List all interfaces
ip link
ip link show
# Brief format (cleaner)
ip -br link
# Output:
# lo UNKNOWN 00:00:00:00:00:00 <LOOPBACK,UP,LOWER_UP>
# eth0 UP 52:54:00:12:34:56 <BROADCAST,MULTICAST,UP,LOWER_UP>
# wlan0 DOWN 00:11:22:33:44:55 <BROADCAST,MULTICAST>
# Specific interface
ip link show eth0
# With statistics
ip -s link show eth0
# Statistics output:
# RX: bytes packets errors dropped missed mcast
# 1234567 12345 0 0 0 0
# TX: bytes packets errors dropped carrier collsns
# 7654321 54321 0 0 0 0
Control Interfaces
# Bring interface up
sudo ip link set eth0 up
# Bring interface down
sudo ip link set eth0 down
# Set MTU
sudo ip link set eth0 mtu 9000
# Change MAC address (interface must be down)
sudo ip link set eth0 down
sudo ip link set eth0 address 00:11:22:33:44:55
sudo ip link set eth0 up
# Set promiscuous mode
sudo ip link set eth0 promisc on
sudo ip link set eth0 promisc off
# Rename interface
sudo ip link set eth0 down
sudo ip link set eth0 name lan0
sudo ip link set lan0 up
Create Virtual Interfaces
# Create VLAN interface
sudo ip link add link eth0 name eth0.10 type vlan id 10
sudo ip link set eth0.10 up
# Create bridge
sudo ip link add br0 type bridge
sudo ip link set eth0 master br0
sudo ip link set br0 up
# Create bond
sudo ip link add bond0 type bond mode 802.3ad
sudo ip link set eth0 master bond0
sudo ip link set eth1 master bond0
sudo ip link set bond0 up
# Create dummy interface (testing)
sudo ip link add dummy0 type dummy
sudo ip link set dummy0 up
# Create VETH pair (containers/namespaces)
sudo ip link add veth0 type veth peer name veth1
# Delete interface
sudo ip link delete eth0.10
ip addr (Address Management)
View Addresses
# Show all addresses
ip addr
ip addr show
# Brief format
ip -br addr
# Output:
# lo UNKNOWN 127.0.0.1/8 ::1/128
# eth0 UP 192.168.1.100/24 fe80::5054:ff:fe12:3456/64
# wlan0 DOWN
# IPv4 only
ip -4 addr
# IPv6 only
ip -6 addr
# Specific interface
ip addr show eth0
ip addr show dev eth0
# Only show running interfaces
ip addr show up
# Show scope global addresses (no link-local)
ip addr show scope global
Add/Remove Addresses
# Add IPv4 address
sudo ip addr add 192.168.1.100/24 dev eth0
# Add with broadcast (explicit)
sudo ip addr add 192.168.1.100/24 broadcast 192.168.1.255 dev eth0
# Add IPv6 address
sudo ip addr add 2001:db8::1/64 dev eth0
# Add secondary address (multiple IPs on one interface)
sudo ip addr add 192.168.1.101/24 dev eth0
# Add with label (alias-style)
sudo ip addr add 192.168.1.102/24 dev eth0 label eth0:0
# Remove specific address
sudo ip addr del 192.168.1.101/24 dev eth0
# Flush all addresses from interface
sudo ip addr flush dev eth0
# Flush only IPv4
sudo ip -4 addr flush dev eth0
Address Properties
# Temporary address (for privacy)
sudo ip addr add 192.168.1.150/24 dev eth0 valid_lft 3600 preferred_lft 1800
# Show address lifetime
ip -d addr show eth0
# Permanent vs Dynamic indicators in output:
# inet 192.168.1.100/24 scope global dynamic eth0
# ^^^ dynamic = DHCP
# inet 192.168.1.101/24 scope global secondary eth0
# ^^^ secondary = additional address
ip route (Routing)
View Routing Table
# Show main routing table
ip route
ip route show
# Output interpretation:
# default via 192.168.1.1 dev eth0 proto dhcp metric 100
# ^^^ default gateway
# 192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.100 metric 100
# ^^^ directly connected network
# Show route to specific destination
ip route get 8.8.8.8
# Output:
# 8.8.8.8 via 192.168.1.1 dev eth0 src 192.168.1.100 uid 1000
# Show all routing tables
ip route show table all
# Show specific table
ip route show table local
ip route show table main
# With protocol info
ip route show proto kernel # Directly connected
ip route show proto dhcp # DHCP-learned
ip route show proto static # Manually added
Add/Remove Routes
# Add route via gateway
sudo ip route add 10.0.0.0/8 via 192.168.1.254
# Add route via interface (point-to-point)
sudo ip route add 10.0.0.0/8 dev eth0
# Add default route
sudo ip route add default via 192.168.1.1
# Add route with metric
sudo ip route add 10.0.0.0/8 via 192.168.1.254 metric 100
# Add route to specific table
sudo ip route add 10.0.0.0/8 via 192.168.1.254 table 100
# Add blackhole route (drop traffic)
sudo ip route add blackhole 10.10.10.0/24
# Add unreachable route (send ICMP unreachable)
sudo ip route add unreachable 10.10.10.0/24
# Replace route (add or update)
sudo ip route replace 10.0.0.0/8 via 192.168.1.254
# Delete route
sudo ip route del 10.0.0.0/8
sudo ip route del default
# Flush routing cache
sudo ip route flush cache
ip neigh (ARP/Neighbor Cache)
View Neighbors
# Show ARP/neighbor table
ip neigh
ip neigh show
# Output:
# 192.168.1.1 dev eth0 lladdr 00:11:22:33:44:55 REACHABLE
# 192.168.1.50 dev eth0 lladdr aa:bb:cc:dd:ee:ff STALE
# States:
# REACHABLE - recently confirmed
# STALE - valid but not confirmed recently
# DELAY - waiting for confirmation
# PROBE - sending probes
# FAILED - no response
# PERMANENT - manually added
# Show specific interface
ip neigh show dev eth0
# Show specific address
ip neigh show 192.168.1.1
Manage Neighbors
# Add static ARP entry
sudo ip neigh add 192.168.1.50 lladdr aa:bb:cc:dd:ee:ff dev eth0
# Replace entry
sudo ip neigh replace 192.168.1.50 lladdr aa:bb:cc:dd:ee:ff dev eth0
# Delete entry
sudo ip neigh del 192.168.1.50 dev eth0
# Flush cache for interface
sudo ip neigh flush dev eth0
# Flush all STALE entries
sudo ip neigh flush all nud stale
ip rule (Policy Routing)
View Rules
# Show routing policy
ip rule
ip rule show
# Default output:
# 0: from all lookup local
# 32766: from all lookup main
# 32767: from all lookup default
Create Policy Routes
# Route specific source through different table
sudo ip rule add from 192.168.1.100 table 100
sudo ip route add default via 10.0.0.1 table 100
# Route by destination
sudo ip rule add to 10.0.0.0/8 table 100
# Route by fwmark (firewall mark)
sudo ip rule add fwmark 1 table 100
# Route by interface
sudo ip rule add iif eth0 table 100
sudo ip rule add oif eth0 table 100
# Set priority
sudo ip rule add from 192.168.1.100 table 100 priority 100
# Delete rule
sudo ip rule del from 192.168.1.100 table 100
ip netns (Network Namespaces)
Manage Namespaces
# List namespaces
ip netns list
# Create namespace
sudo ip netns add test-ns
# Delete namespace
sudo ip netns del test-ns
# Execute command in namespace
sudo ip netns exec test-ns ip addr
sudo ip netns exec test-ns bash
# Move interface to namespace
sudo ip link set eth1 netns test-ns
# Create veth pair for namespace connectivity
sudo ip link add veth0 type veth peer name veth1
sudo ip link set veth1 netns test-ns
sudo ip addr add 10.0.0.1/24 dev veth0
sudo ip link set veth0 up
sudo ip netns exec test-ns ip addr add 10.0.0.2/24 dev veth1
sudo ip netns exec test-ns ip link set veth1 up
sudo ip netns exec test-ns ip link set lo up
ip monitor (Event Monitoring)
# Monitor all network events
ip monitor
# Monitor specific events
ip monitor link # Interface changes
ip monitor addr # Address changes
ip monitor route # Routing changes
ip monitor neigh # ARP changes
# Multiple event types
ip monitor link addr route
# With timestamps
ip -ts monitor
Troubleshooting Workflows
Check Network Connectivity
# 1. Check interface status
ip -br link
# 2. Check IP addresses
ip -br addr
# 3. Check default route
ip route | grep default
# 4. Check route to destination
ip route get 8.8.8.8
# 5. Check established connections
ss -tan state established
# 6. Check DNS connectivity
ss -tan 'dport = :53'
Debug Service Not Accessible
# 1. Is service listening?
ss -tulnp | grep :80
# 2. On correct interface?
ss -tulnp | grep :80 | grep -E '0\.0\.0\.0|::|\*'
# 3. Firewall blocking?
# (Check with firewalld/nftables)
# 4. Check connections to service
ss -tan 'dport = :80'
Diagnose Slow Network
# 1. Check interface errors
ip -s link show eth0 | grep -E 'errors|dropped'
# 2. Check for connection issues
ss -tan state time-wait | wc -l # Too many = connection churn
ss -tan state close-wait | wc -l # Leaking connections
# 3. Check buffer usage
ss -tmi | grep -E 'rcv_space|snd_wnd'
# 4. Check route metrics
ip route | grep metric
Quick Command Reference
ss Quick Reference
ss -tulnp # Listening ports with process
ss -tan state established # Established connections
ss -tan 'dport = :443' # Connections to port 443
ss -tan 'dst 10.0.0.0/8' # Connections to 10.x.x.x
ss -s # Statistics summary
ss -tan state time-wait | wc -l # Count TIME_WAIT
ip Quick Reference
# Addresses
ip -br addr # Brief address list
ip addr add 192.168.1.100/24 dev eth0 # Add address
ip addr del 192.168.1.100/24 dev eth0 # Remove address
# Interfaces
ip -br link # Brief interface list
ip link set eth0 up/down # Enable/disable
ip -s link show eth0 # Statistics
# Routes
ip route # Show routes
ip route get 8.8.8.8 # Route to destination
ip route add 10.0.0.0/8 via 192.168.1.1 # Add route
ip route del 10.0.0.0/8 # Delete route
# Neighbors
ip neigh # Show ARP table
ip neigh flush dev eth0 # Clear ARP cache