563 lines
21 KiB
Bash
563 lines
21 KiB
Bash
#!/bin/bash
|
|
|
|
# Global variables
|
|
VERSION="2.0"
|
|
VERBOSE=false
|
|
BACKUP_DIR="/root/security_backup_$(date +%Y%m%d_%H%M%S)"
|
|
LOG_FILE="/var/log/security_hardening.log"
|
|
SCRIPT_NAME=$(basename "$0")
|
|
|
|
# Function for logging
|
|
log() {
|
|
local message="$(date '+%Y-%m-%d %H:%M:%S'): $1"
|
|
echo "$message" | sudo tee -a "$LOG_FILE"
|
|
$VERBOSE && echo "$message"
|
|
}
|
|
|
|
# Function for error handling
|
|
handle_error() {
|
|
log "Error: $1"
|
|
exit 1
|
|
}
|
|
|
|
# Function to install packages
|
|
install_package() {
|
|
log "Installing $1..."
|
|
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y "$1" || handle_error "Failed to install $1"
|
|
}
|
|
|
|
# Function to backup files
|
|
backup_files() {
|
|
sudo mkdir -p "$BACKUP_DIR" || handle_error "Failed to create backup directory"
|
|
|
|
local files_to_backup=(
|
|
"/etc/default/grub"
|
|
"/etc/ssh/sshd_config"
|
|
"/etc/pam.d/common-password"
|
|
"/etc/login.defs"
|
|
"/etc/sysctl.conf"
|
|
)
|
|
|
|
for file in "${files_to_backup[@]}"; do
|
|
if [ -f "$file" ]; then
|
|
sudo cp "$file" "$BACKUP_DIR/" || log "Warning: Failed to backup $file"
|
|
else
|
|
log "Warning: $file not found, skipping backup"
|
|
fi
|
|
done
|
|
|
|
log "Backup created in $BACKUP_DIR"
|
|
}
|
|
|
|
# Function to restore from backup
|
|
restore_backup() {
|
|
if [ -d "$BACKUP_DIR" ]; then
|
|
for file in "$BACKUP_DIR"/*; do
|
|
sudo cp "$file" "$(dirname "$(readlink -f "$file")")" || log "Warning: Failed to restore $(basename "$file")"
|
|
done
|
|
log "Restored configurations from $BACKUP_DIR"
|
|
else
|
|
log "Backup directory not found. Cannot restore."
|
|
fi
|
|
}
|
|
|
|
# Function to check permissions
|
|
check_permissions() {
|
|
if [ "$EUID" -ne 0 ]; then
|
|
echo "This script must be run with sudo privileges."
|
|
echo "Please run it again using: sudo $0"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Function to display help
|
|
display_help() {
|
|
echo "Usage: sudo ./$SCRIPT_NAME [OPTIONS]"
|
|
echo "Options:"
|
|
echo " -h, --help Display this help message"
|
|
echo " -v, --verbose Enable verbose output"
|
|
echo " --version Display script version"
|
|
echo " --dry-run Perform a dry run without making changes"
|
|
echo " --restore Restore system from the most recent backup"
|
|
exit 0
|
|
}
|
|
|
|
# Function to display version
|
|
display_version() {
|
|
echo "Enhanced Ubuntu Linux Security Hardening Script v$VERSION"
|
|
exit 0
|
|
}
|
|
|
|
# Function to check system requirements
|
|
check_requirements() {
|
|
if ! command -v lsb_release &> /dev/null; then
|
|
handle_error "lsb_release command not found. This script requires an Ubuntu-based system."
|
|
fi
|
|
|
|
local os_name=$(lsb_release -si)
|
|
local os_version=$(lsb_release -sr)
|
|
|
|
if [[ "$os_name" != "Ubuntu" && "$os_name" != "Debian" ]]; then
|
|
handle_error "This script is designed for Ubuntu or Debian-based systems. Detected OS: $os_name"
|
|
if [[ $(echo "$os_version < 18.04" | bc) -eq 1 ]]; then
|
|
handle_error "This script requires Ubuntu 18.04 or later. Detected version: $os_version"
|
|
elif [[ "$os_name" == "Debian" && $(echo "$os_version < 12.0" | bc) -eq 1 ]]; then
|
|
handle_error "This script requires Debian 12.0 or later. Detected version: $os_version"
|
|
fi
|
|
fi
|
|
|
|
log "System requirements check passed. OS: $os_name $os_version"
|
|
}
|
|
|
|
# Function to update system
|
|
update_system() {
|
|
log "Updating System..."
|
|
sudo apt-get update -y || handle_error "System update failed"
|
|
sudo DEBIAN_FRONTEND=noninteractive apt-get upgrade -y || handle_error "System upgrade failed"
|
|
}
|
|
|
|
# Function to setup firewall
|
|
setup_firewall() {
|
|
log "Installing and Configuring Firewall..."
|
|
install_package "ufw"
|
|
sudo ufw default deny incoming || handle_error "Failed to set UFW default incoming policy"
|
|
sudo ufw default allow outgoing || handle_error "Failed to set UFW default outgoing policy"
|
|
sudo ufw limit ssh comment 'Allow SSH with rate limiting' || handle_error "Failed to configure SSH in UFW"
|
|
sudo ufw allow 80/tcp comment 'Allow HTTP' || handle_error "Failed to allow HTTP in UFW"
|
|
sudo ufw allow 443/tcp comment 'Allow HTTPS' || handle_error "Failed to allow HTTPS in UFW"
|
|
|
|
local apply_ipv6_rules
|
|
read -p "Do you want to apply IPv6-specific firewall rules? (y/N): " apply_ipv6_rules
|
|
case $apply_ipv6_rules in
|
|
[Yy]* )
|
|
log "Applying IPv6-specific firewall rules..."
|
|
sudo ufw allow in on lo || handle_error "Failed to allow loopback traffic"
|
|
sudo ufw allow out on lo || handle_error "Failed to allow loopback traffic"
|
|
sudo ufw deny in from ::/0 || handle_error "Failed to deny all incoming IPv6 traffic"
|
|
sudo ufw allow out to ::/0 || handle_error "Failed to allow all outgoing IPv6 traffic"
|
|
log "IPv6 firewall rules applied"
|
|
;;
|
|
* )
|
|
log "Skipping IPv6-specific firewall rules"
|
|
;;
|
|
esac
|
|
|
|
sudo ufw logging on || handle_error "Failed to enable UFW logging"
|
|
sudo ufw --force enable || handle_error "Failed to enable UFW"
|
|
log "Firewall configured and enabled"
|
|
}
|
|
|
|
# Function to setup Fail2Ban
|
|
setup_fail2ban() {
|
|
log "Installing and Configuring Fail2Ban..."
|
|
install_package "fail2ban"
|
|
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local || handle_error "Failed to create Fail2Ban local config"
|
|
sudo sed -i 's/bantime = 10m/bantime = 1h/' /etc/fail2ban/jail.local || handle_error "Failed to set Fail2Ban bantime"
|
|
sudo sed -i 's/maxretry = 5/maxretry = 3/' /etc/fail2ban/jail.local || handle_error "Failed to set Fail2Ban maxretry"
|
|
sudo systemctl enable fail2ban || handle_error "Failed to enable Fail2Ban service"
|
|
sudo systemctl start fail2ban || handle_error "Failed to start Fail2Ban service"
|
|
log "Fail2Ban configured and started"
|
|
}
|
|
|
|
# Function to setup ClamAV
|
|
setup_clamav() {
|
|
log "Installing and Updating ClamAV..."
|
|
install_package "clamav"
|
|
install_package "clamav-daemon"
|
|
sudo systemctl stop clamav-freshclam || log "Warning: Failed to stop clamav-freshclam"
|
|
sudo freshclam || log "Warning: ClamAV database update failed"
|
|
sudo systemctl start clamav-freshclam || handle_error "Failed to start clamav-freshclam"
|
|
sudo systemctl enable clamav-freshclam || handle_error "Failed to enable clamav-freshclam"
|
|
log "ClamAV installed and updated"
|
|
}
|
|
|
|
# Function to disable root login
|
|
disable_root() {
|
|
log "Checking for non-root users with sudo privileges..."
|
|
|
|
# Get the list of users with sudo privileges
|
|
sudo_users=$(getent group sudo | cut -d: -f4 | tr ',' '\n' | grep -v "^root$")
|
|
|
|
# Check if there are any non-root users with sudo privileges
|
|
if [ -z "$sudo_users" ]; then
|
|
log "Warning: No non-root users with sudo privileges found. Skipping root login disable for safety."
|
|
echo "Please create a non-root user with sudo privileges before disabling root login."
|
|
return
|
|
fi
|
|
|
|
log "Non-root users with sudo privileges found. Proceeding to disable root login..."
|
|
|
|
# Disable root login
|
|
if sudo passwd -l root; then
|
|
log "Root login disabled successfully."
|
|
else
|
|
handle_error "Failed to lock root account"
|
|
fi
|
|
|
|
# Disable root SSH login as an additional precaution
|
|
if grep -q "^PermitRootLogin" /etc/ssh/sshd_config; then
|
|
sudo sed -i 's/^PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config || handle_error "Failed to disable root SSH login in sshd_config"
|
|
else
|
|
echo "PermitRootLogin no" | sudo tee -a /etc/ssh/sshd_config > /dev/null || handle_error "Failed to add PermitRootLogin no to sshd_config"
|
|
fi
|
|
|
|
# Restart SSH service to apply changes
|
|
sudo systemctl restart sshd || handle_error "Failed to restart SSH service"
|
|
|
|
log "Root login has been disabled and SSH root login has been explicitly prohibited."
|
|
}
|
|
|
|
# Function to remove unnecessary packages
|
|
remove_packages() {
|
|
log "Removing unnecessary packages..."
|
|
sudo DEBIAN_FRONTEND=noninteractive apt-get remove --purge -y telnetd nis yp-tools rsh-client rsh-redone-client xinetd || log "Warning: Failed to remove some packages"
|
|
sudo apt-get autoremove -y || log "Warning: autoremove failed"
|
|
log "Unnecessary packages removed"
|
|
}
|
|
|
|
# Function to setup audit
|
|
setup_audit() {
|
|
log "Configuring audit rules..."
|
|
install_package "auditd"
|
|
|
|
local audit_rules=(
|
|
"-w /etc/passwd -p wa -k identity"
|
|
"-w /etc/group -p wa -k identity"
|
|
"-w /etc/shadow -p wa -k identity"
|
|
"-w /etc/sudoers -p wa -k sudoers"
|
|
"-w /var/log/auth.log -p wa -k auth_log"
|
|
"-w /sbin/insmod -p x -k modules"
|
|
"-w /sbin/rmmod -p x -k modules"
|
|
"-w /sbin/modprobe -p x -k modules"
|
|
"-w /var/log/faillog -p wa -k logins"
|
|
"-w /var/log/lastlog -p wa -k logins"
|
|
"-w /var/run/utmp -p wa -k session"
|
|
"-w /var/log/wtmp -p wa -k session"
|
|
"-w /var/log/btmp -p wa -k session"
|
|
"-a always,exit -F arch=b64 -S adjtimex -S settimeofday -k time-change"
|
|
"-a always,exit -F arch=b32 -S adjtimex -S settimeofday -S stime -k time-change"
|
|
"-a always,exit -F arch=b64 -S clock_settime -k time-change"
|
|
"-a always,exit -F arch=b32 -S clock_settime -k time-change"
|
|
"-w /etc/localtime -p wa -k time-change"
|
|
)
|
|
|
|
for rule in "${audit_rules[@]}"; do
|
|
echo "$rule" | sudo tee -a /etc/audit/rules.d/audit.rules > /dev/null || handle_error "Failed to add audit rule: $rule"
|
|
done
|
|
|
|
sudo systemctl enable auditd || handle_error "Failed to enable auditd service"
|
|
sudo systemctl start auditd || handle_error "Failed to start auditd service"
|
|
log "Audit rules configured and auditd started"
|
|
}
|
|
|
|
# Function to disable unused filesystems
|
|
disable_filesystems() {
|
|
log "Disabling Unused Filesystems..."
|
|
local filesystems=("cramfs" "freevxfs" "jffs2" "hfs" "hfsplus" "squashfs" "udf" "vfat")
|
|
|
|
for fs in "${filesystems[@]}"; do
|
|
echo "install $fs /bin/true" | sudo tee -a /etc/modprobe.d/CIS.conf > /dev/null || handle_error "Failed to disable filesystem: $fs"
|
|
done
|
|
|
|
log "Unused filesystems disabled"
|
|
}
|
|
|
|
# Function to secure boot settings
|
|
secure_boot() {
|
|
log "Securing Boot Settings..."
|
|
|
|
# Secure GRUB configuration file
|
|
if [ -f /boot/grub/grub.cfg ]; then
|
|
sudo chown root:root /boot/grub/grub.cfg || handle_error "Failed to change ownership of grub.cfg"
|
|
sudo chmod 600 /boot/grub/grub.cfg || handle_error "Failed to change permissions of grub.cfg"
|
|
log "GRUB configuration file secured"
|
|
else
|
|
log "Warning: /boot/grub/grub.cfg not found. Skipping GRUB file permissions."
|
|
fi
|
|
|
|
# Modify kernel parameters
|
|
if [ -f /etc/default/grub ]; then
|
|
# Backup original file
|
|
sudo cp /etc/default/grub /etc/default/grub.bak || handle_error "Failed to backup grub file"
|
|
|
|
# Add or modify kernel parameters
|
|
local kernel_params="audit=1 net.ipv4.conf.all.rp_filter=1 net.ipv4.conf.all.accept_redirects=0 net.ipv4.conf.all.send_redirects=0"
|
|
|
|
# Ask if user wants to disable SACK
|
|
local disable_sack
|
|
read -p "Do you want to disable TCP SACK? This is generally not recommended. (y/N): " disable_sack
|
|
case $disable_sack in
|
|
[Yy]* )
|
|
kernel_params+=" net.ipv4.tcp_sack=0"
|
|
log "TCP SACK will be disabled"
|
|
;;
|
|
* )
|
|
log "TCP SACK will remain enabled"
|
|
;;
|
|
esac
|
|
|
|
sudo sed -i "s/GRUB_CMDLINE_LINUX=\"\"/GRUB_CMDLINE_LINUX=\"$kernel_params\"/" /etc/default/grub || handle_error "Failed to modify kernel parameters"
|
|
|
|
# Update GRUB
|
|
if command -v update-grub &> /dev/null; then
|
|
sudo update-grub || handle_error "Failed to update GRUB"
|
|
elif command -v grub2-mkconfig &> /dev/null; then
|
|
sudo grub2-mkconfig -o /boot/grub2/grub.cfg || handle_error "Failed to update GRUB"
|
|
else
|
|
log "Warning: Neither update-grub nor grub2-mkconfig found. Please update GRUB manually."
|
|
fi
|
|
|
|
log "Kernel parameters updated"
|
|
else
|
|
log "Warning: /etc/default/grub not found. Skipping kernel parameter modifications."
|
|
fi
|
|
|
|
log "Boot settings secured"
|
|
}
|
|
|
|
# Function to configure IPv6
|
|
configure_ipv6() {
|
|
local disable_ipv6
|
|
read -p "Do you want to disable IPv6? (y/N): " disable_ipv6
|
|
case $disable_ipv6 in
|
|
[Yy]* )
|
|
log "Disabling IPv6..."
|
|
echo "net.ipv6.conf.all.disable_ipv6 = 1" | sudo tee -a /etc/sysctl.conf || handle_error "Failed to disable IPv6 (all)"
|
|
echo "net.ipv6.conf.default.disable_ipv6 = 1" | sudo tee -a /etc/sysctl.conf || handle_error "Failed to disable IPv6 (default)"
|
|
echo "net.ipv6.conf.lo.disable_ipv6 = 1" | sudo tee -a /etc/sysctl.conf || handle_error "Failed to disable IPv6 (lo)"
|
|
sudo sysctl -p || handle_error "Failed to apply sysctl changes"
|
|
log "IPv6 has been disabled"
|
|
;;
|
|
* )
|
|
log "IPv6 will remain enabled"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Function to setup AppArmor
|
|
setup_apparmor() {
|
|
log "Setting up AppArmor..."
|
|
|
|
if ! command -v apparmor_status &> /dev/null; then
|
|
install_package "apparmor"
|
|
install_package "apparmor-utils"
|
|
else
|
|
log "AppArmor is already installed. Skipping installation."
|
|
fi
|
|
|
|
sudo systemctl enable apparmor || handle_error "Failed to enable AppArmor service"
|
|
sudo systemctl start apparmor || handle_error "Failed to start AppArmor service"
|
|
|
|
sudo aa-enforce /etc/apparmor.d/* || log "Warning: Failed to enforce some AppArmor profiles"
|
|
|
|
log "AppArmor setup complete. All profiles are in enforce mode."
|
|
log "Monitor /var/log/syslog and /var/log/auth.log for any AppArmor-related issues."
|
|
}
|
|
|
|
# Function to setup NTP
|
|
setup_ntp() {
|
|
log "Setting up time synchronization..."
|
|
|
|
# Check if systemd-timesyncd is available (modern Ubuntu systems)
|
|
if systemctl list-unit-files | grep -q systemd-timesyncd.service; then
|
|
log "Using systemd-timesyncd for time synchronization"
|
|
sudo systemctl enable systemd-timesyncd.service || handle_error "Failed to enable systemd-timesyncd service"
|
|
sudo systemctl start systemd-timesyncd.service || handle_error "Failed to start systemd-timesyncd service"
|
|
log "systemd-timesyncd setup complete"
|
|
else
|
|
# Fall back to traditional NTP if systemd-timesyncd is not available
|
|
log "Using traditional NTP for time synchronization"
|
|
install_package "ntp"
|
|
sudo systemctl enable ntp || handle_error "Failed to enable NTP service"
|
|
sudo systemctl start ntp || handle_error "Failed to start NTP service"
|
|
log "NTP setup complete"
|
|
fi
|
|
}
|
|
|
|
# Function to setup AIDE
|
|
setup_aide() {
|
|
log "Setting up AIDE..."
|
|
install_package "aide"
|
|
sudo aideinit || handle_error "Failed to initialize AIDE database"
|
|
sudo mv /var/lib/aide/aide.db.new /var/lib/aide/aide.db || handle_error "Failed to move AIDE database"
|
|
log "AIDE setup complete"
|
|
}
|
|
|
|
# Function to configure sysctl
|
|
configure_sysctl() {
|
|
log "Configuring sysctl settings..."
|
|
|
|
local sysctl_config=(
|
|
"# IP Spoofing protection"
|
|
"net.ipv4.conf.all.rp_filter = 1"
|
|
"net.ipv4.conf.default.rp_filter = 1"
|
|
""
|
|
"# Ignore ICMP broadcast requests"
|
|
"net.ipv4.icmp_echo_ignore_broadcasts = 1"
|
|
""
|
|
"# Disable source packet routing"
|
|
"net.ipv4.conf.all.accept_source_route = 0"
|
|
"net.ipv6.conf.all.accept_source_route = 0"
|
|
""
|
|
"# Ignore send redirects"
|
|
"net.ipv4.conf.all.send_redirects = 0"
|
|
"net.ipv4.conf.default.send_redirects = 0"
|
|
""
|
|
"# Block SYN attacks"
|
|
"net.ipv4.tcp_syncookies = 1"
|
|
"net.ipv4.tcp_max_syn_backlog = 2048"
|
|
"net.ipv4.tcp_synack_retries = 2"
|
|
"net.ipv4.tcp_syn_retries = 5"
|
|
""
|
|
"# Log Martians"
|
|
"net.ipv4.conf.all.log_martians = 1"
|
|
"net.ipv4.icmp_ignore_bogus_error_responses = 1"
|
|
""
|
|
"# Ignore ICMP redirects"
|
|
"net.ipv4.conf.all.accept_redirects = 0"
|
|
"net.ipv6.conf.all.accept_redirects = 0"
|
|
""
|
|
"# Ignore Directed pings"
|
|
"net.ipv4.icmp_echo_ignore_all = 1"
|
|
""
|
|
"# Enable ASLR"
|
|
"kernel.randomize_va_space = 2"
|
|
""
|
|
"# Increase system file descriptor limit"
|
|
"fs.file-max = 65535"
|
|
""
|
|
"# Allow for more PIDs"
|
|
"kernel.pid_max = 65536"
|
|
""
|
|
"# Protect against kernel pointer leaks"
|
|
"kernel.kptr_restrict = 1"
|
|
""
|
|
"# Restrict dmesg access"
|
|
"kernel.dmesg_restrict = 1"
|
|
""
|
|
"# Restrict kernel profiling"
|
|
"kernel.perf_event_paranoid = 2"
|
|
)
|
|
|
|
printf "%s\n" "${sysctl_config[@]}" | sudo tee -a /etc/sysctl.conf || handle_error "Failed to update sysctl.conf"
|
|
sudo sysctl -p || handle_error "Failed to apply sysctl changes"
|
|
log "sysctl settings configured"
|
|
}
|
|
|
|
# Function for additional security measures
|
|
additional_security() {
|
|
log "Applying additional security measures..."
|
|
|
|
# Disable core dumps
|
|
echo "* hard core 0" | sudo tee -a /etc/security/limits.conf || handle_error "Failed to disable core dumps"
|
|
|
|
# Set proper permissions on sensitive files
|
|
sudo chmod 600 /etc/shadow || handle_error "Failed to set permissions on /etc/shadow"
|
|
sudo chmod 600 /etc/gshadow || handle_error "Failed to set permissions on /etc/gshadow"
|
|
|
|
# Enable process accounting
|
|
install_package "acct"
|
|
sudo /usr/sbin/accton on || handle_error "Failed to enable process accounting"
|
|
|
|
# Restrict SSH
|
|
sudo sed -i 's/^#PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config || handle_error "Failed to disable root login via SSH"
|
|
sudo sed -i 's/^#PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config || handle_error "Failed to disable password authentication for SSH"
|
|
sudo sed -i 's/^#Protocol.*/Protocol 2/' /etc/ssh/sshd_config || handle_error "Failed to set SSH protocol version"
|
|
sudo systemctl restart sshd || handle_error "Failed to restart SSH service"
|
|
|
|
# Configure strong password policy
|
|
sudo sed -i 's/PASS_MAX_DAYS\t99999/PASS_MAX_DAYS\t90/' /etc/login.defs || handle_error "Failed to set password max days"
|
|
sudo sed -i 's/PASS_MIN_DAYS\t0/PASS_MIN_DAYS\t7/' /etc/login.defs || handle_error "Failed to set password min days"
|
|
sudo sed -i 's/password.*pam_unix.so.*/password [success=1 default=ignore] pam_unix.so obscure sha512 minlen=14 remember=5/' /etc/pam.d/common-password || handle_error "Failed to configure password policy"
|
|
|
|
log "Additional security measures applied"
|
|
}
|
|
|
|
# Function to setup automatic updates
|
|
setup_automatic_updates() {
|
|
log "Setting up automatic security updates..."
|
|
install_package "unattended-upgrades"
|
|
sudo dpkg-reconfigure -plow unattended-upgrades || handle_error "Failed to configure unattended-upgrades"
|
|
log "Automatic security updates configured"
|
|
}
|
|
|
|
# Main function
|
|
main() {
|
|
local dry_run=false
|
|
|
|
# Parse command line arguments
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
-h|--help)
|
|
display_help
|
|
;;
|
|
-v|--verbose)
|
|
VERBOSE=true
|
|
shift
|
|
;;
|
|
--version)
|
|
display_version
|
|
;;
|
|
--dry-run)
|
|
dry_run=true
|
|
shift
|
|
;;
|
|
--restore)
|
|
restore_backup
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo "Unknown option: $1"
|
|
display_help
|
|
;;
|
|
esac
|
|
done
|
|
|
|
check_permissions
|
|
check_requirements
|
|
backup_files
|
|
|
|
if $dry_run; then
|
|
log "Performing dry run. No changes will be made."
|
|
else
|
|
update_system
|
|
setup_firewall
|
|
setup_fail2ban
|
|
setup_clamav
|
|
# setup_snmp
|
|
# setup_nrpe
|
|
# setup_glpi
|
|
disable_root
|
|
remove_packages
|
|
setup_audit
|
|
disable_filesystems
|
|
secure_boot
|
|
configure_ipv6
|
|
setup_apparmor
|
|
setup_ntp
|
|
setup_aide
|
|
configure_sysctl
|
|
additional_security
|
|
setup_automatic_updates
|
|
fi
|
|
|
|
log "Enhanced Security Configuration executed! Script by captainzero93"
|
|
|
|
if ! $dry_run; then
|
|
# Ask user if they want to restart
|
|
read -p "Do you want to restart the system now to apply all changes? (y/N): " restart_now
|
|
case $restart_now in
|
|
[Yy]* )
|
|
log "Restarting system..."
|
|
sudo reboot
|
|
;;
|
|
* )
|
|
log "Please restart your system manually to apply all changes."
|
|
;;
|
|
esac
|
|
fi
|
|
}
|
|
|
|
# Run the main function
|
|
main "$@"
|