Configuring Firewalls
Guide engineers through configuring firewalls across host-based (iptables, nftables, UFW), cloud-based (AWS Security Groups, NACLs), and container-based (Kubernetes NetworkPolicies) environments with practical rule examples and safety patterns.
When to Use
Use this skill when:
- Initial server setup and hardening
- Exposing a new service (web server, API, database)
- Implementing network segmentation
- Creating bastion host or jump box
- Migrating from iptables to nftables
- Configuring cloud security groups
- Troubleshooting connectivity issues
- Implementing defense-in-depth strategies
Key Features
Tool Selection Framework:
- Ubuntu/Debian + Simplicity: UFW (Uncomplicated Firewall)
- RHEL/CentOS/Fedora: firewalld (default on Red Hat ecosystem)
- Modern Distro + Advanced: nftables (O(log n) performance, unified syntax)
- Legacy Systems: iptables (migrate to nftables when feasible)
- AWS: Security Groups (stateful) + Network ACLs (stateless)
- Kubernetes: NetworkPolicies (requires CNI: Calico, Cilium, Weave)
Common Patterns:
- Web Server: Allow HTTP/HTTPS from anywhere, SSH from bastion only
- Database Server: Allow DB port from app tier only, no public access
- Bastion Host: Single hardened entry point for SSH access
- Egress Filtering: Control outbound traffic to prevent data exfiltration
Safety Checklist:
- Always allow SSH before enabling firewall (prevent lockout)
- Test rules before enabling (dry-run when possible)
- Enable logging for debugging
- Document rules in version control (Git)
- Verify externally with nmap
- Have console access (cloud) or physical access (on-prem)
Quick Start
# UFW (Ubuntu/Debian)
# 1. Set defaults
sudo ufw default deny incoming
sudo ufw default allow outgoing
# 2. CRITICAL: Allow SSH before enabling
sudo ufw allow ssh
sudo ufw limit ssh # Rate-limit to prevent brute force
# 3. Allow web traffic
sudo ufw allow http # Port 80
sudo ufw allow https # Port 443
# 4. Allow from specific IP (database access)
sudo ufw allow from 192.168.1.100 to any port 5432
# 5. Enable firewall
sudo ufw enable
# 6. Verify rules
sudo ufw status verbose
nftables (Modern Linux):
#!/usr/sbin/nft -f
# /etc/nftables.conf
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
# Accept loopback
iif "lo" accept
# Accept established connections (stateful)
ct state established,related accept
# Drop invalid packets
ct state invalid drop
# Allow SSH
tcp dport 22 accept
# Allow HTTP/HTTPS
tcp dport { 80, 443 } accept
# Log dropped packets
log prefix "nftables-drop: " drop
}
chain forward {
type filter hook forward priority 0; policy drop;
}
chain output {
type filter hook output priority 0; policy accept;
}
}
AWS Security Groups (Terraform):
# Web server security group
resource "aws_security_group" "web" {
name = "web-server-sg"
description = "Security group for web servers"
vpc_id = aws_vpc.main.id
# Allow HTTP/HTTPS from anywhere
ingress {
description = "HTTPS from anywhere"
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
# Allow SSH from bastion only
ingress {
description = "SSH from bastion"
from_port = 22
to_port = 22
protocol = "tcp"
security_groups = [aws_security_group.bastion.id]
}
# Allow all outbound
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "web-server-sg"
}
}
Kubernetes NetworkPolicy (Default Deny):
# Deny all ingress traffic by default
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
Universal Best Practices
- Default Deny: Start with deny-all, explicitly allow required traffic
- Principle of Least Privilege: Only open necessary ports/IPs
- No 0.0.0.0/0 on Sensitive Ports: Never allow SSH/RDP/database from anywhere
- Version Control: Store firewall rules in Git
- Logging: Enable and monitor firewall logs
- Regular Audits: Review rules quarterly, remove unused
- Don't Mix Tools: Avoid running iptables and nftables simultaneously
- Test Before Production: Use staging environment first
Troubleshooting
Locked out via SSH:
- Cloud: Use console/session manager to access
- On-prem: Physical console access or IPMI/iLO
- Prevention: Always allow SSH before enabling firewall
Connection timeouts:
- Check firewall status:
sudo ufw statusorsudo nft list ruleset - Verify service is listening:
ss -tuln | grep <port> - Test externally:
nmap -Pn <ip> -p <port> - Check logs:
/var/log/ufw.logorjournalctl -u nftables
AWS ephemeral port issues:
- NACLs need return traffic: Allow 1024-65535 inbound
- Security Groups are stateful (no ephemeral config needed)
Kubernetes pods can't communicate:
- Check NetworkPolicies:
kubectl get networkpolicies -n <namespace> - Verify CNI plugin supports NetworkPolicies (Calico, Cilium)
- Test without policies first
Related Skills
- Security Hardening - Comprehensive server hardening including SSH, fail2ban, SELinux
- Security Architecture - Strategic network security design
- Implementing TLS - Secure communications through firewalls
- SIEM Logging - Monitor and alert on firewall events