524 lines
16 KiB
Bash
524 lines
16 KiB
Bash
#!/bin/bash
|
|
# Football System Firewall Persistence Configuration
|
|
# Ensures firewall rules persist across reboots with nftables
|
|
|
|
set -e
|
|
|
|
echo "Configuring firewall persistence..."
|
|
|
|
# Install required packages if not already installed
|
|
apt-get update -qq
|
|
apt-get install -y -qq \
|
|
nftables \
|
|
iptables-persistent \
|
|
netfilter-persistent
|
|
|
|
# Create nftables configuration directory
|
|
mkdir -p /etc/nftables.conf.d
|
|
|
|
# Main nftables configuration
|
|
cat > /etc/nftables.conf << 'EOF'
|
|
# Football System - nftables Configuration
|
|
# Restrictive firewall rules for secure access
|
|
|
|
# Clear existing rules
|
|
flush ruleset
|
|
|
|
# Table definitions
|
|
table inet filter {
|
|
# Chain definitions
|
|
chain input {
|
|
type filter hook input priority 0; policy drop;
|
|
|
|
# Allow loopback traffic
|
|
iifname "lo" accept comment "Allow loopback"
|
|
|
|
# Allow established and related connections
|
|
ct state established,related accept comment "Allow established/related"
|
|
|
|
# Drop invalid packets
|
|
ct state invalid drop comment "Drop invalid packets"
|
|
|
|
# Allow ICMP (limited)
|
|
ip protocol icmp icmp type { echo-request, echo-reply } limit rate 10/second burst 5 packets accept comment "Allow ping (rate limited)"
|
|
ip6 nexthdr icmpv6 icmpv6 type { echo-request, echo-reply } limit rate 10/second burst 5 packets accept comment "Allow IPv6 ping (rate limited)"
|
|
|
|
# Allow required ICMP types
|
|
ip protocol icmp icmp type { destination-unreachable, time-exceeded, parameter-problem } accept comment "Allow required ICMP"
|
|
ip6 nexthdr icmpv6 icmpv6 type { destination-unreachable, time-exceeded, parameter-problem, packet-too-big, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept comment "Allow required ICMPv6"
|
|
|
|
# SSH access (restricted to management network if configured)
|
|
tcp dport 22 accept comment "Allow SSH (consider restricting)"
|
|
|
|
# Remmina/VNC access (only if needed)
|
|
tcp dport { 5900, 5901 } accept comment "Allow VNC access"
|
|
|
|
# WireGuard VPN
|
|
udp dport 51820 accept comment "Allow WireGuard VPN"
|
|
|
|
# DHCP client (if needed)
|
|
udp sport { 67,68 } udp dport { 67,68 } accept comment "Allow DHCP"
|
|
|
|
# DNS client
|
|
udp dport 53 ct state established,related accept comment "Allow DNS responses"
|
|
|
|
# NTP client
|
|
udp dport 123 ct state established,related accept comment "Allow NTP responses"
|
|
|
|
# HTTP/HTTPS client traffic (outbound responses)
|
|
tcp sport { 80,443 } ct state established,related accept comment "Allow web responses"
|
|
|
|
# Drop and log other traffic
|
|
log prefix "NFT-INPUT-DROP: " drop comment "Log and drop other input"
|
|
}
|
|
|
|
chain forward {
|
|
type filter hook forward priority 0; policy drop;
|
|
|
|
# Allow forwarding for VPN traffic
|
|
iifname "wg0" oifname != "wg0" accept comment "Allow VPN forwarding"
|
|
iifname != "wg0" oifname "wg0" accept comment "Allow traffic to VPN"
|
|
|
|
# Drop and log other forwarded traffic
|
|
log prefix "NFT-FORWARD-DROP: " drop comment "Log and drop other forward"
|
|
}
|
|
|
|
chain output {
|
|
type filter hook output priority 0; policy accept;
|
|
|
|
# Allow all outbound traffic by default (restrict as needed)
|
|
# Log blocked traffic for troubleshooting
|
|
log prefix "NFT-OUTPUT-DROP: " drop comment "Log dropped output"
|
|
}
|
|
}
|
|
|
|
# NAT table for VPN (if needed)
|
|
table ip nat {
|
|
chain postrouting {
|
|
type nat hook postrouting priority 100; policy accept;
|
|
|
|
# NAT for VPN traffic (if internet access via VPN)
|
|
# oifname "eth0" ip saddr 10.8.0.0/24 masquerade comment "NAT for VPN"
|
|
}
|
|
}
|
|
|
|
EOF
|
|
|
|
# Create custom rules directory for modular configuration
|
|
mkdir -p /etc/nftables.conf.d
|
|
|
|
# Create separate rule file for allowed management networks
|
|
cat > /etc/nftables.conf.d/management.nft << 'EOF'
|
|
# Management Network Access Rules
|
|
# Uncomment and modify for your management network(s)
|
|
|
|
# Allow SSH from management network only
|
|
# add rule inet filter input ip saddr 192.168.1.0/24 tcp dport 22 accept comment "SSH from management network"
|
|
|
|
# Allow monitoring from management network
|
|
# add rule inet filter input ip saddr 192.168.1.0/24 udp dport { 161,162 } accept comment "SNMP from management network"
|
|
EOF
|
|
|
|
# Create rate limiting rules
|
|
cat > /etc/nftables.conf.d/rate-limits.nft << 'EOF'
|
|
# Rate Limiting Rules
|
|
# Prevent brute force attacks and flooding
|
|
|
|
# Rate limit new SSH connections
|
|
add rule inet filter input tcp dport 22 ct state new limit rate 3/minute burst 5 accept comment "Rate limit SSH"
|
|
|
|
# Rate limit ping requests
|
|
add rule inet filter input ip protocol icmp icmp type echo-request limit rate 10/second burst 5 packets accept comment "Rate limit ping"
|
|
|
|
# Rate limit VNC connections
|
|
add rule inet filter input tcp dport { 5900,5901 } ct state new limit rate 2/minute burst 3 accept comment "Rate limit VNC"
|
|
EOF
|
|
|
|
# Create logging rules
|
|
cat > /etc/nftables.conf.d/logging.nft << 'EOF'
|
|
# Enhanced Logging Rules
|
|
# Log suspicious activity for security monitoring
|
|
|
|
# Log connection attempts to blocked ports
|
|
add rule inet filter input tcp dport { 23,3389,1433,3306,5432 } ct state new log prefix "NFT-SCANNED-PORT: " drop comment "Log blocked port scans"
|
|
|
|
# Log fragmented packets
|
|
add rule inet filter input ip frag-off drop log prefix "NFT-FRAGMENTED: " comment "Drop fragmented packets"
|
|
|
|
# Log suspicious flags
|
|
add rule inet filter input tcp flags & (syn|ack) == (syn|ack) log prefix "NFT-SYN-ACK: " drop comment "Log suspicious SYN-ACK"
|
|
EOF
|
|
|
|
# Create firewall persistence script
|
|
cat > /usr/local/bin/firewall-persistence.sh << 'EOF'
|
|
#!/bin/bash
|
|
# Football System - Firewall Persistence Script
|
|
# Ensures firewall rules are saved and restored properly
|
|
|
|
FIREWALL_CONFIG="/etc/nftables.conf"
|
|
RULES_DIR="/etc/nftables.conf.d"
|
|
LOCK_FILE="/var/lock/firewall-persistence"
|
|
LOG_FILE="/var/log/security/firewall-persistence.log"
|
|
|
|
# Function to log messages
|
|
log_message() {
|
|
local level=$1
|
|
local message=$2
|
|
echo "$(date '+%Y-%m-%d %H:%M:%S') [$level] $message" | tee -a "$LOG_FILE"
|
|
}
|
|
|
|
# Function to check if process is running
|
|
is_running() {
|
|
pgrep -f "$1" >/dev/null 2>&1
|
|
}
|
|
|
|
# Prevent concurrent execution
|
|
exec 200>"$LOCK_FILE"
|
|
if flock -n 200; then
|
|
log_message "INFO" "Starting firewall persistence check"
|
|
else
|
|
log_message "WARNING" "Firewall persistence script already running"
|
|
exit 1
|
|
fi
|
|
|
|
# Check if nftables service is running
|
|
if ! systemctl is-active --quiet nftables; then
|
|
log_message "ERROR" "nftables service is not running"
|
|
log_message "INFO" "Starting nftables service..."
|
|
systemctl start nftables
|
|
if systemctl is-active --quiet nftables; then
|
|
log_message "INFO" "nftables service started successfully"
|
|
else
|
|
log_message "CRITICAL" "Failed to start nftables service"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# Verify firewall rules are loaded
|
|
if ! nft list ruleset >/dev/null 2>&1; then
|
|
log_message "ERROR" "No firewall rules are loaded"
|
|
log_message "INFO" "Loading firewall rules..."
|
|
if nft -f "$FIREWALL_CONFIG"; then
|
|
log_message "INFO" "Main firewall rules loaded successfully"
|
|
|
|
# Load additional rule files
|
|
for rule_file in "$RULES_DIR"/*.nft; do
|
|
if [ -f "$rule_file" ]; then
|
|
log_message "INFO" "Loading rules from $(basename "$rule_file")"
|
|
nft -f "$rule_file"
|
|
fi
|
|
done
|
|
else
|
|
log_message "CRITICAL" "Failed to load firewall rules"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# Verify critical rules are in place
|
|
CRITICAL_RULES=(
|
|
"iifname \"lo\" accept"
|
|
"ct state established,related accept"
|
|
"tcp dport 22 accept"
|
|
"udp dport 51820 accept"
|
|
)
|
|
|
|
for rule in "${CRITICAL_RULES[@]}"; do
|
|
if nft list ruleset | grep -q "$rule"; then
|
|
log_message "DEBUG" "Critical rule verified: $rule"
|
|
else
|
|
log_message "WARNING" "Critical rule missing: $rule"
|
|
fi
|
|
done
|
|
|
|
# Check for potential firewall bypasses
|
|
log_message "INFO" "Checking for potential firewall bypasses"
|
|
|
|
# Check for raw socket usage
|
|
if netstat -anp 2>/dev/null | grep -q "raw"; then
|
|
log_message "WARNING" "Raw sockets detected - potential firewall bypass"
|
|
fi
|
|
|
|
# Check for iptables conflicts
|
|
if iptables -L >/dev/null 2>&1 && [ "$(iptables -L | wc -l)" -gt 6 ]; then
|
|
log_message "WARNING" "iptables rules detected - potential conflict with nftables"
|
|
fi
|
|
|
|
# Test basic connectivity through firewall
|
|
log_message "INFO" "Testing basic firewall functionality"
|
|
|
|
# Test loopback
|
|
if ping -c 1 -W 1 127.0.0.1 >/dev/null 2>&1; then
|
|
log_message "DEBUG" "Loopback connectivity test passed"
|
|
else
|
|
log_message "WARNING" "Loopback connectivity test failed"
|
|
fi
|
|
|
|
# Test that basic blocking works (if we can determine an unreachable port)
|
|
# This is a simple test - adjust as needed for your environment
|
|
if timeout 2 bash -c "echo >/dev/tcp/192.0.2.1/80" 2>/dev/null; then
|
|
log_message "WARNING" "Unexpected connectivity to test destination - check firewall rules"
|
|
else
|
|
log_message "DEBUG" "Basic blocking test passed (expected failure)"
|
|
fi
|
|
|
|
# Save current rules for persistence
|
|
if systemctl is-active --quiet nftables; then
|
|
log_message "INFO" "Saving firewall rules for persistence"
|
|
|
|
# Create backup of current rules
|
|
mkdir -p /var/backups/firewall
|
|
nft list ruleset > "/var/backups/firewall/ruleset_$(date +%Y%m%d_%H%M%S).nft"
|
|
|
|
log_message "INFO" "Firewall rules backed up successfully"
|
|
else
|
|
log_message "ERROR" "Cannot save rules - nftables service not running"
|
|
fi
|
|
|
|
# Report status
|
|
if systemctl is-active --quiet nftables && nft list ruleset >/dev/null 2>&1; then
|
|
log_message "INFO" "Firewall persistence check completed successfully"
|
|
exit 0
|
|
else
|
|
log_message "CRITICAL" "Firewall persistence check failed"
|
|
exit 1
|
|
fi
|
|
EOF
|
|
|
|
# Make persistence script executable
|
|
chmod 750 /usr/local/bin/firewall-persistence.sh
|
|
chown root:root /usr/local/bin/firewall-persistence.sh
|
|
|
|
# Create systemd service for firewall persistence
|
|
cat > /etc/systemd/system/firewall-persistence.service << 'EOF'
|
|
[Unit]
|
|
Description=Firewall Persistence Check
|
|
Documentation=man:nftables(8)
|
|
After=network.target nftables.service
|
|
Wants=nftables.service
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/local/bin/firewall-persistence.sh
|
|
StandardOutput=journal
|
|
StandardError=journal
|
|
|
|
# Security settings
|
|
NoNewPrivileges=yes
|
|
ProtectSystem=strict
|
|
ProtectHome=yes
|
|
ReadWritePaths=/var/log/security /var/lock
|
|
PrivateTmp=yes
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOF
|
|
|
|
# Create systemd timer for periodic checks
|
|
cat > /etc/systemd/system/firewall-persistence.timer << 'EOF'
|
|
[Unit]
|
|
Description=Run firewall persistence checks every 15 minutes
|
|
Requires=firewall-persistence.service
|
|
|
|
[Timer]
|
|
OnCalendar=*:0/15
|
|
Persistent=true
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
EOF
|
|
|
|
# Configure nftables service
|
|
cat > /etc/default/nftables << 'EOF'
|
|
# Configuration for nftables
|
|
|
|
# Set to "yes" to load firewall rules on boot
|
|
STANDARD_SETUP="yes"
|
|
|
|
# Set to "yes" to save firewall rules on shutdown/reboot
|
|
STANDARD_CLEANUP="no"
|
|
|
|
# Additional options to pass to nft during startup
|
|
NFT_OPTIONS=""
|
|
EOF
|
|
|
|
# Create iptables to nftables compatibility (if needed)
|
|
cat > /usr/local/bin/iptables-legacy-save.sh << 'EOF'
|
|
#!/bin/bash
|
|
# Legacy iptables save script for compatibility
|
|
# Saves current iptables rules for backup purposes
|
|
|
|
mkdir -p /var/backups/iptables
|
|
iptables-save > "/var/backups/iptables/legacy_$(date +%Y%m%d_%H%M%S).rules"
|
|
echo "Legacy iptables rules saved"
|
|
EOF
|
|
|
|
chmod 750 /usr/local/bin/iptables-legacy-save.sh
|
|
chown root:root /usr/local/bin/iptables-legacy-save.sh
|
|
|
|
# Create firewall status script
|
|
cat > /usr/local/bin/firewall-status.sh << 'EOF'
|
|
#!/bin/bash
|
|
# Football System - Firewall Status Check
|
|
# Comprehensive firewall status reporting
|
|
|
|
echo "=== Football System Firewall Status ==="
|
|
echo "Time: $(date)"
|
|
echo ""
|
|
|
|
# Check nftables service status
|
|
echo "=== Service Status ==="
|
|
if systemctl is-active --quiet nftables; then
|
|
echo "✅ nftables service: Active"
|
|
else
|
|
echo "❌ nftables service: Inactive"
|
|
fi
|
|
|
|
if systemctl is-enabled --quiet nftables; then
|
|
echo "✅ nftables service: Enabled on boot"
|
|
else
|
|
echo "❌ nftables service: Disabled on boot"
|
|
fi
|
|
|
|
echo ""
|
|
|
|
# Check ruleset status
|
|
echo "=== Ruleset Status ==="
|
|
if nft list ruleset >/dev/null 2>&1; then
|
|
echo "✅ Ruleset: Loaded"
|
|
TOTAL_RULES=$(nft list ruleset | grep -c "accept\|drop")
|
|
echo "Total rules: $TOTAL_RULES"
|
|
else
|
|
echo "❌ Ruleset: Not loaded"
|
|
fi
|
|
|
|
echo ""
|
|
|
|
# Show key rules
|
|
echo "=== Key Security Rules ==="
|
|
nft list ruleset | grep -E "(lo|ssh|wireguard|established)" | head -10
|
|
|
|
echo ""
|
|
|
|
# Check for recent firewall log entries
|
|
echo "=== Recent Firewall Log Entries ==="
|
|
if journalctl -u nftables --since "1 hour ago" | grep -q "NFT"; then
|
|
journalctl -u nftables --since "1 hour ago" | grep "NFT" | tail -5
|
|
else
|
|
echo "No recent firewall log entries"
|
|
fi
|
|
|
|
echo ""
|
|
|
|
# Check persistence timer status
|
|
echo "=== Persistence Monitoring ==="
|
|
if systemctl is-active --quiet firewall-persistence.timer; then
|
|
echo "✅ Persistence timer: Active"
|
|
NEXT_RUN=$(systemctl list-timers firewall-persistence.timer --no-pager | grep "n/a" -A 1 | tail -1 | awk '{print $1,$2,$3,$4}')
|
|
echo "Next run: $NEXT_RUN"
|
|
else
|
|
echo "❌ Persistence timer: Inactive"
|
|
fi
|
|
|
|
echo ""
|
|
|
|
# Network interface status
|
|
echo "=== Network Interface Status ==="
|
|
ip addr show | grep -E "(state|inet)" | grep -v "127.0.0.1"
|
|
|
|
echo ""
|
|
|
|
# Show active connections
|
|
echo "=== Recent Active Connections ==="
|
|
ss -tuln | head -10
|
|
|
|
echo "=== End Firewall Status ==="
|
|
EOF
|
|
|
|
chmod 750 /usr/local/bin/firewall-status.sh
|
|
chown root:root /usr/local/bin/firewall-status.sh
|
|
|
|
# Enable and start services
|
|
systemctl daemon-reload
|
|
systemctl enable nftables
|
|
systemctl start nftables
|
|
|
|
systemctl enable firewall-persistence.timer
|
|
systemctl start firewall-persistence.timer
|
|
|
|
# Load firewall rules
|
|
echo "Loading firewall rules..."
|
|
if nft -f /etc/nftables.conf; then
|
|
echo "✅ Main firewall rules loaded successfully"
|
|
else
|
|
echo "❌ Failed to load main firewall rules"
|
|
exit 1
|
|
fi
|
|
|
|
# Load additional rule files
|
|
for rule_file in /etc/nftables.conf.d/*.nft; do
|
|
if [ -f "$rule_file" ]; then
|
|
echo "Loading rules from $(basename "$rule_file")"
|
|
if nft -f "$rule_file"; then
|
|
echo "✅ Rules from $(basename "$rule_file") loaded successfully"
|
|
else
|
|
echo "❌ Failed to load rules from $(basename "$rule_file")"
|
|
fi
|
|
fi
|
|
done
|
|
|
|
# Run initial persistence check
|
|
if /usr/local/bin/firewall-persistence.sh; then
|
|
echo "✅ Firewall persistence check completed successfully"
|
|
else
|
|
echo "⚠️ Firewall persistence check completed with warnings"
|
|
fi
|
|
|
|
# Create firewall log rotation
|
|
cat > /etc/logrotate.d/firewall << 'EOF'
|
|
# Football System - Firewall Log Rotation
|
|
|
|
/var/log/security/firewall-persistence.log {
|
|
weekly
|
|
rotate 52
|
|
compress
|
|
delaycompress
|
|
missingok
|
|
notifempty
|
|
create 0640 root adm
|
|
sharedscripts
|
|
postrotate
|
|
systemctl reload rsyslog >/dev/null 2>&1 || true
|
|
endscript
|
|
}
|
|
|
|
/var/backups/firewall/*.nft {
|
|
monthly
|
|
rotate 12
|
|
compress
|
|
delaycompress
|
|
missingok
|
|
notifempty
|
|
}
|
|
EOF
|
|
|
|
chmod 644 /etc/logrotate.d/firewall
|
|
chown root:root /etc/logrotate.d/firewall
|
|
|
|
# Display firewall status
|
|
echo ""
|
|
echo "=== Firewall Configuration Summary ==="
|
|
echo "✅ nftables service enabled and started"
|
|
echo "✅ Firewall rules loaded from /etc/nftables.conf"
|
|
echo "✅ Additional rules loaded from /etc/nftables.conf.d/"
|
|
echo "✅ Persistence monitoring enabled (runs every 15 minutes)"
|
|
echo "✅ Status script available: /usr/local/bin/firewall-status.sh"
|
|
echo "✅ Log rotation configured"
|
|
echo ""
|
|
echo "Key firewall ports allowed:"
|
|
echo "- SSH (22): Remote management"
|
|
echo "- WireGuard (51820): VPN access"
|
|
echo "- VNC (5900-5901): Remote desktop"
|
|
echo "- ICMP (limited): Network diagnostics"
|
|
echo ""
|
|
echo "Run 'firewall-status.sh' for detailed status"
|
|
echo "✅ Firewall persistence configuration completed" |