feat: Major v2.0.0 rewrite - Enterprise-grade NAS setup script

🚀 BREAKING CHANGE: Complete rewrite to enterprise-grade standards

###  New Features:
- Enhanced input validation (IP, port, username, path)
- Automatic rollback mechanism on failures
- Comprehensive unit testing framework (50+ tests)
- Advanced logging with timestamps and levels
- Interactive configuration system with persistence
- Performance optimization suite (kernel, Docker, Samba)
- Advanced firewall configuration with monitoring
- System health monitoring and maintenance tools
- Multi-distribution support with version validation

### 🛡️ Security Enhancements:
- SSH hardening with security policies
- Rate limiting for critical services
- IP blocking/unblocking tools
- Intrusion detection capabilities
- Firewall monitoring with alerts
- Secure input sanitization

### 🔧 Architecture Improvements:
- Modular library structure
- Centralized configuration management
- Common functions separation
- Professional error handling with set -euo pipefail
- Signal handling for graceful shutdowns
- Resource cleanup mechanisms

### 📚 Documentation:
- Professional README with comprehensive guides
- Enhanced CONTRIBUTING.md with development standards
- Complete CHANGELOG.md with version history
- Troubleshooting guides and best practices

### 🧪 Testing & Quality:
- Unit tests for all critical functions
- Performance regression testing
- Multi-distribution integration testing
- Input validation testing
- Error scenario testing

This release transforms the script from a basic tool to a production-ready,
enterprise-grade NAS setup solution suitable for professional environments.
This commit is contained in:
Sebastian Palencsár
2025-06-17 10:57:46 +02:00
parent cf27011875
commit cb91166616
11 changed files with 3486 additions and 444 deletions

View File

@@ -1,66 +1,444 @@
#!/bin/bash
# Function to set up firewall rules for Fedora
setup_firewall_fedora() {
echo "Setting up firewall for Fedora..."
# Enhanced firewall configuration with comprehensive rules and intrusion detection
# UFW configuration function
configure_ufw() {
log_info "Configuring UFW (Uncomplicated Firewall)..."
# Install UFW if not present
case $DISTRO in
ubuntu|debian)
sudo apt-get install -y ufw
;;
arch)
sudo pacman -S --noconfirm ufw
;;
fedora|opensuse)
log_warning "UFW not available on $DISTRO, using firewalld instead"
return 1
;;
esac
# Reset UFW to defaults
sudo ufw --force reset
# Set default policies
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw default deny forward
# Configure logging
sudo ufw logging medium
return 0
}
# Firewalld configuration function
configure_firewalld() {
log_info "Configuring firewalld..."
# Install firewalld if not present
case $DISTRO in
fedora)
sudo dnf install -y firewalld
;;
opensuse)
sudo zypper install -y firewalld
;;
*)
log_error "Firewalld not supported on $DISTRO"
return 1
;;
esac
# Enable and start firewalld
sudo systemctl enable firewalld
sudo systemctl start firewalld
# Set default zone
sudo firewall-cmd --set-default-zone=public
return 0
}
# Add UFW rules
add_ufw_rules() {
local ssh_port="${SSH_PORT:-$DEFAULT_SSH_PORT}"
log_info "Adding UFW firewall rules..."
# SSH access
sudo ufw allow "$ssh_port/tcp" comment "SSH"
# Samba file sharing
sudo ufw allow from any to any port 137,138 proto udp comment "Samba NetBIOS"
sudo ufw allow from any to any port 139,445 proto tcp comment "Samba SMB"
# NFS (if enabled)
if [[ "${INSTALL_NFS:-false}" == "true" ]]; then
sudo ufw allow 2049/tcp comment "NFS"
sudo ufw allow 111/tcp comment "NFS Portmapper"
sudo ufw allow 111/udp comment "NFS Portmapper"
fi
# Docker (if enabled)
if [[ "${INSTALL_DOCKER:-false}" == "true" ]]; then
sudo ufw allow 2375/tcp comment "Docker API"
sudo ufw allow 2376/tcp comment "Docker API TLS"
fi
# Netdata monitoring (if enabled)
if [[ "${INSTALL_NETDATA:-false}" == "true" ]]; then
sudo ufw allow "$NETDATA_PORT/tcp" comment "Netdata"
fi
# Jellyfin media server (if enabled)
if [[ "${INSTALL_JELLYFIN:-false}" == "true" ]]; then
sudo ufw allow 8096/tcp comment "Jellyfin HTTP"
sudo ufw allow 8920/tcp comment "Jellyfin HTTPS"
sudo ufw allow 1900/udp comment "Jellyfin DLNA"
sudo ufw allow 7359/udp comment "Jellyfin Discovery"
fi
# Portainer (if enabled)
if [[ "${INSTALL_PORTAINER:-false}" == "true" ]]; then
sudo ufw allow 9000/tcp comment "Portainer"
fi
# Vaultwarden (if enabled)
if [[ "${INSTALL_VAULTWARDEN:-false}" == "true" ]]; then
sudo ufw allow 8080/tcp comment "Vaultwarden"
fi
# Basic network services
sudo ufw allow out 53 comment "DNS"
sudo ufw allow out 80/tcp comment "HTTP"
sudo ufw allow out 443/tcp comment "HTTPS"
sudo ufw allow out 123/udp comment "NTP"
# Local network communication
local local_networks=("192.168.0.0/16" "10.0.0.0/8" "172.16.0.0/12")
for network in "${local_networks[@]}"; do
sudo ufw allow from "$network" comment "Local network"
done
log_success "UFW rules configured successfully"
}
# Add firewalld rules
add_firewalld_rules() {
local ssh_port="${SSH_PORT:-$DEFAULT_SSH_PORT}"
log_info "Adding firewalld rules..."
# SSH access
sudo firewall-cmd --permanent --add-port="$ssh_port/tcp"
# Remove default SSH if using custom port
if [[ "$ssh_port" != "22" ]]; then
sudo firewall-cmd --permanent --remove-service=ssh
fi
# Samba file sharing
sudo firewall-cmd --permanent --add-service=samba
# NFS (if enabled)
if [[ "${INSTALL_NFS:-false}" == "true" ]]; then
sudo firewall-cmd --permanent --add-service=nfs
sudo firewall-cmd --permanent --add-service=rpc-bind
sudo firewall-cmd --permanent --add-service=mountd
fi
# HTTP services for web interfaces
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
# Netdata monitoring (if enabled)
if [[ "${INSTALL_NETDATA:-false}" == "true" ]]; then
sudo firewall-cmd --permanent --add-port="$NETDATA_PORT/tcp"
fi
# Jellyfin media server (if enabled)
if [[ "${INSTALL_JELLYFIN:-false}" == "true" ]]; then
sudo firewall-cmd --permanent --add-port=8096/tcp
sudo firewall-cmd --permanent --add-port=8920/tcp
sudo firewall-cmd --permanent --add-port=1900/udp
sudo firewall-cmd --permanent --add-port=7359/udp
fi
# Portainer (if enabled)
if [[ "${INSTALL_PORTAINER:-false}" == "true" ]]; then
sudo firewall-cmd --permanent --add-port=9000/tcp
fi
# Vaultwarden (if enabled)
if [[ "${INSTALL_VAULTWARDEN:-false}" == "true" ]]; then
sudo firewall-cmd --permanent --add-port=8080/tcp
fi
# Reload firewalld
sudo firewall-cmd --reload
echo "Firewall setup complete for Fedora."
log_success "Firewalld rules configured successfully"
}
# Function to set up firewall rules for Arch Linux
setup_firewall_arch() {
echo "Setting up firewall for Arch Linux..."
sudo ufw allow http
sudo ufw allow https
sudo ufw enable
echo "Firewall setup complete for Arch Linux."
# Rate limiting configuration
configure_rate_limiting() {
log_info "Configuring rate limiting..."
case $DISTRO in
ubuntu|debian|arch)
# UFW rate limiting
local ssh_port="${SSH_PORT:-$DEFAULT_SSH_PORT}"
sudo ufw limit "$ssh_port/tcp" comment "SSH rate limit"
# Additional rate limiting for web services
if [[ "${INSTALL_NETDATA:-false}" == "true" ]]; then
sudo ufw limit "$NETDATA_PORT/tcp" comment "Netdata rate limit"
fi
;;
fedora|opensuse)
# Firewalld rate limiting using rich rules
local ssh_port="${SSH_PORT:-$DEFAULT_SSH_PORT}"
sudo firewall-cmd --permanent --add-rich-rule="rule service name=\"ssh\" limit value=\"10/m\" accept"
sudo firewall-cmd --reload
;;
esac
log_success "Rate limiting configured"
}
# Function to set up firewall rules for openSUSE
setup_firewall_opensuse() {
echo "Setting up firewall for openSUSE..."
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
echo "Firewall setup complete for openSUSE."
}
# IP blocking and intrusion detection
configure_ip_blocking() {
log_info "Configuring IP blocking capabilities..."
# Create script for manual IP blocking
sudo tee /usr/local/bin/block-ip > /dev/null <<'EOF'
#!/bin/bash
# Script to block IP addresses
# Detect the operating system and call the appropriate function
if [ -f /etc/fedora-release ]; then
setup_firewall_fedora
elif [ -f /etc/arch-release ]; then
setup_firewall_arch
elif [ -f /etc/SuSE-release ]; then
setup_firewall_opensuse
else
echo "Unsupported operating system."
if [[ $# -ne 1 ]]; then
echo "Usage: $0 <IP_ADDRESS>"
exit 1
fi
configure_firewall() {
log_info "Configuring firewall..."
IP="$1"
# Allow SSH
ufw allow "${DEFAULT_SSH_PORT}/tcp"
# Validate IP address
if [[ ! $IP =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
echo "Error: Invalid IP address format"
exit 1
fi
# Block IP based on firewall type
if command -v ufw &>/dev/null; then
ufw deny from "$IP"
echo "IP $IP blocked via UFW"
elif command -v firewall-cmd &>/dev/null; then
firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='$IP' reject"
firewall-cmd --reload
echo "IP $IP blocked via firewalld"
else
echo "Error: No compatible firewall found"
exit 1
fi
# Log the action
logger "IP $IP manually blocked by $(whoami)"
EOF
sudo chmod +x /usr/local/bin/block-ip
# Allow Samba
ufw allow from any to any port 137,138 proto udp
ufw allow from any to any port 139,445 proto tcp
# Create script for unblocking IP addresses
sudo tee /usr/local/bin/unblock-ip > /dev/null <<'EOF'
#!/bin/bash
# Script to unblock IP addresses
# Allow NFS
ufw allow from any to any port 2049 proto tcp
if [[ $# -ne 1 ]]; then
echo "Usage: $0 <IP_ADDRESS>"
exit 1
fi
# Allow Netdata
ufw allow "${NETDATA_PORT}/tcp"
IP="$1"
# Allow Docker
ufw allow 2375/tcp
ufw allow 2376/tcp
# Validate IP address
if [[ ! $IP =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
echo "Error: Invalid IP address format"
exit 1
fi
# Enable UFW
ufw --force enable
# Unblock IP based on firewall type
if command -v ufw &>/dev/null; then
ufw delete deny from "$IP"
echo "IP $IP unblocked via UFW"
elif command -v firewall-cmd &>/dev/null; then
firewall-cmd --permanent --remove-rich-rule="rule family='ipv4' source address='$IP' reject"
firewall-cmd --reload
echo "IP $IP unblocked via firewalld"
else
echo "Error: No compatible firewall found"
exit 1
fi
log_info "Firewall configuration completed."
# Log the action
logger "IP $IP manually unblocked by $(whoami)"
EOF
sudo chmod +x /usr/local/bin/unblock-ip
log_success "IP blocking scripts created: /usr/local/bin/block-ip and /usr/local/bin/unblock-ip"
}
# Firewall monitoring and alerting
setup_firewall_monitoring() {
log_info "Setting up firewall monitoring..."
# Create log monitoring script
sudo tee /usr/local/bin/firewall-monitor > /dev/null <<'EOF'
#!/bin/bash
# Firewall monitoring script
LOG_FILE="/var/log/firewall-monitor.log"
ALERT_THRESHOLD=10
CHECK_INTERVAL=300 # 5 minutes
monitor_ufw() {
local denied_count=$(grep "UFW BLOCK" /var/log/ufw.log | grep "$(date '+%b %d')" | wc -l)
if [[ $denied_count -gt $ALERT_THRESHOLD ]]; then
echo "$(date): High number of blocked connections detected: $denied_count" >> "$LOG_FILE"
logger "UFW: High number of blocked connections: $denied_count"
fi
}
monitor_firewalld() {
local denied_count=$(journalctl -u firewalld --since "5 minutes ago" | grep -c "REJECT")
if [[ $denied_count -gt $ALERT_THRESHOLD ]]; then
echo "$(date): High number of blocked connections detected: $denied_count" >> "$LOG_FILE"
logger "Firewalld: High number of blocked connections: $denied_count"
fi
}
# Main monitoring loop
while true; do
if command -v ufw &>/dev/null && ufw status | grep -q "Status: active"; then
monitor_ufw
elif command -v firewall-cmd &>/dev/null && firewall-cmd --state &>/dev/null; then
monitor_firewalld
fi
sleep $CHECK_INTERVAL
done
EOF
sudo chmod +x /usr/local/bin/firewall-monitor
# Create systemd service for firewall monitoring
sudo tee /etc/systemd/system/firewall-monitor.service > /dev/null <<EOF
[Unit]
Description=Firewall Monitoring Service
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/firewall-monitor
Restart=always
RestartSec=10
User=root
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable firewall-monitor.service
sudo systemctl start firewall-monitor.service
log_success "Firewall monitoring service configured and started"
}
# Backup and restore firewall configuration
backup_firewall_config() {
local backup_dir="/etc/firewall-backup"
sudo mkdir -p "$backup_dir"
log_info "Backing up firewall configuration..."
case $DISTRO in
ubuntu|debian|arch)
if command -v ufw &>/dev/null; then
sudo cp -r /etc/ufw "$backup_dir/ufw-$(date +%Y%m%d-%H%M%S)"
fi
;;
fedora|opensuse)
if command -v firewall-cmd &>/dev/null; then
sudo cp -r /etc/firewalld "$backup_dir/firewalld-$(date +%Y%m%d-%H%M%S)"
fi
;;
esac
log_success "Firewall configuration backed up to $backup_dir"
}
# Main firewall configuration function
configure_firewall() {
log_info "=== Firewall Configuration ==="
# Backup existing configuration
backup_firewall_config
# Configure appropriate firewall based on distribution
case $DISTRO in
ubuntu|debian|arch)
if configure_ufw; then
add_ufw_rules
configure_rate_limiting
# Enable UFW
sudo ufw --force enable
log_success "UFW firewall enabled and configured"
add_rollback_action "sudo ufw --force disable"
else
log_error "Failed to configure UFW"
return 1
fi
;;
fedora|opensuse)
if configure_firewalld; then
add_firewalld_rules
configure_rate_limiting
log_success "Firewalld configured successfully"
add_rollback_action "sudo systemctl stop firewalld && sudo systemctl disable firewalld"
else
log_error "Failed to configure firewalld"
return 1
fi
;;
*)
log_error "Unsupported distribution for firewall configuration: $DISTRO"
return 1
;;
esac
# Additional security features
configure_ip_blocking
setup_firewall_monitoring
# Show firewall status
echo
log_info "Firewall Status:"
case $DISTRO in
ubuntu|debian|arch)
sudo ufw status verbose
;;
fedora|opensuse)
sudo firewall-cmd --list-all
;;
esac
log_success "Firewall configuration completed successfully"
}