Configure iptables, nftables, and cloud firewalls. Implement network segmentation and traffic filtering. Use when securing network perimeters or implementing security zones.
BY BagelHole/DevOps-Security-Agent-Skills contributors, via Agentic Awesome SkillsUPDATED Oct 26, 2026
INTENDED FOR✳Claude Code>_Codex↗CursorInstall in a listed agent.
instructions.md
---
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.
category: security
risk: critical
source: https://github.com/BagelHole/DevOps-Security-Agent-Skills
source_repo: BagelHole/DevOps-Security-Agent-Skills
source_type: community
date_added: '2026-09-20'
license: MIT
license_source: https://github.com/BagelHole/DevOps-Security-Agent-Skills/blob/main/LICENSE
compatibility: Requires the relevant security tooling (scanners, vault CLIs) and an
authorized scope for any active assessment. Docs-only; helper scripts and templates
not bundled.
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
Before writes, inventory the active firewall manager, IPv4/IPv6 policy, container/CNI rules and current management path. Preserve a verified rules backup, out-of-band console and tested rollback. Use an atomic reviewed ruleset where supported; do not flush NAT/mangle or an entire ruleset on a shared host. Examples are alternative local-lab sketches, not a script to run sequentially.
## iptables
### Basic Setup with Default Deny
```bash
# Preserve existing rules; do not flush production/container-managed tables.
# Build and validate a complete candidate offline, including management allows,
# before atomically applying it within authorized scope.
# 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
# Do not add a global SYN ACCEPT: it bypasses service/source restrictions.
# Apply a measured, service-specific limiter before the matching service allow;
# a host firewall cannot guarantee mitigation of upstream bandwidth exhaustion.
# 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
# Allow SSH from management network
ufw allow from 10.0.100.0/24 to any port 22 proto tcp
# Enable only after confirming this allow matches the actual management path.
ufw enable
# 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
### Illustrative Server Configuration
Not a complete router/container policy: the forward chain drops traffic, so the DNAT example below also needs narrowly scoped forwarding and IP forwarding configuration. Validate required ICMPv6 control/error traffic for the actual network before use. The late SYN limiter does not affect earlier accepted HTTP/HTTPS packets.
```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-neighbor-advert, nd-router-solicit, nd-router-advert, destination-unreachable, packet-too-big, time-exceeded, parameter-problem } 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 | Review the Docker backend and supported policy chain; disabling Docker firewall management can break isolation/NAT and is not a routine fix |
| nftables and iptables conflict | Both running simultaneously | Identify whether iptables uses the nft backend and which manager owns rules; do not remove packages or flush blindly |
| 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 (`linux-hardening`) - System security
- aws-vpc (`aws-vpc`) - AWS networking
- zero-trust (`zero-trust`) - Identity-based access patterns
- vpn-setup (`vpn-setup`) - Secure tunnel configuration
## Limitations
- Apply guidance only within authorized scope; test destructive steps in non-production first.
- Docs-only import: upstream scripts and templates not bundled.
### Example
```bash
# Read-only first: inventory before any active step.
which <tool> && <tool> --help | head -n 20
```
> Adapted from [BagelHole/DevOps-Security-Agent-Skills](https://github.com/BagelHole/DevOps-Security-Agent-Skills) (MIT); frontmatter, When to Use/Limitations, and safety boundaries added for upstream compliance. Docs-only import: helper scripts and templates not bundled.
---
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.
category: security
risk: critical
source: https://github.com/BagelHole/DevOps-Security-Agent-Skills
source_repo: BagelHole/DevOps-Security-Agent-Skills
source_type: community
date_added: '2026-09-20'
license: MIT
license_source: https://github.com/BagelHole/DevOps-Security-Agent-Skills/blob/main/LICENSE
compatibility: Requires the relevant security tooling (scanners, vault CLIs) and an
authorized scope for any active assessment. Docs-only; helper scripts and templates
not bundled.
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
Before writes, inventory the active firewall manager, IPv4/IPv6 policy, container/CNI rules and current management path. Preserve a verified rules backup, out-of-band console and tested rollback. Use an atomic reviewed ruleset where supported; do not flush NAT/mangle or an entire ruleset on a shared host. Examples are alternative local-lab sketches, not a script to run sequentially.
## iptables
### Basic Setup with Default Deny
```bash
# Preserve existing rules; do not flush production/container-managed tables.
# Build and validate a complete candidate offline, including management allows,
# before atomically applying it within authorized scope.
# 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
# Do not add a global SYN ACCEPT: it bypasses service/source restrictions.
# Apply a measured, service-specific limiter before the matching service allow;
# a host firewall cannot guarantee mitigation of upstream bandwidth exhaustion.
# 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
# Allow SSH from management network
ufw allow from 10.0.100.0/24 to any port 22 proto tcp
# Enable only after confirming this allow matches the actual management path.
ufw enable
# 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
### Illustrative Server Configuration
Not a complete router/container policy: the forward chain drops traffic, so the DNAT example below also needs narrowly scoped forwarding and IP forwarding configuration. Validate required ICMPv6 control/error traffic for the actual network before use. The late SYN limiter does not affect earlier accepted HTTP/HTTPS packets.
```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-neighbor-advert, nd-router-solicit, nd-router-advert, destination-unreachable, packet-too-big, time-exceeded, parameter-problem } 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 | Review the Docker backend and supported policy chain; disabling Docker firewall management can break isolation/NAT and is not a routine fix |
| nftables and iptables conflict | Both running simultaneously | Identify whether iptables uses the nft backend and which manager owns rules; do not remove packages or flush blindly |
| 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 (`linux-hardening`) - System security
- aws-vpc (`aws-vpc`) - AWS networking
- zero-trust (`zero-trust`) - Identity-based access patterns
- vpn-setup (`vpn-setup`) - Secure tunnel configuration
## Limitations
- Apply guidance only within authorized scope; test destructive steps in non-production first.
- Docs-only import: upstream scripts and templates not bundled.
### Example
```bash
# Read-only first: inventory before any active step.
which <tool> && <tool> --help | head -n 20
```
> Adapted from [BagelHole/DevOps-Security-Agent-Skills](https://github.com/BagelHole/DevOps-Security-Agent-Skills) (MIT); frontmatter, When to Use/Limitations, and safety boundaries added for upstream compliance. Docs-only import: helper scripts and templates not bundled.
COMPATIBILITY & REFERENCES
Platform guidance
Imported SKILL.md format for Claude Code, Codex and Cursor. Review the complete instructions and required tools before use. Package integrity checked; individual agent behavior has not been tested.
Generate detailed control implementation guidance, technical steps, and implementation plans for OSCAL security controls. Use this skill to create implementation narratives, technical procedures, and deployment plans.
Soc2 Compliance Checker - Auto-activating skill for Security Advanced. Triggers on: soc2 compliance checker, soc2 compliance checker Part of the Security Advanced skill category.