Networking and Firewall
Network Stack Overview
Linux networking flows: application → socket → kernel TCP/IP stack → network interface → physical/virtual link. Configuration can be transient (ip commands) or persistent (Netplan, NetworkManager, ifcfg files).
ip link show
ip -br addr show # brief address summary
cat /sys/class/net/eth0/operstate # link up/down
Interface Configuration
Modern tools replace deprecated ifconfig and route:
# Temporary configuration (lost on reboot)
ip addr add 192.168.1.50/24 dev eth0
ip link set eth0 up
ip addr del 192.168.1.50/24 dev eth0
ip route show
ip route add default via 192.168.1.1
ip route add 10.0.0.0/8 via 10.0.0.1 dev eth1
Persistent Configuration
| Distro/tool | Config location |
|---|---|
| Ubuntu (server) | /etc/netplan/*.yaml |
| Debian | /etc/network/interfaces |
| RHEL/Fedora | /etc/NetworkManager/system-connections/ |
| Any (NM CLI) | nmcli connection modify |
# Ubuntu Netplan apply
sudo netplan apply
sudo netplan try # rollback if disconnected
# NetworkManager
nmcli device status
nmcli connection show
sudo nmcli connection up "Wired connection 1"
Sockets and Connections
ss -tulpn # listening TCP/UDP with process
ss -tn state established # active connections
ss -s # socket summary statistics
# Legacy (may not be installed)
netstat -rn
netstat -tulpn
# Test local port
nc -zv localhost 443
curl -v telnet://localhost:25
Connectivity Testing
ping -c 3 192.168.1.1
ping -6 -c 3 2001:4860:4860::8888 # IPv6
traceroute 8.8.8.8
tracepath example.com
mtr -r -c 10 example.com # combined ping/traceroute
# HTTP layer
curl -I --connect-timeout 5 https://example.com
curl -v http://localhost:8080/health
DNS Resolution
cat /etc/resolv.conf
resolvectl status # systemd-resolved
systemd-resolve --status # older name
dig example.com +short
dig @1.1.1.1 example.com # query specific resolver
dig example.com MX
nslookup example.com
getent hosts example.com # uses NSS (/etc/nsswitch.conf)
/etc/hosts overrides DNS for local entries:
sudo tee -a /etc/hosts <<EOF
192.168.1.100 db.internal db
EOF
Hostname
hostnamectl
sudo hostnamectl set-hostname web01.prod.example.com
sudo hostnamectl set-hostname --static web01
Cloud instances often set hostname via cloud-init — align DNS A/AAAA records with hostname -f.
Firewall — ufw (Debian/Ubuntu)
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp comment 'HTTP'
sudo ufw allow 443/tcp
sudo ufw allow from 10.0.0.0/8 to any port 5432 proto tcp
sudo ufw enable
sudo ufw status verbose numbered
sudo ufw delete 3 # delete rule by number
Firewall — firewalld (Fedora/RHEL)
sudo systemctl enable --now firewalld
sudo firewall-cmd --list-all
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --reload
# Zone assignment
sudo firewall-cmd --zone=public --change-interface=eth0
nftables / iptables (Advanced)
When ufw/firewalld is insufficient (NAT, forwarding, custom chains):
sudo nft list ruleset
sudo iptables -L -n -v # legacy iptables
# Enable IP forwarding (router/NAT)
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
# Persist: net.ipv4.ip_forward=1 in /etc/sysctl.d/
Prefer high-level tools until you need custom NAT, Docker bridge rules, or complex forwarding.
Troubleshooting Checklist
| Symptom | Checks |
|---|---|
| No connectivity | ip addr, link state, default route, cable/VPC |
| Intermittent drops | dmesg, NIC errors ethtool -S eth0 |
| DNS fails | dig, resolvectl, firewall on port 53 UDP/TCP |
| Port closed externally | ss -tlnp, cloud security groups, ufw/firewalld |
| Slow transfers | MTU (ping -M do -s 1472), congestion, iperf3 |
| Connection refused | Service down or wrong bind address |
| Timeout | Firewall DROP rules or routing black hole |
# MTU discovery
ping -M do -s 1472 8.8.8.8 # reduce size if fragmentation needed
ip link set eth0 mtu 1400 # common fix for VPN/cloud overlay
Best Practices
| Practice | Reason |
|---|---|
| Document open ports in runbooks | OS + cloud SG must both allow traffic |
| Default deny incoming | Expose only required services |
| Use static IPs or reserved DHCP | Stable firewall rules and DNS |
| Test from outside the host | ss shows listen; doesn’t prove external reachability |
Common Mistakes
| Mistake | Consequence |
|---|---|
| Configuring only OS firewall | Cloud SG still blocks traffic |
| Binding service to 127.0.0.1 | Not reachable remotely (sometimes intentional) |
| Wrong interface name after reboot | eth0 → ens3 breaks Netplan/ifcfg |
| Flushing iptables with Docker running | Breaks container networking |
Production Scenario
A three-tier app on AWS: web tier in public subnet, app/db in private subnets.
- Security groups: Web allows 443 from 0.0.0.0/0; app allows 8080 from web SG only
- OS ufw: Web denies all except 443 and SSH from bastion IP
- DNS: Private Route53 zone
internal.example.comfor app/db endpoints - Health checks: ALB hits
/healthon port 443;curlfrom bastion validates app tier
Incident: app tier unreachable. ss -tlnp shows app listening on 0.0.0.0:8080 — SG misconfigured to allow web subnet CIDR instead of web SG reference. Fix SG; no app restart needed.
Document open ports and security group rules alongside OS firewall policy — both layers must allow traffic for services to work.