Introduction
Networking is the foundation of infrastructure. Every server, container, and service depends on packets getting from point A to point B. Yet many engineers treat networking as magic—it either works or it doesn’t.
This guide covers essential networking concepts with practical examples. Not theory for exam prep, but knowledge you’ll use daily.
IP Addressing and Subnetting
CIDR Notation Quick Reference
| CIDR | Subnet Mask | Hosts | Use Case |
|---|---|---|---|
| /32 | 255.255.255.255 | 1 | Single host route |
| /30 | 255.255.255.252 | 2 | Point-to-point links |
| /28 | 255.255.255.240 | 14 | Small server subnet |
| /24 | 255.255.255.0 | 254 | Standard subnet |
| /22 | 255.255.252.0 | 1022 | Large subnet |
| /16 | 255.255.0.0 | 65,534 | VPC level |
Subnet Planning
Company Network: 10.0.0.0/16
├── Production (10.1.0.0/16)
│ ├── Web Tier: 10.1.1.0/24 (254 hosts)
│ ├── App Tier: 10.1.2.0/24 (254 hosts)
│ ├── DB Tier: 10.1.3.0/24 (254 hosts)
│ └── Management: 10.1.255.0/24 (254 hosts)
│
├── Staging (10.2.0.0/16)
│ ├── Web: 10.2.1.0/24
│ ├── App: 10.2.2.0/24
│ └── DB: 10.2.3.0/24
│
└── Development (10.3.0.0/16)
└── All services: 10.3.0.0/22 (1022 hosts)
Calculating Subnets
#!/usr/bin/env python3
# subnet_calculator.py
import ipaddress
def analyze_subnet(cidr: str):
"""Analyze a subnet and print details."""
network = ipaddress.ip_network(cidr, strict=False)
print(f"Network: {network.network_address}")
print(f"Netmask: {network.netmask}")
print(f"Broadcast: {network.broadcast_address}")
print(f"Host range: {network[1]} - {network[-2]}")
print(f"Total hosts: {network.num_addresses - 2}")
print(f"Prefix length: /{network.prefixlen}")
def subnet_contains(network_cidr: str, ip: str) -> bool:
"""Check if IP is within subnet."""
network = ipaddress.ip_network(network_cidr, strict=False)
return ipaddress.ip_address(ip) in network
def split_subnet(cidr: str, new_prefix: int):
"""Split subnet into smaller subnets."""
network = ipaddress.ip_network(cidr, strict=False)
return list(network.subnets(new_prefix=new_prefix))
# Usage
if __name__ == "__main__":
analyze_subnet("10.1.0.0/24")
print("\nSplit /23 into /25s:")
for subnet in split_subnet("10.1.0.0/23", 25):
print(f" {subnet}")
DNS Deep Dive
Record Types
| Type | Purpose | Example |
|---|---|---|
| A | IPv4 address | web.example.com → 93.184.216.34 |
| AAAA | IPv6 address | web.example.com → 2606:2800::... |
| CNAME | Alias | www.example.com → web.example.com |
| MX | Mail server | example.com → mail.example.com (priority 10) |
| TXT | Arbitrary text | SPF, DKIM, domain verification |
| NS | Name servers | example.com → ns1.provider.com |
| PTR | Reverse lookup | 34.216.184.93 → web.example.com |
| SRV | Service location | _ldap._tcp.example.com → ldap.example.com:389 |
DNS Troubleshooting
# Basic resolution
dig example.com
# Specific record type
dig example.com MX
dig example.com TXT
# Query specific DNS server
dig @8.8.8.8 example.com
# Trace the resolution path
dig +trace example.com
# Reverse lookup
dig -x 93.184.216.34
# Short output
dig +short example.com
# Full query path with timing
dig +stats +noall +answer example.com
Internal DNS Setup
# /etc/bind/named.conf.local
zone "internal.yourorg.com" {
type master;
file "/etc/bind/zones/db.internal.yourorg.com";
allow-transfer { 10.0.0.11; }; # Secondary DNS
};
zone "1.0.10.in-addr.arpa" {
type master;
file "/etc/bind/zones/db.10.0.1";
};
# /etc/bind/zones/db.internal.yourorg.com
$TTL 604800
@ IN SOA ns1.internal.yourorg.com. admin.yourorg.com. (
3 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
@ IN NS ns1.internal.yourorg.com.
@ IN NS ns2.internal.yourorg.com.
ns1 IN A 10.0.1.10
ns2 IN A 10.0.1.11
; Web servers
web-01 IN A 10.1.1.10
web-02 IN A 10.1.1.11
web-03 IN A 10.1.1.12
; Load balancer VIP
web IN A 10.1.1.100
; Database servers
db-01 IN A 10.1.3.10
db-02 IN A 10.1.3.11
db IN CNAME db-01
; Service discovery
_ldap._tcp IN SRV 10 0 389 ldap.internal.yourorg.com.
TCP/IP Fundamentals
The TCP Handshake
Client Server
| |
| SYN (seq=100) |
| ---------------------------------> |
| |
| SYN-ACK (seq=300, ack=101) |
| <--------------------------------- |
| |
| ACK (seq=101, ack=301) |
| ---------------------------------> |
| |
| Connection Established |
Understanding TCP States
# View all connections with states
ss -tan
# Count connections by state
ss -tan | awk '{print $1}' | sort | uniq -c | sort -rn
# Find connections to specific port
ss -tan 'dport = :443'
# Connections per source IP
ss -tan | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head
Common states and what they mean:
| State | Meaning | Concern Level |
|---|---|---|
| ESTABLISHED | Active connection | Normal |
| TIME_WAIT | Connection closing, waiting | Normal, but many = problem |
| CLOSE_WAIT | Waiting for app to close | Many = application bug |
| SYN_SENT | Initiating connection | Many = network issue |
| SYN_RECV | Received SYN, sent SYN-ACK | Many = possible SYN flood |
TCP Tuning
# /etc/sysctl.conf
# Increase buffer sizes
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 87380 16777216
# Connection backlog
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
# TIME_WAIT handling
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 30
# Keepalive settings
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 60
net.ipv4.tcp_keepalive_probes = 3
# Apply changes
sysctl -p
Routing
Understanding Route Tables
# View routing table
ip route
# Typical output:
# default via 10.0.0.1 dev eth0 proto static metric 100
# 10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.50
# 10.1.0.0/16 via 10.0.0.254 dev eth0
# 169.254.0.0/16 dev eth0 scope link metric 1000
# Add static route
ip route add 192.168.100.0/24 via 10.0.0.254
# Add route through specific interface
ip route add 172.16.0.0/12 dev tun0
# Delete route
ip route del 192.168.100.0/24
# Trace route path
traceroute -n example.com
mtr --report example.com
Persistent Routes
# /etc/netplan/99-custom-routes.yaml (Ubuntu)
network:
version: 2
ethernets:
eth0:
routes:
- to: 192.168.100.0/24
via: 10.0.0.254
- to: 172.16.0.0/12
via: 10.0.0.253
metric: 100
Policy-Based Routing
# Route traffic from specific source through different gateway
ip rule add from 10.0.1.0/24 table custom
ip route add default via 10.0.0.252 table custom
# Route based on destination port (with iptables mark)
iptables -t mangle -A PREROUTING -p tcp --dport 443 -j MARK --set-mark 1
ip rule add fwmark 1 table ssl_traffic
ip route add default via 10.0.0.251 table ssl_traffic
Firewalls and iptables
iptables Fundamentals
# View current rules
iptables -L -n -v
# Basic server policy
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# Allow established connections
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# Allow loopback
iptables -A INPUT -i lo -j ACCEPT
# Allow SSH from management network
iptables -A INPUT -p tcp -s 10.0.255.0/24 --dport 22 -j ACCEPT
# Allow HTTP/HTTPS
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# Allow ICMP (ping)
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
# Log dropped packets
iptables -A INPUT -j LOG --log-prefix "iptables-dropped: "
# Save rules
iptables-save > /etc/iptables/rules.v4
nftables (Modern Alternative)
# /etc/nftables.conf
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
# Connection tracking
ct state established,related accept
ct state invalid drop
# Loopback
iif lo accept
# ICMP
ip protocol icmp accept
ip6 nexthdr icmpv6 accept
# SSH from management
ip saddr 10.0.255.0/24 tcp dport 22 accept
# Web services
tcp dport { 80, 443 } accept
# Logging
log prefix "nftables-dropped: " counter drop
}
chain forward {
type filter hook forward priority 0; policy drop;
}
chain output {
type filter hook output priority 0; policy accept;
}
}
Load Balancing
Layer 4 vs Layer 7
| Feature | Layer 4 (TCP/UDP) | Layer 7 (HTTP) |
|---|---|---|
| Speed | Faster | Slower |
| SSL Termination | No | Yes |
| Content-based routing | No | Yes |
| WebSocket support | Yes | Yes |
| Use case | Generic TCP, databases | Web applications |
HAProxy Configuration
# /etc/haproxy/haproxy.cfg
global
log /dev/log local0
maxconn 50000
user haproxy
group haproxy
daemon
stats socket /run/haproxy/admin.sock mode 660 level admin
defaults
log global
mode http
option httplog
option dontlognull
option forwardfor
option http-server-close
timeout connect 5s
timeout client 30s
timeout server 30s
errorfile 503 /etc/haproxy/errors/503.http
frontend http_front
bind *:80
bind *:443 ssl crt /etc/haproxy/certs/combined.pem
# Redirect HTTP to HTTPS
http-request redirect scheme https unless { ssl_fc }
# Route based on path
acl is_api path_beg /api
acl is_static path_beg /static
use_backend api_servers if is_api
use_backend static_servers if is_static
default_backend web_servers
backend web_servers
balance roundrobin
option httpchk GET /health
http-check expect status 200
server web1 10.1.1.10:8080 check inter 5s fall 3 rise 2
server web2 10.1.1.11:8080 check inter 5s fall 3 rise 2
server web3 10.1.1.12:8080 check inter 5s fall 3 rise 2 backup
backend api_servers
balance leastconn
option httpchk GET /api/health
server api1 10.1.2.10:8080 check weight 100
server api2 10.1.2.11:8080 check weight 100
backend static_servers
balance uri
server static1 10.1.4.10:80 check
server static2 10.1.4.11:80 check
listen stats
bind *:8404
stats enable
stats uri /stats
stats refresh 10s
stats admin if LOCALHOST
Troubleshooting Toolkit
Essential Commands
# Network interfaces
ip addr show
ip link show
# Connectivity test
ping -c 4 example.com
ping6 -c 4 ipv6.example.com
# Port connectivity
nc -zv example.com 443
telnet example.com 443
# DNS resolution
dig example.com
nslookup example.com
host example.com
# Route tracing
traceroute -n example.com
mtr --report --no-dns example.com
# TCP connections
ss -tuln # Listening ports
ss -tuan # All connections
netstat -tlnp # Listening with process
# Network statistics
ip -s link # Interface stats
nstat # Network statistics
# Packet capture
tcpdump -i eth0 port 443
tcpdump -i any host 10.0.0.50
tcpdump -w capture.pcap -i eth0
Debugging Scenarios
Connection Refused:
# Check if service is listening
ss -tuln | grep :8080
# Check firewall
iptables -L -n | grep 8080
nft list ruleset | grep 8080
# Check service status
systemctl status myservice
journalctl -u myservice -f
Connection Timeout:
# Check routing
ip route get 10.1.1.10
# Check intermediate firewalls
traceroute -T -p 8080 10.1.1.10
# Check for packet drops
watch -n1 'nstat -z | grep -i drop'
Slow Network:
# Measure bandwidth
iperf3 -c server -t 30
# Check for packet loss
mtr --report example.com
# Check interface errors
ip -s link show eth0
# Check for retransmissions
ss -ti dst :443
Lessons Learned
- Master subnetting. You’ll use it every day.
- DNS is always the problem. Until proven otherwise.
- Capture packets when stuck. tcpdump tells the truth.
- Understand TCP states. CLOSE_WAIT floods are application bugs.
- Document your network. A diagram saves hours of troubleshooting.
Conclusion
Networking doesn’t have to be mysterious. Understand the fundamentals, know your troubleshooting tools, and most problems become solvable.
The best network engineers I know share one trait: they can quickly narrow down whether a problem is DNS, routing, firewall, or application. Build that mental model, practice with the tools, and networking becomes one less unknown.
Resources
- TCP/IP Illustrated - The classic reference
- Linux Network Administration - Red Hat guides
- Practical Packet Analysis - Wireshark deep dive