mirror of
https://github.com/BagelHole/DevOps-Security-Agent-Skills.git
synced 2026-08-22 12:49:53 +02:00
454 lines
11 KiB
Markdown
454 lines
11 KiB
Markdown
---
|
|
name: firewall-config
|
|
description: Configure iptables, nftables, and cloud firewalls. Implement network segmentation and traffic filtering. Use when securing network perimeters or implementing security zones.
|
|
license: MIT
|
|
metadata:
|
|
author: devops-skills
|
|
version: "1.0"
|
|
---
|
|
|
|
# Firewall Configuration
|
|
|
|
Configure host-based and cloud firewalls for network security.
|
|
|
|
## When to Use This Skill
|
|
|
|
Use this skill when:
|
|
- Setting up a new server and need to restrict network access
|
|
- Implementing network segmentation between application tiers
|
|
- Configuring cloud security groups for AWS, GCP, or Azure resources
|
|
- Migrating from iptables to nftables
|
|
- Auditing existing firewall rules for compliance
|
|
- Responding to a security incident requiring emergency network blocks
|
|
|
|
## Prerequisites
|
|
|
|
- Root or sudo access on Linux hosts
|
|
- AWS CLI configured for cloud security groups
|
|
- Understanding of TCP/IP, ports, and protocols
|
|
- Network diagram showing required traffic flows
|
|
|
|
## iptables
|
|
|
|
### Basic Setup with Default Deny
|
|
|
|
```bash
|
|
# Flush existing rules
|
|
iptables -F
|
|
iptables -X
|
|
iptables -t nat -F
|
|
iptables -t mangle -F
|
|
|
|
# Default policies - deny all inbound, allow outbound
|
|
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
|
|
|
|
# Drop invalid packets
|
|
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
|
|
|
|
# Allow SSH (restrict to management subnet)
|
|
iptables -A INPUT -p tcp --dport 22 -s 10.0.100.0/24 -j ACCEPT
|
|
|
|
# Allow HTTP/HTTPS from anywhere
|
|
iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
|
|
|
|
# Allow ICMP (ping) with rate limiting
|
|
iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/s --limit-burst 4 -j ACCEPT
|
|
|
|
# Log dropped packets (rate limited to avoid log flooding)
|
|
iptables -A INPUT -m limit --limit 5/min -j LOG --log-prefix "IPTABLES-DROP: " --log-level 4
|
|
|
|
# Save rules (Debian/Ubuntu)
|
|
iptables-save > /etc/iptables/rules.v4
|
|
ip6tables-save > /etc/iptables/rules.v6
|
|
```
|
|
|
|
### Anti-DDoS Rules
|
|
|
|
```bash
|
|
# SYN flood protection
|
|
iptables -A INPUT -p tcp --syn -m limit --limit 25/s --limit-burst 50 -j ACCEPT
|
|
iptables -A INPUT -p tcp --syn -j DROP
|
|
|
|
# Limit new connections per source IP
|
|
iptables -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 50 -j REJECT
|
|
|
|
# Block port scanning (detect TCP flags abuse)
|
|
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
|
|
iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP
|
|
iptables -A INPUT -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP
|
|
iptables -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
|
|
iptables -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
|
|
```
|
|
|
|
### Application-Specific Rules
|
|
|
|
```bash
|
|
# Web server with database backend
|
|
# Allow app servers to reach database (port 5432)
|
|
iptables -A INPUT -p tcp --dport 5432 -s 10.0.1.0/24 -j ACCEPT
|
|
|
|
# Allow monitoring (Prometheus node exporter)
|
|
iptables -A INPUT -p tcp --dport 9100 -s 10.0.200.0/24 -j ACCEPT
|
|
|
|
# DNS resolution
|
|
iptables -A INPUT -p udp --sport 53 -j ACCEPT
|
|
iptables -A INPUT -p tcp --sport 53 -j ACCEPT
|
|
|
|
# NTP
|
|
iptables -A INPUT -p udp --sport 123 -j ACCEPT
|
|
|
|
# Block specific IP (incident response)
|
|
iptables -I INPUT 1 -s 203.0.113.50 -j DROP
|
|
```
|
|
|
|
## UFW (Uncomplicated Firewall)
|
|
|
|
```bash
|
|
# Enable UFW with default deny
|
|
ufw default deny incoming
|
|
ufw default allow outgoing
|
|
ufw enable
|
|
|
|
# Allow SSH from management network
|
|
ufw allow from 10.0.100.0/24 to any port 22 proto tcp
|
|
|
|
# Allow HTTP/HTTPS
|
|
ufw allow 80/tcp
|
|
ufw allow 443/tcp
|
|
|
|
# Allow specific application profile
|
|
ufw allow 'Nginx Full'
|
|
|
|
# Rate limit SSH (max 6 connections in 30 seconds)
|
|
ufw limit ssh
|
|
|
|
# Allow port range
|
|
ufw allow 8000:8080/tcp
|
|
|
|
# Deny specific IP
|
|
ufw deny from 203.0.113.50
|
|
|
|
# Check status
|
|
ufw status verbose
|
|
ufw status numbered
|
|
|
|
# Delete a rule by number
|
|
ufw delete 3
|
|
|
|
# Application profiles
|
|
ufw app list
|
|
ufw app info 'Nginx Full'
|
|
```
|
|
|
|
## nftables
|
|
|
|
### Complete Server Configuration
|
|
|
|
```bash
|
|
#!/usr/sbin/nft -f
|
|
flush ruleset
|
|
|
|
# Define variables
|
|
define LAN = 10.0.0.0/16
|
|
define MGMT = 10.0.100.0/24
|
|
define MONITOR = 10.0.200.0/24
|
|
|
|
table inet filter {
|
|
# Rate limiting set
|
|
set rate_limit {
|
|
type ipv4_addr
|
|
flags dynamic,timeout
|
|
timeout 1m
|
|
}
|
|
|
|
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 and ICMPv6
|
|
ip protocol icmp icmp type { echo-request, destination-unreachable, time-exceeded } limit rate 10/second accept
|
|
ip6 nexthdr icmpv6 icmpv6 type { echo-request, nd-neighbor-solicit, nd-router-advert } accept
|
|
|
|
# SSH from management only
|
|
tcp dport 22 ip saddr $MGMT accept
|
|
|
|
# HTTP/HTTPS from anywhere
|
|
tcp dport { 80, 443 } accept
|
|
|
|
# Prometheus metrics from monitoring subnet
|
|
tcp dport 9100 ip saddr $MONITOR accept
|
|
|
|
# Rate limit new connections
|
|
tcp flags syn limit rate over 25/second burst 50 packets drop
|
|
|
|
# Log dropped traffic
|
|
log prefix "nft-drop: " level warn limit rate 5/minute
|
|
}
|
|
|
|
chain forward {
|
|
type filter hook forward priority 0; policy drop;
|
|
}
|
|
|
|
chain output {
|
|
type filter hook output priority 0; policy accept;
|
|
|
|
# Optional: restrict outbound to known destinations
|
|
# tcp dport { 80, 443, 53 } accept
|
|
# udp dport { 53, 123 } accept
|
|
# ct state established,related accept
|
|
# drop
|
|
}
|
|
}
|
|
|
|
# NAT table for port forwarding
|
|
table ip nat {
|
|
chain prerouting {
|
|
type nat hook prerouting priority -100;
|
|
# Forward port 8080 to internal app server
|
|
tcp dport 8080 dnat to 10.0.1.10:8080
|
|
}
|
|
|
|
chain postrouting {
|
|
type nat hook postrouting priority 100;
|
|
oifname "eth0" masquerade
|
|
}
|
|
}
|
|
```
|
|
|
|
### nftables Management Commands
|
|
|
|
```bash
|
|
# Load configuration
|
|
nft -f /etc/nftables.conf
|
|
|
|
# List all rules
|
|
nft list ruleset
|
|
|
|
# List specific table
|
|
nft list table inet filter
|
|
|
|
# Add a rule dynamically
|
|
nft add rule inet filter input tcp dport 8443 accept
|
|
|
|
# Insert rule at position
|
|
nft insert rule inet filter input position 5 ip saddr 10.0.50.0/24 tcp dport 3306 accept
|
|
|
|
# Delete a rule by handle
|
|
nft -a list chain inet filter input # show handles
|
|
nft delete rule inet filter input handle 15
|
|
|
|
# Monitor in real time
|
|
nft monitor
|
|
```
|
|
|
|
## AWS Security Groups
|
|
|
|
### Terraform Configuration
|
|
|
|
```hcl
|
|
# Web tier security group
|
|
resource "aws_security_group" "web" {
|
|
name_prefix = "web-sg-"
|
|
vpc_id = aws_vpc.main.id
|
|
description = "Security group for web servers"
|
|
|
|
ingress {
|
|
description = "HTTPS from internet"
|
|
from_port = 443
|
|
to_port = 443
|
|
protocol = "tcp"
|
|
cidr_blocks = ["0.0.0.0/0"]
|
|
}
|
|
|
|
ingress {
|
|
description = "HTTP redirect"
|
|
from_port = 80
|
|
to_port = 80
|
|
protocol = "tcp"
|
|
cidr_blocks = ["0.0.0.0/0"]
|
|
}
|
|
|
|
egress {
|
|
description = "All outbound"
|
|
from_port = 0
|
|
to_port = 0
|
|
protocol = "-1"
|
|
cidr_blocks = ["0.0.0.0/0"]
|
|
}
|
|
|
|
tags = {
|
|
Name = "web-sg"
|
|
Environment = "production"
|
|
ManagedBy = "terraform"
|
|
}
|
|
}
|
|
|
|
# App tier - only accepts traffic from web tier
|
|
resource "aws_security_group" "app" {
|
|
name_prefix = "app-sg-"
|
|
vpc_id = aws_vpc.main.id
|
|
description = "Security group for application servers"
|
|
|
|
ingress {
|
|
description = "HTTP from web tier"
|
|
from_port = 8080
|
|
to_port = 8080
|
|
protocol = "tcp"
|
|
security_groups = [aws_security_group.web.id]
|
|
}
|
|
|
|
egress {
|
|
from_port = 0
|
|
to_port = 0
|
|
protocol = "-1"
|
|
cidr_blocks = ["0.0.0.0/0"]
|
|
}
|
|
}
|
|
|
|
# Database tier - only accepts from app tier
|
|
resource "aws_security_group" "db" {
|
|
name_prefix = "db-sg-"
|
|
vpc_id = aws_vpc.main.id
|
|
description = "Security group for database servers"
|
|
|
|
ingress {
|
|
description = "PostgreSQL from app tier"
|
|
from_port = 5432
|
|
to_port = 5432
|
|
protocol = "tcp"
|
|
security_groups = [aws_security_group.app.id]
|
|
}
|
|
|
|
egress {
|
|
from_port = 0
|
|
to_port = 0
|
|
protocol = "-1"
|
|
cidr_blocks = ["0.0.0.0/0"]
|
|
}
|
|
}
|
|
```
|
|
|
|
### AWS CLI Commands
|
|
|
|
```bash
|
|
# Create security group
|
|
aws ec2 create-security-group \
|
|
--group-name web-sg \
|
|
--description "Web server SG" \
|
|
--vpc-id vpc-0abc123
|
|
|
|
# Add inbound rule
|
|
aws ec2 authorize-security-group-ingress \
|
|
--group-id sg-0abc123 \
|
|
--protocol tcp --port 443 \
|
|
--cidr 0.0.0.0/0
|
|
|
|
# Add rule referencing another security group
|
|
aws ec2 authorize-security-group-ingress \
|
|
--group-id sg-0db456 \
|
|
--protocol tcp --port 5432 \
|
|
--source-group sg-0app789
|
|
|
|
# Remove a rule
|
|
aws ec2 revoke-security-group-ingress \
|
|
--group-id sg-0abc123 \
|
|
--protocol tcp --port 22 \
|
|
--cidr 0.0.0.0/0
|
|
|
|
# Describe rules
|
|
aws ec2 describe-security-group-rules \
|
|
--filters Name=group-id,Values=sg-0abc123
|
|
```
|
|
|
|
## Firewall Rule Audit Script
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# firewall-audit.sh - Audit current firewall rules for common issues
|
|
|
|
echo "=== Firewall Audit Report ==="
|
|
echo "Date: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
echo "Host: $(hostname)"
|
|
echo ""
|
|
|
|
# Check if firewall is active
|
|
if command -v nft &>/dev/null; then
|
|
echo "--- nftables rules ---"
|
|
nft list ruleset
|
|
elif command -v iptables &>/dev/null; then
|
|
echo "--- iptables rules ---"
|
|
iptables -L -n -v --line-numbers
|
|
fi
|
|
|
|
echo ""
|
|
echo "--- Open ports ---"
|
|
ss -tlnp
|
|
|
|
echo ""
|
|
echo "--- Potential issues ---"
|
|
|
|
# Check for overly permissive rules
|
|
if iptables -L INPUT -n 2>/dev/null | grep -q "0.0.0.0/0.*dpt:22"; then
|
|
echo "WARNING: SSH (port 22) open to 0.0.0.0/0 - restrict to management subnet"
|
|
fi
|
|
|
|
if iptables -L INPUT -n 2>/dev/null | grep -q "0.0.0.0/0.*dpt:3306"; then
|
|
echo "CRITICAL: MySQL (port 3306) open to 0.0.0.0/0"
|
|
fi
|
|
|
|
if iptables -L INPUT -n 2>/dev/null | grep -q "0.0.0.0/0.*dpt:5432"; then
|
|
echo "CRITICAL: PostgreSQL (port 5432) open to 0.0.0.0/0"
|
|
fi
|
|
|
|
# Check default policies
|
|
DEFAULT_INPUT=$(iptables -L INPUT 2>/dev/null | head -1 | grep -oP 'policy \K\w+')
|
|
if [ "$DEFAULT_INPUT" = "ACCEPT" ]; then
|
|
echo "CRITICAL: Default INPUT policy is ACCEPT - should be DROP"
|
|
fi
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
| Problem | Cause | Solution |
|
|
|---------|-------|----------|
|
|
| Locked out of SSH | Rule order or default deny applied before allow | Use out-of-band console access; add SSH allow rule first |
|
|
| Rules lost after reboot | Rules not persisted | Install `iptables-persistent` or save to `/etc/nftables.conf` |
|
|
| Docker bypasses iptables | Docker modifies iptables FORWARD chain | Use `DOCKER-USER` chain for custom rules; set `"iptables": false` in daemon.json |
|
|
| nftables and iptables conflict | Both running simultaneously | Migrate fully to nftables; remove iptables packages |
|
|
| AWS SG rule limit reached | Max 60 inbound rules per SG | Use prefix lists or consolidate CIDR ranges |
|
|
| Legitimate traffic blocked | Rule ordering issue | Place more specific allow rules before general deny rules |
|
|
|
|
## Best Practices
|
|
|
|
- Default deny policy on all chains
|
|
- Minimal rule sets - only open what is required
|
|
- Regular rule audits (monthly minimum)
|
|
- Log denied traffic for security monitoring
|
|
- Document all rules with descriptions and ticket references
|
|
- Use connection tracking for stateful inspection
|
|
- Rate limit inbound connections to prevent DDoS
|
|
- Separate management traffic from application traffic
|
|
- Test rule changes in staging before production
|
|
- Keep persistent backups of working rule sets
|
|
|
|
## Related Skills
|
|
|
|
- [linux-hardening](../../hardening/linux-hardening/) - System security
|
|
- [aws-vpc](../../../infrastructure/cloud-aws/aws-vpc/) - AWS networking
|
|
- [zero-trust](../zero-trust/) - Identity-based access patterns
|
|
- [vpn-setup](../vpn-setup/) - Secure tunnel configuration
|