update : not good
This commit is contained in:
parent
9d27cb1b59
commit
e83894e30e
@ -8,6 +8,38 @@ NOCOLOR='\033[0m'
|
|||||||
echo "${YELLOW} ** ${NOCOLOR} Début du script : 01-ssh"
|
echo "${YELLOW} ** ${NOCOLOR} Début du script : 01-ssh"
|
||||||
echo "${NOCOLOR}"
|
echo "${NOCOLOR}"
|
||||||
|
|
||||||
|
echo "${YELLOW} * ${NOCOLOR} Controle des persmissions"
|
||||||
|
echo "${NOCOLOR}"
|
||||||
|
|
||||||
|
check_permissions
|
||||||
|
|
||||||
|
echo "${YELLOW} * ${NOCOLOR} Controle des persmissions : ${GREEN} OK"
|
||||||
|
echo "${NOCOLOR}"
|
||||||
|
|
||||||
|
echo "${YELLOW} * ${NOCOLOR} Controle des pre requis"
|
||||||
|
echo "${NOCOLOR}"
|
||||||
|
|
||||||
|
check_requirements
|
||||||
|
|
||||||
|
echo "${YELLOW} * ${NOCOLOR} Controle des pre requis : ${GREEN} OK"
|
||||||
|
echo "${NOCOLOR}"
|
||||||
|
|
||||||
|
echo "${YELLOW} * ${NOCOLOR} Sauvegarde ancien fichiers"
|
||||||
|
echo "${NOCOLOR}"
|
||||||
|
|
||||||
|
backup_files
|
||||||
|
|
||||||
|
echo "${YELLOW} * ${NOCOLOR} Sauvegarde ancien fichiers : ${GREEN} OK"
|
||||||
|
echo "${NOCOLOR}"
|
||||||
|
|
||||||
|
echo "${YELLOW} * ${NOCOLOR} Update du systeme"
|
||||||
|
echo "${NOCOLOR}"
|
||||||
|
|
||||||
|
update_system
|
||||||
|
|
||||||
|
echo "${YELLOW} * ${NOCOLOR} Update du systeme : ${GREEN} OK"
|
||||||
|
echo "${NOCOLOR}"
|
||||||
|
|
||||||
echo "${YELLOW} * ${NOCOLOR} Copie du fichier : authorized_keys"
|
echo "${YELLOW} * ${NOCOLOR} Copie du fichier : authorized_keys"
|
||||||
echo "${NOCOLOR}"
|
echo "${NOCOLOR}"
|
||||||
|
|
3
00-proxy/02proxy
Normal file
3
00-proxy/02proxy
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
Acquire::http::proxy "http://serv-proxy.fr.dgs.group:3128";
|
||||||
|
Acquire::https::proxy "http://serv-proxy.fr.dgs.group:3128";
|
||||||
|
Acquire::ftp::proxy "http://serv-proxy.fr.dgs.group:3128";
|
36
00-proxy/script.sh
Normal file
36
00-proxy/script.sh
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Pour la configuration de l'APT d'utiliser le proxy
|
||||||
|
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
NOCOLOR='\033[0m'
|
||||||
|
|
||||||
|
echo "${YELLOW} ** ${NOCOLOR} Début du script : 02-apt"
|
||||||
|
echo "${NOCOLOR}"
|
||||||
|
|
||||||
|
echo "${YELLOW} * ${NOCOLOR} Copie du fichier : 02proxy"
|
||||||
|
echo "${NOCOLOR}"
|
||||||
|
|
||||||
|
cp 02-apt/02proxy /etc/apt/apt.conf.d/02proxy >> /dev/null
|
||||||
|
|
||||||
|
echo "${YELLOW} * ${NOCOLOR} Copie du fichier : 02proxy : ${GREEN} OK"
|
||||||
|
echo "${NOCOLOR}"
|
||||||
|
|
||||||
|
echo "${YELLOW} * ${NOCOLOR} Référence update"
|
||||||
|
echo "${NOCOLOR}"
|
||||||
|
|
||||||
|
apt update >> /dev/null
|
||||||
|
|
||||||
|
echo "${YELLOW} * ${NOCOLOR} Référence update : ${GREEN} OK"
|
||||||
|
echo "${NOCOLOR}"
|
||||||
|
|
||||||
|
echo "${YELLOW} * ${NOCOLOR} Mise à jour"
|
||||||
|
echo "${NOCOLOR}"
|
||||||
|
|
||||||
|
apt full-upgrade -y >> /dev/null
|
||||||
|
|
||||||
|
echo "${YELLOW} * ${NOCOLOR} Mise à jour : ${GREEN} OK"
|
||||||
|
echo "${NOCOLOR}"
|
||||||
|
|
||||||
|
echo "${YELLOW} ** ${NOCOLOR} Fin du script : 02-apt"
|
||||||
|
echo "${NOCOLOR}"
|
1
01-key/authorized_keys
Normal file
1
01-key/authorized_keys
Normal file
@ -0,0 +1 @@
|
|||||||
|
ssh-rsa AAAAB3NzaC1yc2EAAAADAQA
|
66
02-prompt/00-basic
Normal file
66
02-prompt/00-basic
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# get load averages
|
||||||
|
IFS=" " read LOAD1 LOAD5 LOAD15 <<<$(awk '{ print $1,$2,$3 }' /proc/loadavg)
|
||||||
|
# get free memory
|
||||||
|
IFS=" " read USED AVAIL TOTAL <<<$(free -htm | awk '/Mem/ { print $3,$7,$2 }')
|
||||||
|
# get processes
|
||||||
|
PROCESS=$(ps -eo user=|sort|uniq -c | awk '{ print $2 " " $1 }')
|
||||||
|
PROCESS_ALL=$(echo "$PROCESS"| awk {'print $2'} | awk '{ SUM += $1} END { print SUM }')
|
||||||
|
PROCESS_ROOT=$(echo "$PROCESS" | awk '/root/ { print $2}')
|
||||||
|
PROCESS_USER=$(echo "$PROCESS" | awk '!/root/ { SUM += $2} END { print SUM }')
|
||||||
|
# get processors
|
||||||
|
PROCESSOR_NAME=$(awk -F": " '/model name/ { print $2 }' /proc/cpuinfo | head -1)
|
||||||
|
PROCESSOR_COUNT=$(grep -ioPc 'processor\t:' /proc/cpuinfo)
|
||||||
|
|
||||||
|
# colors
|
||||||
|
W="\e[0;39m"
|
||||||
|
G="\e[1;32m"
|
||||||
|
R="\e[1;31m"
|
||||||
|
dim="\e[2m"
|
||||||
|
undim="\e[0m"
|
||||||
|
|
||||||
|
echo -e "${W}System info:
|
||||||
|
$W Hostname$dim····$undim: $W${HOSTNAME}
|
||||||
|
$W Distro$dim······$undim: $W$(grep "PRETTY_NAME" /etc/*release | cut -d "=" -f 2- | sed 's/"//g')
|
||||||
|
$W Kernel$dim······$undim: $W$(uname -sr)
|
||||||
|
$W Uptime$dim······$undim: $W$(uptime -p)
|
||||||
|
$W Load$dim········$undim: $G$LOAD1$W (1m), $G$LOAD5$W (5m), $G$LOAD15$W (15m)
|
||||||
|
$W Processes$dim···$undim: $G$PROCESS_ROOT$W (root), $G$PROCESS_USER$W (user), $G$PROCESS_ALL$W (total)
|
||||||
|
$W CPU$dim·········$undim: $W$PROCESSOR_NAME ($G$PROCESSOR_COUNT$W vCPU)
|
||||||
|
$W Memory$dim······$undim: $G$USED$W used, $G$AVAIL$W avail, $G$TOTAL$W total"
|
||||||
|
|
||||||
|
# config
|
||||||
|
max_usage=90
|
||||||
|
bar_width=50
|
||||||
|
|
||||||
|
# disk usage: ignore zfs, squashfs & tmpfs
|
||||||
|
printf "\nDisk usage:\n"
|
||||||
|
|
||||||
|
while read line; do
|
||||||
|
# get disk usage
|
||||||
|
usage=$(echo "$line" | awk '{print $2}' | sed 's/%//')
|
||||||
|
used_width=$((($usage*$bar_width)/100))
|
||||||
|
# color is green if usage < max_usage, else red
|
||||||
|
if [ "${usage}" -ge "${max_usage}" ]; then
|
||||||
|
color=$R
|
||||||
|
else
|
||||||
|
color=$G
|
||||||
|
fi
|
||||||
|
# print green/red bar until used_width
|
||||||
|
bar="[${color}"
|
||||||
|
for ((i=0; i<$used_width; i++)); do
|
||||||
|
bar+="="
|
||||||
|
done
|
||||||
|
# print dimmmed bar until end
|
||||||
|
bar+="${W}${dim}"
|
||||||
|
for ((i=$used_width; i<$bar_width; i++)); do
|
||||||
|
bar+="·"
|
||||||
|
done
|
||||||
|
bar+="${undim}]"
|
||||||
|
# print usage line & bar
|
||||||
|
echo "${line}" | awk '{ printf("%-31s%+3s used out of %+4s\n", $1, $2, $3); }' | sed -e 's/^/ /'
|
||||||
|
echo -e "${bar}" | sed -e 's/^/ /'
|
||||||
|
done < <(df -H -x zfs -x squashfs -x tmpfs -x devtmpfs -x overlay -x nfs -x nfs4 -x cifs --output=target,pcent,size | tail -n+2)
|
||||||
|
|
||||||
|
printf "\n"
|
25
02-prompt/banner
Normal file
25
02-prompt/banner
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
_______ _
|
||||||
|
|__ __| (_)
|
||||||
|
| | __ _ _ __ _ ___
|
||||||
|
| |/ _` | '_ \| / __|
|
||||||
|
| | (_| | |_) | \__ \
|
||||||
|
|_|\__,_| .__/|_|___/
|
||||||
|
_____ | |_ _ __ __ _
|
||||||
|
/ ____| |_(_) | | | \/ | | |
|
||||||
|
| (___ __ _ _ _ __ | |_ __ | \ / | __ _ ___| | ___ _ _
|
||||||
|
\___ \ / _` | | '_ \| __||__|| |\/| |/ _` |/ __| |/ _ \| | | |
|
||||||
|
____) | (_| | | | | | |_ | | | | (_| | (__| | (_) | |_| |
|
||||||
|
|_____/ \__,_|_|_| |_|\__| |_| |_|\__,_|\___|_|\___/ \__,_|
|
||||||
|
|
||||||
|
AVERTISSEMENT : L'accès à ce système est réservé aux utilisateurs
|
||||||
|
dûment autorisés.
|
||||||
|
|
||||||
|
Toute tentative d'accès, d'accès à ce système sans autorisation ou
|
||||||
|
de maintien frauduleux dans ce système fera l'objet de poursuites
|
||||||
|
conformément à la politique de Tapis-Saint-Maclou.
|
||||||
|
|
||||||
|
Tout utilisateur autorisé est informé et reconnaît que ses actions
|
||||||
|
peuvent être enregistrées, conservées et auditées conformément aux
|
||||||
|
chartes/politiques internes de aux chartes/politiques internes de
|
||||||
|
Tapis-Saint-Maclou.
|
7
03-Fail2ban/jail.local
Normal file
7
03-Fail2ban/jail.local
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
[sshd]
|
||||||
|
enabled = true
|
||||||
|
port = 2222
|
||||||
|
filter = sshd
|
||||||
|
logpath = /var/log/auth.log
|
||||||
|
maxretry = 3
|
||||||
|
bantime = 3600
|
2
04-clamav/etc/panw/cortex.conf
Normal file
2
04-clamav/etc/panw/cortex.conf
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
--distribution-id 896dc20f132a45369e53e479b245d244
|
||||||
|
--distribution-server https://distributions.traps.paloaltonetworks.com/
|
44
04-clamav/script.sh
Normal file
44
04-clamav/script.sh
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Pour installer Cortex sur un serveur Debian
|
||||||
|
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
NOCOLOR='\033[0m'
|
||||||
|
|
||||||
|
echo "${YELLOW} ** ${NOCOLOR} Début du script : 03-cortex"
|
||||||
|
echo "${NOCOLOR}"
|
||||||
|
|
||||||
|
echo "${YELLOW} * ${NOCOLOR} Création du dossier"
|
||||||
|
echo "${NOCOLOR}"
|
||||||
|
|
||||||
|
mkdir -p /etc/panw >> /dev/null
|
||||||
|
|
||||||
|
echo "${YELLOW} * ${NOCOLOR} Création du dossier : ${GREEN} OK"
|
||||||
|
echo "${NOCOLOR}"
|
||||||
|
|
||||||
|
echo "${YELLOW} * ${NOCOLOR} Copie du fichier : cortex.conf"
|
||||||
|
echo "${NOCOLOR}"
|
||||||
|
|
||||||
|
cp 03-cortex/etc/panw/cortex.conf /etc/panw/cortex.conf >> /dev/null
|
||||||
|
|
||||||
|
echo "${YELLOW} * ${NOCOLOR} Copie du fichier : cortex.conf : ${GREEN} OK"
|
||||||
|
echo "${NOCOLOR}"
|
||||||
|
|
||||||
|
echo "${YELLOW} * ${NOCOLOR} Installation iptables"
|
||||||
|
echo "${NOCOLOR}"
|
||||||
|
|
||||||
|
apt install -y iptables >> /dev/null
|
||||||
|
|
||||||
|
echo "${YELLOW} * ${NOCOLOR} Installation iptables : ${GREEN} OK"
|
||||||
|
echo "${NOCOLOR}"
|
||||||
|
|
||||||
|
echo "${YELLOW} * ${NOCOLOR} Installation Cortex"
|
||||||
|
echo "${NOCOLOR}"
|
||||||
|
|
||||||
|
dpkg -i 03-cortex/cortex-8.7.0.131661.deb
|
||||||
|
|
||||||
|
echo "${YELLOW} * ${NOCOLOR} Installation Cortex : ${GREEN} OK"
|
||||||
|
echo "${NOCOLOR}"
|
||||||
|
|
||||||
|
echo "${YELLOW} ** ${NOCOLOR} Fin du script : 03-cortex"
|
||||||
|
echo "${NOCOLOR}"
|
36
05-snmp/script.sh
Normal file
36
05-snmp/script.sh
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Pour la configuration SNMP
|
||||||
|
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
NOCOLOR='\033[0m'
|
||||||
|
|
||||||
|
echo "${YELLOW} ** ${NOCOLOR} Début du script : 06-snmp"
|
||||||
|
echo "${NOCOLOR}"
|
||||||
|
|
||||||
|
echo "${YELLOW} * ${NOCOLOR} Installation composant"
|
||||||
|
echo "${NOCOLOR}"
|
||||||
|
|
||||||
|
apt install -y snmp snmpd >> /dev/null
|
||||||
|
|
||||||
|
echo "${YELLOW} * ${NOCOLOR} Installation composant : ${GREEN} OK"
|
||||||
|
echo "${NOCOLOR}"
|
||||||
|
|
||||||
|
echo "${YELLOW} * ${NOCOLOR} Copie du fichier : snmpd.conf"
|
||||||
|
echo "${NOCOLOR}"
|
||||||
|
|
||||||
|
cp 06-snmp/snmpd.conf /etc/snmp/ >> /dev/null
|
||||||
|
|
||||||
|
echo "${YELLOW} * ${NOCOLOR} Copie du fichier : snmpd.conf : ${GREEN} OK"
|
||||||
|
echo "${NOCOLOR}"
|
||||||
|
|
||||||
|
echo "${YELLOW} * ${NOCOLOR} Relance de service"
|
||||||
|
echo "${NOCOLOR}"
|
||||||
|
|
||||||
|
systemctl restart snmpd
|
||||||
|
|
||||||
|
echo "${YELLOW} * ${NOCOLOR} Relance de service : ${GREEN} OK"
|
||||||
|
echo "${NOCOLOR}"
|
||||||
|
|
||||||
|
echo "${YELLOW} ** ${NOCOLOR} Fin du script : 06-snmp"
|
||||||
|
echo "${NOCOLOR}"
|
6
05-snmp/snmpd.conf
Normal file
6
05-snmp/snmpd.conf
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
rocommunity eveagroup 10.78.56.100
|
||||||
|
rocommunity SUP-TSM-PRIV 10.78.56.16
|
||||||
|
rocommunity public 10.78.56.100
|
||||||
|
rocommunity SUP-TSM-PRIV 10.78.56.45
|
||||||
|
|
||||||
|
extend docker /etc/snmp/docker-stats.py
|
562
dsq
Normal file
562
dsq
Normal file
@ -0,0 +1,562 @@
|
|||||||
|
#!/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 "$@"
|
858
script-global.sh
Normal file
858
script-global.sh
Normal file
@ -0,0 +1,858 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Variables Global
|
||||||
|
VERSION="1.2"
|
||||||
|
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")
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[0;33m'
|
||||||
|
BLUE='\[\033[0;34m\]'
|
||||||
|
PINK='\[\033[0;35m\]'
|
||||||
|
NOCOLOR='\033[0m'
|
||||||
|
|
||||||
|
# Fonction pour la présentatation du script
|
||||||
|
start() {
|
||||||
|
echo -e " " | tee -a "$LOG_FILE"
|
||||||
|
echo -e " ############################################################################## " | tee -a "$LOG_FILE"
|
||||||
|
echo -e " # " | tee -a "$LOG_FILE"
|
||||||
|
echo -e " # ██ ██ █████ ██████ ██████ ███████ ███ ██ ██ ███ ██ ██████ " | tee -a "$LOG_FILE"
|
||||||
|
echo -e " # ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██ ██ ████ ██ ██ " | tee -a "$LOG_FILE"
|
||||||
|
echo -e " # ███████ ███████ ██████ ██ ██ █████ ██ ██ ██ ██ ██ ██ ██ ██ ███ " | tee -a "$LOG_FILE"
|
||||||
|
echo -e " # ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ " | tee -a "$LOG_FILE"
|
||||||
|
echo -e " # ██ ██ ██ ██ ██ ██ ██████ ███████ ██ ████ ██ ██ ████ ██████ " | tee -a "$LOG_FILE"
|
||||||
|
echo -e " # " | tee -a "$LOG_FILE"
|
||||||
|
echo -e " # Script de renforcement de la sécurité Linux v$VERSION" | tee -a "$LOG_FILE"
|
||||||
|
echo -e " # " | tee -a "$LOG_FILE"
|
||||||
|
echo -e " ############################################################################## " | tee -a "$LOG_FILE"
|
||||||
|
echo -e " " | tee -a "$LOG_FILE"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fonction pour l'enregistrement des logs
|
||||||
|
log() {
|
||||||
|
local message="${YELLOW} $(date '+%Y-%m-%d %H:%M:%S') ${NOCOLOR} : ${GREEN} $1 ${NOCOLOR}"
|
||||||
|
echo -e "$message" | tee -a "$LOG_FILE"
|
||||||
|
$VERBOSE && echo -e " ${BLUE} * $message"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fonction pour la gestion des warnings
|
||||||
|
handle_warning() {
|
||||||
|
log "${PINK} - Avertissement : $1 ${NOCOLOR}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fonction pour la gestion des erreurs
|
||||||
|
handle_error() {
|
||||||
|
log "${RED} - Erreur : $1 ${NOCOLOR}"
|
||||||
|
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fonction d'installation des paquets
|
||||||
|
install_package() {
|
||||||
|
log "Installion $1 ..."
|
||||||
|
|
||||||
|
DEBIAN_FRONTEND=noninteractive apt install -y "$1" || handle_error "Échec de l'installation $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fonction de sauvegarde des fichiers
|
||||||
|
backup_files() {
|
||||||
|
log "Sauvegarde des fichiers ..."
|
||||||
|
|
||||||
|
mkdir -p "$BACKUP_DIR" || handle_error "Échec de la création du répertoire de sauvegarde"
|
||||||
|
|
||||||
|
local files_to_backup=(
|
||||||
|
"/etc/default/grub"
|
||||||
|
"/etc/ssh/sshd_config"
|
||||||
|
"/etc/ssh/ssh_config"
|
||||||
|
"/etc/snmp/snmpd.conf"
|
||||||
|
"/etc/pam.d/common-password"
|
||||||
|
"/etc/login.defs"
|
||||||
|
"/etc/sysctl.conf"
|
||||||
|
)
|
||||||
|
|
||||||
|
for file in "${files_to_backup[@]}"; do
|
||||||
|
if [ -f "$file" ]; then
|
||||||
|
cp "$file" "$BACKUP_DIR/" || log "Avertissement : Échec de la sauvegarde $file"
|
||||||
|
else
|
||||||
|
log "Avertissement: $file introuvable, sauvegarde ignorée"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
log " * Sauvegarde créée en $BACKUP_DIR"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fonction de restauration à partir d'une sauvegarde
|
||||||
|
restore_backup() {
|
||||||
|
if [ -d "$BACKUP_DIR" ]; then
|
||||||
|
for file in "$BACKUP_DIR"/*; do
|
||||||
|
cp "$file" "$(dirname "$(readlink -f "$file")")" || log "Avertissement : Échec de la restauration $(basename "$file")"
|
||||||
|
done
|
||||||
|
log "Configurations rétablies à partir de $BACKUP_DIR"
|
||||||
|
else
|
||||||
|
log "Répertoire de sauvegarde introuvable. Impossible de restaurer."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fonction d'affichage de l'aide
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fonction d'affichage de la version
|
||||||
|
display_version() {
|
||||||
|
echo "Script de renforcement de la sécurité Linux v$VERSION"
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fonction de vérification des autorisations pour Ubuntu
|
||||||
|
check_permissions() {
|
||||||
|
if [ "$EUID" -ne 0 ]; then
|
||||||
|
echo -e "${RED} * Ce script doit être exécuté avec les privilèges sudo."
|
||||||
|
echo -e "${RED} * Veuillez l'exécuter à nouveau en utilisant : sudo $0"
|
||||||
|
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fonction de controle de la présence d'un proxy web
|
||||||
|
check_proxy() {
|
||||||
|
log "Test présence proxy web ..."
|
||||||
|
|
||||||
|
if apt update > /dev/null 2>&1; then
|
||||||
|
log " * Aucune configuration proxy requise. La mise à jour des paquets a réussi."
|
||||||
|
else
|
||||||
|
log " * Erreur lors de la mise à jour des paquets. Vérification des besoins en proxy web ..."
|
||||||
|
|
||||||
|
# Tester la connectivité Internet
|
||||||
|
if ping -c 1 google.com > /dev/null 2>&1; then
|
||||||
|
log "La connectivité Internet est présente, mais apt ne fonctionne pas. Configuration du proxy requise."
|
||||||
|
|
||||||
|
cp 00-proxy/02proxy /etc/apt/apt.conf.d/02proxy || handle_error "Échec de la copie du fichier de configuration du proxy"
|
||||||
|
|
||||||
|
log " * Configuration du proxy appliquée."
|
||||||
|
handle_warning "Essayez de nouveau la mise à jour des paquets avec 'apt update'."
|
||||||
|
else
|
||||||
|
handle_error "Aucune connectivité Internet. Vérifiez votre connexion réseau."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fonction de vérification des exigences du système
|
||||||
|
check_requirements() {
|
||||||
|
log "Identification du système ..."
|
||||||
|
|
||||||
|
if ! command -v lsb_release &> /dev/null; then
|
||||||
|
handle_error "La commande lsb_release n'a pas été trouvée. Ce script nécessite un système basé sur Ubuntu et Debian."
|
||||||
|
fi
|
||||||
|
|
||||||
|
local os_name=$(lsb_release -si)
|
||||||
|
local os_version=$(lsb_release -sr)
|
||||||
|
|
||||||
|
if [[ "$os_name" != "Ubuntu" && "$os_name" != "Debian" ]]; then
|
||||||
|
handle_error "Ce script est conçu pour les systèmes basés sur Ubuntu ou Debian. OS detecté : $os_name"
|
||||||
|
if [[ $(echo "$os_version < 18.04" | bc) -eq 1 ]]; then
|
||||||
|
handle_error "Ce script nécessite Ubuntu 18.04 ou une version ultérieure. Version detecté : $os_version"
|
||||||
|
elif [[ "$os_name" == "Debian" && $(echo "$os_version < 12.0" | bc) -eq 1 ]]; then
|
||||||
|
handle_error "Ce script nécessite Debian 12.0 ou une version ultérieure. Version detecté : $os_version"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
log " * La vérification de la configuration requise a été effectuée. OS: $os_name VERSION: $os_version"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fonction de mise à jour du système
|
||||||
|
update_system() {
|
||||||
|
log "Mise à jour du système ..."
|
||||||
|
|
||||||
|
# Mise à jour de la liste des paquets
|
||||||
|
apt update -y || handle_error "Échec de la mise à jour du système"
|
||||||
|
|
||||||
|
# Mise à niveau du système
|
||||||
|
DEBIAN_FRONTEND=noninteractive apt full-upgrade -y || handle_error "Échec de la mise à niveau du système"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fonction de mise en place de clé SSH
|
||||||
|
setup_ssh() {
|
||||||
|
log "Installation et configuration des clés SSH ..."
|
||||||
|
|
||||||
|
# Demande à l'utilisateur s'il souhaite appliquer les clé SSH
|
||||||
|
local apply_key_ssh
|
||||||
|
read -p "Voulez-vous appliquer les clé SSH ? (y/N): " apply_key_ssh
|
||||||
|
|
||||||
|
#
|
||||||
|
case $apply_key_ssh in
|
||||||
|
[Yy]* )
|
||||||
|
log "Application des clé ssh ..."
|
||||||
|
|
||||||
|
# Copie du fichier des clés SSH
|
||||||
|
cp 01-key/authorized_keys /root/.ssh/authorized_keys || handle_error "Échec de la copie de authorized_keys"
|
||||||
|
|
||||||
|
# Mise en place des droits
|
||||||
|
chmod 600 /root/.ssh/authorized_keys || handle_error "Échec de la mise en place des droits sur le fichier authorized_keys"
|
||||||
|
chmod 700 /root/.ssh || handle_error "Échec de la mise en place des droits sur le répertoire .ssh"
|
||||||
|
|
||||||
|
# Création du répertoire authorized_keys
|
||||||
|
mkdir -p /etc/ssh/authorized_keys/ || handle_error "Échec de la création du répertoire authorized_keys"
|
||||||
|
|
||||||
|
cd /etc/ssh/authorized_keys/ >> /dev/null
|
||||||
|
|
||||||
|
# Création du lien symbolique
|
||||||
|
ln -s /root/.ssh/authorized_keys root || handle_error "Échec de la création du lien symbolique"
|
||||||
|
|
||||||
|
#
|
||||||
|
local file="/etc/ssh/sshd_config"
|
||||||
|
local line=`grep -n "^.*AuthorizedKeysFile.*authorized_keys.*" $file | cut -d ":" -f 1`
|
||||||
|
|
||||||
|
#echo $line
|
||||||
|
|
||||||
|
# Vérification de la présence de la ligne AuthorizedKeysFile
|
||||||
|
if [ -z "$line" ]; then
|
||||||
|
echo "AuthorizedKeysFile .ssh/authorized_keys" | tee -a $file
|
||||||
|
else
|
||||||
|
sed -i ''$line'c\AuthorizedKeysFile .ssh/authorized_keys' $file > /dev/null || handle_error "Échec de "
|
||||||
|
fi
|
||||||
|
|
||||||
|
#
|
||||||
|
line=`grep -n "^.*AuthorizedKeysFile.*authorized_keys.*" $file | cut -d ":" -f 1` || handle_error "Échec de "
|
||||||
|
|
||||||
|
# Redémarrage du service sshd
|
||||||
|
systemctl restart sshd || handle_error "Échec du redémarrage du service SSH"
|
||||||
|
|
||||||
|
log " * Mise en place de clé SSH "
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
log " * Sauter la mise en place de clé SSH"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fonction de configuration du prompt de connexion
|
||||||
|
setup_prompt() {
|
||||||
|
log "Installation et configuration du prompt de connexion ..."
|
||||||
|
|
||||||
|
# Demande à l'utilisateur s'il souhaite appliquer le prompt de connexion
|
||||||
|
local apply_prompt
|
||||||
|
read -p "Voulez-vous appliquer le prompt de connexion ? (y/N): " apply_prompt
|
||||||
|
|
||||||
|
#
|
||||||
|
case $apply_prompt in
|
||||||
|
[Yy]* )
|
||||||
|
log "Application du prompt ..."
|
||||||
|
|
||||||
|
# Copie des fichiers de configuration
|
||||||
|
cp 02-prompt/banner /etc/banner || handle_error "Échec de la copie de banner"
|
||||||
|
cp 02-prompt/00-basic /etc/update-motd.d/00-basic || handle_error "Échec de la copie de 00-basic"
|
||||||
|
|
||||||
|
# Mise en place des droits
|
||||||
|
chmod +x /etc/update-motd.d/00-basic || handle_error "Échec de la mise en place des droits sur 00-basic"
|
||||||
|
|
||||||
|
# Redémarrage du service sshd
|
||||||
|
systemctl restart sshd >> /dev/null
|
||||||
|
|
||||||
|
log " * Mise en place du prompt de connexion"
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
log " * Sauter la mise en place du prompt de connexion"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fonction de configuration du pare-feu
|
||||||
|
setup_firewall() {
|
||||||
|
log "Installation et configuration du pare-feu ..."
|
||||||
|
|
||||||
|
# Demande à l'utilisateur s'il souhaite appliquer le prompt de connexion
|
||||||
|
local apply_firewall
|
||||||
|
read -p "Voulez-vous appliquer la configuration firewall ? (y/N): " apply_firewall
|
||||||
|
|
||||||
|
#
|
||||||
|
case $apply_firewall in
|
||||||
|
[Yy]* )
|
||||||
|
log "Application du prompt ..."
|
||||||
|
|
||||||
|
# Vérification de la présence de UFW
|
||||||
|
install_package "ufw"
|
||||||
|
|
||||||
|
# Vérification de la présence de iptables
|
||||||
|
ufw default deny incoming || handle_error "Échec de la définition de la politique de réception par défaut de l'UFW"
|
||||||
|
ufw default allow outgoing || handle_error "Échec de la définition de la politique de sortie par défaut de l'UFW"
|
||||||
|
ufw limit ssh comment 'Allow SSH with rate limiting' || handle_error "Échec de la configuration de SSH dans UFW"
|
||||||
|
ufw allow 80/tcp comment 'Allow HTTP' || handle_error "Échec de l'autorisation de HTTP dans l'UFW"
|
||||||
|
ufw allow 443/tcp comment 'Allow HTTPS' || handle_error "Échec de l'autorisation de HTTPS dans l'UFW"
|
||||||
|
ufw allow 22/tcp comment 'Allow HTTPS' || handle_error "Échec de l'autorisation de SSH dans l'UFW"
|
||||||
|
|
||||||
|
# Demande à l'utilisateur s'il souhaite appliquer des règles de pare-feu spécifiques à IPv6
|
||||||
|
local apply_ipv6_rules
|
||||||
|
read -p "Voulez-vous appliquer des règles de pare-feu spécifiques à IPv6 ? (y/N): " apply_ipv6_rules
|
||||||
|
|
||||||
|
# Application des règles de pare-feu spécifiques à IPv6
|
||||||
|
case $apply_ipv6_rules in
|
||||||
|
[Yy]* )
|
||||||
|
log "Application de règles de pare-feu spécifiques à IPv6 ..."
|
||||||
|
|
||||||
|
ufw allow in on lo || handle_error "Échec de l'autorisation du trafic de bouclage"
|
||||||
|
ufw allow out on lo || handle_error "Échec de l'autorisation du trafic de bouclage"
|
||||||
|
ufw deny in from ::/0 || handle_error "Échec du refus de l'ensemble du trafic IPv6 entrant"
|
||||||
|
ufw allow out to ::/0 || handle_error "Échec de l'autorisation de tout le trafic IPv6 sortant"
|
||||||
|
|
||||||
|
log "Règles de pare-feu IPv6 appliquées"
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
log "Sauter les règles de pare-feu spécifiques à IPv6"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Activation de la journalisation UFW
|
||||||
|
ufw logging on || handle_error "Échec de l'activation de la journalisation UFW"
|
||||||
|
ufw --force enable || handle_error "Échec de l'activation de l'UFW"
|
||||||
|
|
||||||
|
log " * Pare-feu configuré et activé"
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
log " * Sauter la mise en place du pare-feu"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fonction de configuration de Fail2Ban
|
||||||
|
setup_fail2ban() {
|
||||||
|
log "Installation et configuration de Fail2Ban ..."
|
||||||
|
|
||||||
|
# Demande à l'utilisateur s'il souhaite installer Fail2Ban
|
||||||
|
local apply_fail2ban
|
||||||
|
read -p "Voulez-vous appliquer la configuration Fail2Ban ? (y/N): " apply_fail2ban
|
||||||
|
|
||||||
|
#
|
||||||
|
case $apply_fail2ban in
|
||||||
|
[Yy]* )
|
||||||
|
# Vérification de la présence de Fail2Ban
|
||||||
|
install_package "fail2ban"
|
||||||
|
|
||||||
|
# Copie de la configuration locale de Fail2Ban
|
||||||
|
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local || handle_error "Échec de la création de la configuration locale de Fail2Ban"
|
||||||
|
cp 03-Fail2ban/etc/fail2ban/jail.conf /etc/fail2ban/jail.d/ || handle_error "Échec de la ccopie des configurations Fail2Ban"
|
||||||
|
|
||||||
|
# Configuration de Fail2Ban
|
||||||
|
sed -i 's/bantime = 10m/bantime = 1h/' /etc/fail2ban/jail.local || handle_error "Échec de la mise en place de Fail2Ban bantime"
|
||||||
|
sed -i 's/maxretry = 5/maxretry = 3/' /etc/fail2ban/jail.local || handle_error "Échec de la définition de Fail2Ban maxretry"
|
||||||
|
|
||||||
|
#
|
||||||
|
systemctl enable fail2ban || handle_error "Échec de l'activation du service Fail2Ban"
|
||||||
|
systemctl start fail2ban || handle_error "Échec du démarrage du service Fail2Ban"
|
||||||
|
|
||||||
|
log "Fail2Ban configuré et démarré"
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
log " * Sauter de l'installation de fail2ban"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fonction de configuration de ClamAV
|
||||||
|
setup_clamav() {
|
||||||
|
log "Installation et mise à jour de ClamAV ..."
|
||||||
|
|
||||||
|
# Demande à l'utilisateur s'il souhaite installer ClamAV
|
||||||
|
local apply_clamav
|
||||||
|
read -p "Voulez-vous appliquer la configuration firewall ? (y/N): " apply_clamav
|
||||||
|
|
||||||
|
#
|
||||||
|
case $apply_clamav in
|
||||||
|
[Yy]* )
|
||||||
|
# Vérification de la présence de ClamAV
|
||||||
|
install_package "clamav"
|
||||||
|
install_package "clamav-daemon"
|
||||||
|
|
||||||
|
# Vérification de la présence de Freshclam
|
||||||
|
systemctl stop clamav-freshclam || log "Avertissement : Échec de l'arrêt de clamav-freshclam"
|
||||||
|
freshclam || log "Avertissement : La mise à jour de la base de données de ClamAV a échoué"
|
||||||
|
|
||||||
|
# Configuration de Freshclam
|
||||||
|
systemctl start clamav-freshclam || handle_error "Échec du démarrage de clamav-freshclam"
|
||||||
|
systemctl enable clamav-freshclam || handle_error "Échec de l'activation de clamav-freshclam"
|
||||||
|
|
||||||
|
log "ClamAV installé et mis à jour"
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
log " * Sauter de l'installation de ClamAV"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fonction de configuration de SNMP
|
||||||
|
setup_snmp() {
|
||||||
|
log "Installation et configuration de SNMP ..."
|
||||||
|
|
||||||
|
# Demande à l'utilisateur s'il souhaite installer SNMP
|
||||||
|
local apply_snmp
|
||||||
|
read -p "Voulez-vous appliquer la configuration SNMP ? (y/N): " apply_snmp
|
||||||
|
|
||||||
|
#
|
||||||
|
case $apply_snmp in
|
||||||
|
[Yy]* )
|
||||||
|
# Vérification de la présence de SNMP
|
||||||
|
install_package "snmpd"
|
||||||
|
install_package "snmp"
|
||||||
|
|
||||||
|
# Copie de la configuration SNMP
|
||||||
|
cp 05-snmp/snmpd.conf /etc/snmp/snmpd.conf >> /dev/null
|
||||||
|
|
||||||
|
systemctl reload daemon
|
||||||
|
|
||||||
|
systemctl enable snmpd || handle_error "Échec de l'activation du service SNMP"
|
||||||
|
systemctl start snmpd || handle_error "Échec du démarrage du service SNMP"
|
||||||
|
|
||||||
|
log "SNMP installé et configuré"
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
log " * Sauter de l'installation de SNMP"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fonction permettant de désactiver l'accès à la racine
|
||||||
|
disable_root() {
|
||||||
|
log "Vérification de la présence d'utilisateurs non root ayant des privilèges sudo ..."
|
||||||
|
|
||||||
|
# Obtenir la liste des utilisateurs ayant des privilèges sudo
|
||||||
|
sudo_users=$(getent group sudo | cut -d: -f4 | tr ',' '\n' | grep -v "^root$")
|
||||||
|
|
||||||
|
# Vérifier s'il y a des utilisateurs non root avec des privilèges sudo
|
||||||
|
if [ -z "$sudo_users" ]; then
|
||||||
|
log "Attention : Aucun utilisateur non-root avec des privilèges sudo n'a été trouvé. Sauter la désactivation de la connexion root pour plus de sécurité."
|
||||||
|
|
||||||
|
echo "Veuillez créer un utilisateur non root avec les privilèges sudo avant de désactiver la connexion root."
|
||||||
|
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Des utilisateurs non root avec des privilèges sudo ont été trouvés. Procédure de désactivation de l'accès à la racine ..."
|
||||||
|
|
||||||
|
# Désactiver l'accès à root
|
||||||
|
if passwd -l root; then
|
||||||
|
log "La connexion à root a été désactivée avec succès."
|
||||||
|
else
|
||||||
|
handle_error "Échec du verrouillage du compte root"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Désactiver la connexion SSH de root à titre de précaution supplémentaire
|
||||||
|
if grep -q "^PermitRootLogin" /etc/ssh/sshd_config; then
|
||||||
|
sed -i 's/^#PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config || handle_error "Échec de la désactivation de la connexion SSH de root dans sshd_config"
|
||||||
|
else
|
||||||
|
echo "PermitRootLogin no" | tee -a /etc/ssh/sshd_config > /dev/null || handle_error "Échec de l'ajout de PermitRootLogin no à sshd_config"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Redémarrer le service SSH pour appliquer les changements
|
||||||
|
systemctl reload daemon
|
||||||
|
|
||||||
|
systemctl restart sshd || handle_error "Échec du redémarrage du service SSH"
|
||||||
|
|
||||||
|
log "La connexion de root a été désactivée et la connexion à root par SSH a été explicitement interdite."
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fonction de suppression des paquets inutiles
|
||||||
|
remove_packages() {
|
||||||
|
log "Suppression des paquets inutiles ..."
|
||||||
|
|
||||||
|
DEBIAN_FRONTEND=noninteractive apt remove --purge -y telnetd nis yp-tools rsh-client rsh-redone-client xinetd || log "Avertissement : Échec de la suppression de certains paquets"
|
||||||
|
apt autoremove -y || log "Avertissement : échec de l'autoremove"
|
||||||
|
|
||||||
|
log "Suppression des paquets inutiles"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fonction de mise en place de l'audit
|
||||||
|
setup_audit() {
|
||||||
|
log "Configuration des règles d'audit ..."
|
||||||
|
|
||||||
|
# Vérification de la présence d'auditd
|
||||||
|
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" | tee -a /etc/audit/rules.d/audit.rules > /dev/null || handle_error "Échec de l'ajout d'une règle d'audit : $rule"
|
||||||
|
done
|
||||||
|
|
||||||
|
systemctl enable auditd || handle_error "Échec de l'activation du service auditd"
|
||||||
|
systemctl start auditd || handle_error "Échec du démarrage du service auditd"
|
||||||
|
|
||||||
|
log "Règles d'audit configurées et auditd démarré"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fonction permettant de désactiver les systèmes de fichiers inutilisés
|
||||||
|
disable_filesystems() {
|
||||||
|
log "Désactivation des systèmes de fichiers inutilisés ..."
|
||||||
|
|
||||||
|
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 "Échec de la désactivation du système de fichiers : $fs"
|
||||||
|
done
|
||||||
|
|
||||||
|
log "Systèmes de fichiers inutilisés désactivés"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fonction de sécurisation des paramètres de démarrage
|
||||||
|
secure_boot() {
|
||||||
|
log "Sécurisation des paramètres de démarrage ..."
|
||||||
|
|
||||||
|
# Fichier de configuration GRUB sécurisé
|
||||||
|
if [ -f /boot/grub/grub.cfg ]; then
|
||||||
|
chown root:root /boot/grub/grub.cfg || handle_error "Échec du changement de propriétaire de grub.cfg"
|
||||||
|
chmod 600 /boot/grub/grub.cfg || handle_error "Échec de la modification des permissions de grub.cfg"
|
||||||
|
|
||||||
|
log "Fichier de configuration GRUB sécurisé"
|
||||||
|
else
|
||||||
|
log "Avertissement : /boot/grub/grub.cfg n'a pas été trouvé. Ignorer les permissions du fichier GRUB."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Modifier les paramètres du noyau
|
||||||
|
if [ -f /etc/default/grub ]; then
|
||||||
|
# Sauvegarde du fichier original
|
||||||
|
cp /etc/default/grub /etc/default/grub.bak || handle_error "Échec de la sauvegarde du fichier grub"
|
||||||
|
|
||||||
|
# Ajouter ou modifier les paramètres du noyau
|
||||||
|
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"
|
||||||
|
|
||||||
|
# Demande si l'utilisateur souhaite désactiver SACK
|
||||||
|
local disable_sack
|
||||||
|
|
||||||
|
read -p "Voulez-vous désactiver TCP SACK ? Ce n'est généralement pas recommandé. (y/N): " disable_sack
|
||||||
|
|
||||||
|
case $disable_sack in
|
||||||
|
[Yy]* )
|
||||||
|
kernel_params+=" net.ipv4.tcp_sack=0"
|
||||||
|
|
||||||
|
log "TCP SACK sera désactivée"
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
log "TCP SACK restera activée"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
sed -i "s/GRUB_CMDLINE_LINUX=\"\"/GRUB_CMDLINE_LINUX=\"$kernel_params\"/" /etc/default/grub || handle_error "Échec de la modification des paramètres du noyau"
|
||||||
|
|
||||||
|
# Update GRUB
|
||||||
|
if command -v update-grub &> /dev/null; then
|
||||||
|
update-grub || handle_error "Échec de la mise à jour du GRUB"
|
||||||
|
elif command -v grub2-mkconfig &> /dev/null; then
|
||||||
|
grub2-mkconfig -o /boot/grub2/grub.cfg || handle_error "Échec de la mise à jour du GRUB"
|
||||||
|
else
|
||||||
|
log "Avertissement : Ni update-grub ni grub2-mkconfig n'ont été trouvés. Veuillez mettre à jour GRUB manuellement."
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Mise à jour des paramètres du noyau"
|
||||||
|
else
|
||||||
|
log "Avertissement : /etc/default/grub n'a pas été trouvé. Sauter les modifications des paramètres du noyau."
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Paramètres de démarrage sécurisés"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fonction de configuration d'IPv6
|
||||||
|
configure_ipv6() {
|
||||||
|
local disable_ipv6
|
||||||
|
|
||||||
|
read -p "Voulez-vous désactiver IPv6 ? (y/N): " disable_ipv6
|
||||||
|
|
||||||
|
case $disable_ipv6 in
|
||||||
|
[Yy]* )
|
||||||
|
log "Désactivation IPv6 ..."
|
||||||
|
echo "net.ipv6.conf.all.disable_ipv6 = 1" | tee -a /etc/sysctl.conf || handle_error "Échec de la désactivation d'IPv6 (all)"
|
||||||
|
echo "net.ipv6.conf.default.disable_ipv6 = 1" | tee -a /etc/sysctl.conf || handle_error "Échec de la désactivation d'IPv6 (default)"
|
||||||
|
echo "net.ipv6.conf.lo.disable_ipv6 = 1" | tee -a /etc/sysctl.conf || handle_error "Échec de la désactivation d'IPv6 (lo)"
|
||||||
|
|
||||||
|
sysctl -p || handle_error "Échec de l'application des changements sysctl"
|
||||||
|
|
||||||
|
log "IPv6 a été désactivé"
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
log "IPv6 reste activé"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fonction de configuration d'AppArmor
|
||||||
|
setup_apparmor() {
|
||||||
|
log "Configuration d'AppArmor ..."
|
||||||
|
|
||||||
|
if ! command -v apparmor_status &> /dev/null; then
|
||||||
|
install_package "apparmor"
|
||||||
|
install_package "apparmor-utils"
|
||||||
|
else
|
||||||
|
log "AppArmor est déjà installé. Sauter l'installation."
|
||||||
|
fi
|
||||||
|
|
||||||
|
systemctl reload daemon
|
||||||
|
|
||||||
|
systemctl enable apparmor || handle_error "Échec de l'activation du service AppArmor"
|
||||||
|
systemctl start apparmor || handle_error "Échec du démarrage du service AppArmor"
|
||||||
|
|
||||||
|
aa-enforce /etc/apparmor.d/* || log "Avertissement : Échec de l'application de certains profils AppArmor"
|
||||||
|
|
||||||
|
log "L'installation d'AppArmor est terminée. Tous les profils sont en mode exécution."
|
||||||
|
log "Moniteur /var/log/syslog and /var/log/auth.log pour tout problème lié à AppArmor."
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fonction de configuration de NTP
|
||||||
|
setup_ntp() {
|
||||||
|
log "Configuration de la synchronisation de l'heure ..."
|
||||||
|
|
||||||
|
# Vérifier si systemd-timesyncd est disponible (systèmes Ubuntu modernes)
|
||||||
|
if systemctl list-unit-files | grep -q systemd-timesyncd.service; then
|
||||||
|
log "Utilisation de systemd-timesyncd pour la synchronisation temporelle"
|
||||||
|
|
||||||
|
systemctl reload daemon
|
||||||
|
|
||||||
|
systemctl enable systemd-timesyncd.service || handle_error "Échec de l'activation du service systemd-timesyncd"
|
||||||
|
systemctl start systemd-timesyncd.service || handle_error "Échec du démarrage du service systemd-timesyncd"
|
||||||
|
|
||||||
|
log "systemd-timesyncd installation terminée"
|
||||||
|
else
|
||||||
|
# Revenir au protocole NTP traditionnel si systemd-timesyncd n'est pas disponible
|
||||||
|
log "Utilisation du protocole NTP traditionnel pour la synchronisation du temps"
|
||||||
|
|
||||||
|
install_package "ntp"
|
||||||
|
|
||||||
|
systemctl reload daemon
|
||||||
|
|
||||||
|
systemctl enable ntp || handle_error "Échec de l'activation du service NTP"
|
||||||
|
systemctl start ntp || handle_error "Échec du démarrage du service NTP"
|
||||||
|
|
||||||
|
log "Configuration NTP terminée"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fonction de configuration de l'AIDE
|
||||||
|
setup_aide() {
|
||||||
|
log "Mise en place d'AIDE ..."
|
||||||
|
|
||||||
|
install_package "aide"
|
||||||
|
|
||||||
|
aideinit || handle_error "Échec de l'initialisation de la base de données AIDE"
|
||||||
|
mv /var/lib/aide/aide.db.new /var/lib/aide/aide.db || handle_error "Échec du transfert de la base de données AIDE"
|
||||||
|
|
||||||
|
log "L'installation d'AIDE est terminée et la base de données a été initialisée."
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fonction de configuration de sysctl
|
||||||
|
configure_sysctl() {
|
||||||
|
log "Configuration des paramètres sysctl ..."
|
||||||
|
|
||||||
|
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 "Échec de la mise à jour sysctl.conf"
|
||||||
|
sysctl -p || handle_error "Échec de l'application des changements sysctl"
|
||||||
|
|
||||||
|
log "Paramètres sysctl configurés"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fonction pour des mesures de sécurité supplémentaires
|
||||||
|
additional_security() {
|
||||||
|
log "Appliquer des mesures de sécurité supplémentaires ..."
|
||||||
|
|
||||||
|
# Désactiver les vidages de noyau
|
||||||
|
echo "* hard core 0" | sudo tee -a /etc/security/limits.conf || handle_error "Échec de la désactivation des vidages de noyau"
|
||||||
|
|
||||||
|
# Définir des autorisations appropriées pour les fichiers sensibles
|
||||||
|
chmod 600 /etc/shadow || handle_error "Échec de la définition des autorisations sur /etc/shadow"
|
||||||
|
chmod 600 /etc/gshadow || handle_error "Échec de la définition des autorisations sur /etc/gshadow"
|
||||||
|
|
||||||
|
# Permettre la comptabilisation des processus
|
||||||
|
install_package "acct"
|
||||||
|
|
||||||
|
/usr/sbin/accton on || handle_error "Échec de l'activation de la comptabilité des processus"
|
||||||
|
|
||||||
|
# Restreindre SSH
|
||||||
|
sed -i 's/^#PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config || handle_error "Échec de la désactivation de la connexion root via SSH"
|
||||||
|
sed -i 's/^#PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config || handle_error "Échec de la désactivation de l'authentification par mot de passe pour SSH"
|
||||||
|
sed -i 's/^#Protocol.*/Protocol 2/' /etc/ssh/sshd_config || handle_error "Échec de la définition de la version du protocole SSH"
|
||||||
|
|
||||||
|
systemctl reload daemon
|
||||||
|
|
||||||
|
systemctl restart sshd || handle_error "Échec du redémarrage du service SSH"
|
||||||
|
|
||||||
|
# Configurer une politique de mot de passe fort
|
||||||
|
sed -i 's/PASS_MAX_DAYS\t99999/PASS_MAX_DAYS\t90/' /etc/login.defs || handle_error "Échec de la définition du nombre maximal de jours pour le mot de passe"
|
||||||
|
sed -i 's/PASS_MIN_DAYS\t0/PASS_MIN_DAYS\t7/' /etc/login.defs || handle_error "Échec de la définition du mot de passe (nombre de jours minimum)"
|
||||||
|
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 "Échec de la configuration de la politique de mot de passe"
|
||||||
|
|
||||||
|
log "Mesures de sécurité supplémentaires appliquées"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fonction de mise à jour automatique
|
||||||
|
setup_automatic_updates() {
|
||||||
|
log "Mise en place de mises à jour de sécurité automatiques ..."
|
||||||
|
|
||||||
|
install_package "unattended-upgrades"
|
||||||
|
|
||||||
|
dpkg-reconfigure -plow unattended-upgrades || handle_error "Échec de la configuration des mises à jour sans surveillance"
|
||||||
|
|
||||||
|
log "Configuration des mises à jour de sécurité automatiques"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fonction principale
|
||||||
|
main() {
|
||||||
|
local dry_run=false
|
||||||
|
|
||||||
|
# Analyse des arguments de la ligne de commande
|
||||||
|
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 "Option inconnue : $1"
|
||||||
|
display_help
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
start
|
||||||
|
check_permissions
|
||||||
|
check_proxy
|
||||||
|
check_requirements
|
||||||
|
backup_files
|
||||||
|
|
||||||
|
if $dry_run; then
|
||||||
|
log "Exécution d'un 'dry run'. Aucune modification ne sera apportée."
|
||||||
|
else
|
||||||
|
update_system
|
||||||
|
setup_ssh
|
||||||
|
setup_prompt
|
||||||
|
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 "Configuration de la sécurité renforcée exécutée !!!"
|
||||||
|
log "Script by Tips-Of-Mine"
|
||||||
|
|
||||||
|
if ! $dry_run; then
|
||||||
|
# Demander à l'utilisateur s'il souhaite redémarrer
|
||||||
|
read -p "Voulez-vous redémarrer le système maintenant pour appliquer tous les changements ? (y/N): " restart_now
|
||||||
|
case $restart_now in
|
||||||
|
[Yy]* )
|
||||||
|
log "Redémarrage du système ..."
|
||||||
|
|
||||||
|
reboot
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
log "Veuillez redémarrer votre système manuellement pour appliquer tous les changements."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Exécuter la fonction principale
|
||||||
|
main "$@"
|
@ -11,7 +11,7 @@ echo "${NOCOLOR}"
|
|||||||
|
|
||||||
chmod +x ./01-ssh/script.sh >> /dev/null
|
chmod +x ./01-ssh/script.sh >> /dev/null
|
||||||
chmod +x ./02-apt/script.sh >> /dev/null
|
chmod +x ./02-apt/script.sh >> /dev/null
|
||||||
chmod +x ./03-cortex/script.sh >> /dev/null
|
chmod +x ./03-antivirus/script.sh >> /dev/null
|
||||||
chmod +x ./04-agent-glpi/script.sh >> /dev/null
|
chmod +x ./04-agent-glpi/script.sh >> /dev/null
|
||||||
chmod +x ./05-manageengine/script.sh >> /dev/null
|
chmod +x ./05-manageengine/script.sh >> /dev/null
|
||||||
chmod +x ./06-snmp/script.sh >> /dev/null
|
chmod +x ./06-snmp/script.sh >> /dev/null
|
||||||
@ -41,12 +41,12 @@ echo "${NOCOLOR}"
|
|||||||
echo "${YELLOW} *** ${NOCOLOR} Fin du script : APT : ${GREEN} OK"
|
echo "${YELLOW} *** ${NOCOLOR} Fin du script : APT : ${GREEN} OK"
|
||||||
echo "${NOCOLOR}"
|
echo "${NOCOLOR}"
|
||||||
|
|
||||||
echo "${YELLOW} *** ${NOCOLOR} Lancement du script : Cortex"
|
echo "${YELLOW} *** ${NOCOLOR} Lancement du script : Antivirus"
|
||||||
echo "${NOCOLOR}"
|
echo "${NOCOLOR}"
|
||||||
|
|
||||||
./03-cortex/script.sh
|
./03-antivirus/script.sh
|
||||||
|
|
||||||
echo "${YELLOW} *** ${NOCOLOR} Fin du script : Cortex : ${GREEN} OK"
|
echo "${YELLOW} *** ${NOCOLOR} Fin du script : Antivirus : ${GREEN} OK"
|
||||||
echo "${NOCOLOR}"
|
echo "${NOCOLOR}"
|
||||||
|
|
||||||
echo "${YELLOW} *** ${NOCOLOR} Lancement du script : GLPI"
|
echo "${YELLOW} *** ${NOCOLOR} Lancement du script : GLPI"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user