Networking is central to Linux administration, and it is also one of the things developers most often treat as a black box until something breaks. This guide covers both halves: the protocol concepts every developer should carry in their head — the TCP/IP model, IP addressing, CIDR math, TCP vs. UDP, ports, and NAT — and the Linux commands and config files that configure, monitor, and troubleshoot real networks.
The Networking Model: Layers, Addresses, and Protocols
Before the commands, the mental model. Almost every network problem you will ever debug lives at one of four layers, and knowing which layer narrows the search enormously.
The TCP/IP Model
Application Layer (HTTP, HTTPS, SSH, DNS)
↓
Transport Layer (TCP, UDP)
↓
Network Layer (IP, ICMP)
↓
Link Layer (Ethernet, WiFi)
When you troubleshoot, you work this stack bottom-up: is the physical link up (Link), do you have an IP and a route (Network), is the port open and reachable (Transport), and does the service respond correctly (Application)?
IP Addresses
IPv4 is a 32-bit address written as four octets — 192.168.1.100. Part of the address identifies the network, the rest identifies the host:
192.168.1.100
└─┬─┘ └─┬─┘
Network Host
IPv6 is a 128-bit address written in hex groups — 2001:0db8:85a3:0000:0000:8a2e:0370:7334 — designed to outlast the exhausted IPv4 space. (For a deeper treatment, see the dedicated IPv6 posts on this blog.)
Private ranges are not routable on the public internet and are what your LAN and most homelabs use:
10.0.0.0/8 (10.x.x.x)
172.16.0.0/12 (172.16.x.x – 172.31.x.x)
192.168.0.0/16 (192.168.x.x)
A couple of special addresses worth memorizing: 127.0.0.1 is localhost (loopback), and 0.0.0.0 means “all interfaces” when a service binds to it.
CIDR Notation
CIDR (Classless Inter-Domain Routing) notation appends a prefix length that says how many leading bits are the network portion:
192.168.1.0/24
└── 24 bits network, 8 bits host
= 256 addresses (192.168.1.0 – 192.168.1.255)
10.0.0.0/8
└── 8 bits network, 24 bits host
= 16,777,216 addresses
The smaller the prefix number, the larger the network. This is the math behind every routing rule, firewall source range, and subnet you will configure below.
TCP vs. UDP
The transport layer offers two protocols with opposite trade-offs:
|
TCP |
UDP |
| Connection |
Connection-oriented (handshake) |
Connectionless |
| Delivery |
Reliable, retransmits lost packets |
Best-effort, no guarantee |
| Ordering |
Ordered |
Unordered |
| Overhead |
Higher (flow control, ACKs) |
Lower, faster |
| Typical use |
HTTP, SSH, databases |
DNS, video streaming, gaming, VoIP |
TCP trades latency for guarantees; UDP trades guarantees for speed. When you choose a protocol — or debug why a service “sometimes” loses data — this is the distinction that matters.
Ports
A port is a 16-bit number (0–65535) that identifies which service on a host a connection is for. The well-known ports you will see constantly:
| Port |
Service |
| 22 |
SSH |
| 53 |
DNS |
| 80 |
HTTP |
| 443 |
HTTPS |
| 3306 |
MySQL |
| 5432 |
PostgreSQL |
| 6379 |
Redis |
To see what is listening locally, or whether a remote port is reachable:
1
2
|
ss -tuln # local listening TCP/UDP ports (see the ss table below)
nc -zv hostname 443 # test whether a remote port accepts connections
|
NAT (Network Address Translation)
Private IP addresses cannot route on the internet, so your router rewrites the source address (and port) of outbound packets to its single public IP, and reverses the translation for the replies:
Private: 192.168.1.100:45678 → NAT → Public: 203.0.113.50:12345
This is why an entire household of devices shares one public IP, and why inbound connections need explicit port forwarding (covered later) to reach a machine behind NAT.
Network Configuration
Viewing Network Interfaces
1
2
3
4
5
6
7
8
9
10
11
12
|
# Modern (iproute2)
ip addr
ip a # Short form
# Legacy (deprecated but common)
ifconfig
# Link status
ip link
# Specific interface
ip addr show eth0
|
Output Explained
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP
link/ether 00:11:22:33:44:55 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.100/24 brd 192.168.1.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::211:22ff:fe33:4455/64 scope link
- UP: Interface is up
- LOWER_UP: Physical link is up
- mtu 1500: Maximum transmission unit
- inet: IPv4 address
- inet6: IPv6 address
Temporary Configuration
1
2
3
4
5
6
7
8
9
|
# Add IP address
sudo ip addr add 192.168.1.100/24 dev eth0
# Remove IP address
sudo ip addr del 192.168.1.100/24 dev eth0
# Bring interface up/down
sudo ip link set eth0 up
sudo ip link set eth0 down
|
Persistent Configuration
Netplan (Ubuntu 18.04+)
1
2
3
4
5
6
7
8
9
10
11
12
|
# /etc/netplan/01-network.yaml
network:
version: 2
ethernets:
eth0:
dhcp4: true
eth1:
addresses:
- 192.168.1.100/24
gateway4: 192.168.1.1
nameservers:
addresses: [8.8.8.8, 8.8.4.4]
|
NetworkManager
1
2
3
4
5
6
7
8
9
10
11
12
|
# List connections
nmcli connection show
# Add static IP
nmcli connection add type ethernet con-name "static-eth0" \
ifname eth0 ip4 192.168.1.100/24 gw4 192.168.1.1
# Modify DNS
nmcli connection modify "static-eth0" ipv4.dns "8.8.8.8 8.8.4.4"
# Bring up connection
nmcli connection up "static-eth0"
|
/etc/network/interfaces (Debian)
# /etc/network/interfaces
auto eth0
iface eth0 inet static
address 192.168.1.100
netmask 255.255.255.0
gateway 192.168.1.1
dns-nameservers 8.8.8.8 8.8.4.4
1
|
sudo systemctl restart networking
|
Routing
View Routes
1
2
3
4
5
6
7
8
|
# Routing table
ip route
# or
ip r
# Legacy
route -n
netstat -rn
|
Modify Routes
1
2
3
4
5
6
7
8
|
# Add route
sudo ip route add 10.0.0.0/8 via 192.168.1.1
# Delete route
sudo ip route del 10.0.0.0/8
# Default gateway
sudo ip route add default via 192.168.1.1
|
DNS
Configuration
1
2
3
4
5
|
# Modern (systemd-resolved)
resolvectl status
# Traditional
cat /etc/resolv.conf
|
# /etc/resolv.conf
nameserver 8.8.8.8
nameserver 8.8.4.4
search example.com
Testing DNS
1
2
3
4
5
6
7
8
9
10
11
12
13
|
# Lookup
dig google.com
dig +short google.com
# Specific DNS server
dig @8.8.8.8 google.com
# Reverse lookup
dig -x 8.8.8.8
# Alternative tools
nslookup google.com
host google.com
|
/etc/hosts
Static hostname resolution:
# /etc/hosts
127.0.0.1 localhost
192.168.1.50 server.local server
Network Troubleshooting
Connectivity Tests
1
2
3
4
5
6
7
8
9
10
11
12
|
# Basic connectivity
ping google.com
ping -c 4 192.168.1.1 # 4 packets only
# Path to destination
traceroute google.com
tracepath google.com
mtr google.com # Interactive
# Check port
nc -zv example.com 80
telnet example.com 80
|
Connection Status
1
2
3
4
5
6
7
8
|
# TCP/UDP connections
ss -tuln # Listening ports
ss -tunp # Processes
ss -s # Summary
# Legacy
netstat -tuln
netstat -tunp
|
ss Options
| Option |
Meaning |
-t |
TCP |
-u |
UDP |
-l |
Listening |
-n |
Numeric (no DNS) |
-p |
Show process |
-a |
All sockets |
Network Traffic
1
2
3
4
5
6
7
8
9
10
11
12
13
|
# Bandwidth monitoring
iftop
nethogs
# Packet capture
sudo tcpdump -i eth0
sudo tcpdump -i eth0 port 80
sudo tcpdump -i eth0 -w capture.pcap
# Traffic statistics
vnstat
vnstat -d # Daily
vnstat -l # Live
|
Common Failure Patterns
Three error messages account for the majority of connectivity problems, and each points at a different layer:
Connection refused — the packet reached the host, but nothing is listening on that port (or the service crashed). The host is up; the service is not.
1
2
3
|
curl: (7) Failed to connect: Connection refused
ss -tln | grep 8080 # is anything listening?
systemctl status myservice # is the service running?
|
Connection timed out — the packet never got a response at all. This is almost always a firewall silently dropping traffic, or no route to the host. A refusal is fast; a timeout hangs.
1
2
3
|
curl: (28) Connection timed out
sudo ufw status # local firewall blocking it?
ip route get 203.0.113.50 # is there a route to the destination?
|
DNS resolution failed — the name could not be turned into an address, so nothing was even attempted. Test resolution directly and bypass your configured resolver to isolate it:
1
2
3
|
dig example.com
cat /etc/resolv.conf
dig @8.8.8.8 example.com # works with a public resolver? then it's your DNS config
|
The pattern generalizes: a fast failure means something actively rejected you (service down, connection refused); a slow failure means something swallowed the packet (firewall, routing, DNS). That single distinction will tell you which layer to investigate first.
Firewalls
UFW (Ubuntu)
Simple firewall management:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
# Enable/disable
sudo ufw enable
sudo ufw disable
sudo ufw status
# Default policies
sudo ufw default deny incoming
sudo ufw default allow outgoing
# Allow rules
sudo ufw allow 22
sudo ufw allow ssh
sudo ufw allow 80/tcp
sudo ufw allow from 192.168.1.0/24
# Deny rules
sudo ufw deny 23
# Delete rules
sudo ufw delete allow 80
# Application profiles
sudo ufw app list
sudo ufw allow 'Nginx Full'
|
firewalld (RHEL/CentOS)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
# Status
sudo firewall-cmd --state
sudo firewall-cmd --list-all
# Add service
sudo firewall-cmd --add-service=http --permanent
sudo firewall-cmd --add-port=8080/tcp --permanent
# Reload
sudo firewall-cmd --reload
# Zones
sudo firewall-cmd --get-zones
sudo firewall-cmd --zone=public --list-all
|
iptables (Low-Level)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
# View rules
sudo iptables -L -n -v
sudo iptables -L -t nat
# Basic rules
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -A INPUT -j DROP
# Save rules
sudo iptables-save > /etc/iptables/rules.v4
# Restore rules
sudo iptables-restore < /etc/iptables/rules.v4
|
nftables (Modern Replacement)
1
2
3
4
5
|
# View rules
sudo nft list ruleset
# Add rule
sudo nft add rule inet filter input tcp dport 22 accept
|
Port Forwarding
SSH Tunnel
1
2
3
4
5
6
7
8
9
10
|
# Local port forward
ssh -L 8080:localhost:80 user@server
# Access server's port 80 via localhost:8080
# Remote port forward
ssh -R 8080:localhost:3000 user@server
# Server's 8080 forwards to your 3000
# Dynamic (SOCKS proxy)
ssh -D 1080 user@server
|
iptables NAT
1
2
3
4
5
6
7
|
# Enable forwarding
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
# Forward port
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 \
-j DNAT --to-destination 192.168.1.100:8080
sudo iptables -t nat -A POSTROUTING -j MASQUERADE
|
Network Bonding/Teaming
Combine multiple interfaces:
1
2
3
4
5
6
7
8
9
10
11
|
# Netplan example
network:
version: 2
bonds:
bond0:
interfaces: [eth0, eth1]
parameters:
mode: 802.3ad
lacp-rate: fast
addresses:
- 192.168.1.100/24
|
Quick Diagnostics Script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
#!/bin/bash
echo "=== Network Interfaces ==="
ip addr
echo -e "\n=== Routing Table ==="
ip route
echo -e "\n=== DNS Configuration ==="
cat /etc/resolv.conf
echo -e "\n=== Listening Ports ==="
ss -tuln
echo -e "\n=== Internet Connectivity ==="
ping -c 2 8.8.8.8
echo -e "\n=== DNS Resolution ==="
dig +short google.com
|
Quick Reference
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
# Interface management
ip addr # View addresses
ip link set eth0 up/down # Enable/disable
ip route # View routes
# DNS
dig domain.com # DNS lookup
cat /etc/resolv.conf # DNS config
# Connectivity
ping host # Test connectivity
traceroute host # Trace path
ss -tuln # Listening ports
# Firewall (UFW)
sudo ufw enable # Enable firewall
sudo ufw allow 22 # Allow SSH
sudo ufw status # View rules
|
Network troubleshooting is systematic: check physical link, IP config, routing, DNS, then firewall. Work through layer by layer.
Comments