Network Fundamentals for Infrastructure Engineers

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

CIDRSubnet MaskHostsUse Case
/32255.255.255.2551Single host route
/30255.255.255.2522Point-to-point links
/28255.255.255.24014Small server subnet
/24255.255.255.0254Standard subnet
/22255.255.252.01022Large subnet
/16255.255.0.065,534VPC 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

TypePurposeExample
AIPv4 addressweb.example.com → 93.184.216.34
AAAAIPv6 addressweb.example.com → 2606:2800::...
CNAMEAliaswww.example.com → web.example.com
MXMail serverexample.com → mail.example.com (priority 10)
TXTArbitrary textSPF, DKIM, domain verification
NSName serversexample.com → ns1.provider.com
PTRReverse lookup34.216.184.93 → web.example.com
SRVService 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:

StateMeaningConcern Level
ESTABLISHEDActive connectionNormal
TIME_WAITConnection closing, waitingNormal, but many = problem
CLOSE_WAITWaiting for app to closeMany = application bug
SYN_SENTInitiating connectionMany = network issue
SYN_RECVReceived SYN, sent SYN-ACKMany = 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

FeatureLayer 4 (TCP/UDP)Layer 7 (HTTP)
SpeedFasterSlower
SSL TerminationNoYes
Content-based routingNoYes
WebSocket supportYesYes
Use caseGeneric TCP, databasesWeb 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

  1. Master subnetting. You’ll use it every day.
  2. DNS is always the problem. Until proven otherwise.
  3. Capture packets when stuck. tcpdump tells the truth.
  4. Understand TCP states. CLOSE_WAIT floods are application bugs.
  5. 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