Fix: permissions and ACLs for www-data on /etc/asterisk, fail2ban filters and logs, and AMI diagnostics loading

This commit is contained in:
sorcier committed 2026-11-02 04:12:29 +01:00
1 parent 563a01e3c3
commit cbc9fe7f29
4 files changed
+93 -20

No files matched your search

+67 -16
View File
@@ -57,7 +57,8 @@ apt-get install -y --no-install-recommends \
openssl \
ca-certificates \
iptables \
iptables-persistent
iptables-persistent \
acl
# Vérification et installation d'Asterisk
echo -e "${C_GREEN} -> Installation du moteur Asterisk PBX...${C_RESET}"
@@ -156,8 +157,13 @@ mkdir -p /var/spool/asterisk/voicemail/default
mkdir -p /var/log/asterisk
mkdir -p /var/log/nexus-pbx
touch /var/log/asterisk/messages
chown asterisk:asterisk /var/log/asterisk/messages 2>/dev/null || true
touch /var/log/asterisk/messages /var/log/asterisk/security.log
chown asterisk:asterisk /var/log/asterisk/messages /var/log/asterisk/security.log 2>/dev/null || true
chmod 0664 /var/log/asterisk/messages /var/log/asterisk/security.log 2>/dev/null || true
touch /var/log/nexus_security.log
chown www-data:asterisk /var/log/nexus_security.log 2>/dev/null || true
chmod 0664 /var/log/nexus_security.log 2>/dev/null || true
# Droits applicatifs stricts
chown -R www-data:asterisk "$TARGET_DIR"
@@ -168,8 +174,11 @@ chmod 2775 "$TARGET_DIR/storage" \
"$TARGET_DIR/public/avatars"
chown -R asterisk:asterisk /etc/asterisk /var/lib/asterisk /var/spool/asterisk /var/log/asterisk
chmod -R 775 /etc/asterisk
chmod 2775 /etc/asterisk
chmod 2750 /etc/asterisk/keys
setfacl -R -m u:www-data:rwx,g:asterisk:rwx /etc/asterisk 2>/dev/null || true
setfacl -R -d -m u:www-data:rwx,g:asterisk:rwx /etc/asterisk 2>/dev/null || true
# Droits sudoers pour l'interface web (www-data)
cat << 'EOF' > /etc/sudoers.d/nexus-pbx
@@ -194,6 +203,8 @@ timestampevents = yes
secret = AsteriskAmi2026!
deny = 0.0.0.0/0.0.0.0
permit = 127.0.0.1/255.255.255.0
permit = 127.0.0.1/32
permit = ::1/128
read = all
write = all
EOF
@@ -201,7 +212,6 @@ chown asterisk:asterisk /etc/asterisk/manager.conf
chmod 0640 /etc/asterisk/manager.conf
# Fichier de logs pour Fail2ban
if [ ! -f /etc/asterisk/logger.conf ] || ! grep -q 'security' /etc/asterisk/logger.conf 2>/dev/null; then
cat << 'EOF' > /etc/asterisk/logger.conf
[general]
dateformat=%F %T
@@ -209,10 +219,10 @@ dateformat=%F %T
[logfiles]
console => notice,warning,error
messages => notice,warning,error,security
security.log => security
EOF
chown asterisk:asterisk /etc/asterisk/logger.conf 2>/dev/null || true
chmod 0644 /etc/asterisk/logger.conf 2>/dev/null || true
fi
chmod 0664 /etc/asterisk/logger.conf 2>/dev/null || true
# Certificat TLS auto-signé initial pour PJSIP TLS (port 5061) et Nginx HTTPS (port 8443)
if [ ! -f /etc/asterisk/keys/asterisk.crt ] || [ ! -f /etc/asterisk/keys/asterisk.key ]; then
@@ -230,18 +240,32 @@ fi
chown asterisk:asterisk /etc/asterisk/keys/* 2>/dev/null || true
chmod 0640 /etc/asterisk/keys/* 2>/dev/null || true
# Inclusions custom dans Asterisk
touch /etc/asterisk/pjsip.conf /etc/asterisk/extensions.conf
touch /etc/asterisk/pjsip.custom.conf /etc/asterisk/extensions.custom.conf
# Inclusions custom dans Asterisk & initialisation des fichiers cibles
touch /etc/asterisk/pjsip.conf \
/etc/asterisk/pjsip.custom.conf \
/etc/asterisk/extensions.conf \
/etc/asterisk/extensions.custom.conf \
/etc/asterisk/musiconhold.custom.conf \
/etc/asterisk/voicemail.custom.conf \
/etc/asterisk/rtp.conf \
/etc/asterisk/features.conf
if ! grep -q 'pjsip.custom.conf' /etc/asterisk/pjsip.conf 2>/dev/null; then
printf '\n#tryinclude "pjsip.custom.conf"\n' >> /etc/asterisk/pjsip.conf
fi
if ! grep -q 'extensions.custom.conf' /etc/asterisk/extensions.conf 2>/dev/null; then
printf '\n#tryinclude "extensions.custom.conf"\n' >> /etc/asterisk/extensions.conf
fi
chown asterisk:asterisk /etc/asterisk/pjsip* /etc/asterisk/extensions* 2>/dev/null || true
chmod 0664 /etc/asterisk/pjsip.conf /etc/asterisk/extensions.conf 2>/dev/null || true
chmod 0660 /etc/asterisk/*.custom.conf 2>/dev/null || true
chown -R asterisk:asterisk /etc/asterisk
chmod 0664 /etc/asterisk/*.conf /etc/asterisk/*.custom.conf 2>/dev/null || true
chmod 2750 /etc/asterisk/keys
chmod 2775 /etc/asterisk
setfacl -R -m u:www-data:rwx,g:asterisk:rwx /etc/asterisk 2>/dev/null || true
setfacl -R -d -m u:www-data:rwx,g:asterisk:rwx /etc/asterisk 2>/dev/null || true
# Rechargement Asterisk immédiat pour appliquer AMI et Logger
asterisk -rx "core reload" 2>/dev/null || true
asterisk -rx "manager reload" 2>/dev/null || true
# 6. Initialisation de la Base de données SQLite & Configuration initiale
echo -e "${C_GREEN}[5/8] Initialisation de la base SQLite et configuration NexusPBX...${C_RESET}"
@@ -318,13 +342,21 @@ $st = $db->query("SELECT admin_https_port, certbot_strict_port80 FROM settings W
App\FirewallManager::applyNginxConfig((int)($st["admin_https_port"] ?? 8443), (int)($st["certbot_strict_port80"] ?? 0));
'
# Filtre Fail2ban Asterisk
# Filtre Fail2ban Asterisk & Nexus-Web
cat << 'EOF' > /etc/fail2ban/filter.d/asterisk.conf
[Definition]
failregex = ^(%(__prefix_line)s|\[\]\s*)*(?:NOTICE|SECURITY)\[\d+\]:? (?:\S+: )?(?:Registration from |Call from |Invalid password for |Sending fake auth challenge to |No matching endpoint found for )?'?<HOST>(?::\d+)?'?
^(%(__prefix_line)s|\[\]\s*)*SECURITY\[\d+\]:? (?:\S+: )?SecurityEvent="(?:FailedACL|InvalidAccountID|ChallengeResponseFailed|InvalidPassword|AuthFailed)"(?:.*?)RemoteAddress="IPV[46]/(?:UDP|TCP|TLS)/<HOST>/\d+"
ignoreregex =
EOF
chmod 0644 /etc/fail2ban/filter.d/asterisk.conf
cat << 'EOF' > /etc/fail2ban/filter.d/nexus-web.conf
[Definition]
failregex = ^.*\[NEXUS-WEB-AUTH-FAIL\]:\s*<HOST>.*$
ignoreregex =
EOF
chmod 0644 /etc/fail2ban/filter.d/nexus-web.conf
# Jails Fail2ban
cat << 'EOF' > /etc/fail2ban/jail.local
@@ -350,8 +382,25 @@ port = http,https,8443
logpath = /var/log/nginx/*error.log
maxretry = 5
bantime = 3600
[nexus-web]
enabled = true
port = http,https,8443
filter = nexus-web
logpath = /var/log/nexus_security.log
maxretry = 3
findtime = 600
bantime = 3600
EOF
chown root:asterisk /etc/fail2ban/jail.local
chmod 0664 /etc/fail2ban/jail.local
setfacl -m u:www-data:rw /etc/fail2ban/jail.local 2>/dev/null || true
chown root:asterisk /etc/nginx/sites-available/nexus-pbx
chmod 0664 /etc/nginx/sites-available/nexus-pbx
setfacl -m u:www-data:rw /etc/nginx/sites-available/nexus-pbx 2>/dev/null || true
# 8. Crontab & Bannière d'accueil Console (Style FreePBX)
echo -e "${C_GREEN}[7/8] Mise en place des tâches programmées et de la bannière console...${C_RESET}"
@@ -381,14 +430,16 @@ chmod +x /etc/profile.d/nexus-motd.sh
echo -e "${C_GREEN}[8/8] Démarrage et activation des services système...${C_RESET}"
systemctl daemon-reload
# Redémarrage PHP-FPM
# Redémarrage PHP-FPM (rechargement de l'appartenance au groupe asterisk)
systemctl restart php*-fpm 2>/dev/null || true
PHP_SVC=$(systemctl list-unit-files --type=service 2>/dev/null | grep -E "php.*-fpm" | awk '{print $1}' | head -n 1 || echo "php8.4-fpm")
systemctl restart "$PHP_SVC" && systemctl enable "$PHP_SVC"
systemctl restart "$PHP_SVC" 2>/dev/null || true
systemctl enable "$PHP_SVC" 2>/dev/null || true
# Redémarrage Asterisk, Nginx, Fail2ban, Cron
systemctl restart asterisk && systemctl enable asterisk
nginx -t && systemctl restart nginx && systemctl enable nginx
systemctl restart fail2ban && systemctl enable fail2ban
nginx -t && systemctl restart nginx && systemctl enable nginx
systemctl restart cron && systemctl enable cron
# Exécution immédiate de la bannière console
+18 -1
View File
@@ -1729,16 +1729,33 @@ class ConfigGenerator
$tmpPath = $targetPath . '.tmp.' . getmypid();
if (@file_put_contents($tmpPath, $content, LOCK_EX) === false) {
// Repli en écriture directe si le fichier existe déjà et est accessible
if (file_exists($targetPath) && is_writable($targetPath)) {
if (@file_put_contents($targetPath, $content, LOCK_EX) !== false) {
@chgrp($targetPath, 'asterisk');
@chmod($targetPath, 0664);
return;
}
}
throw new RuntimeException("Impossible d'écrire dans {$targetPath}. Vérifiez que www-data fait partie du groupe asterisk et que /etc/asterisk est accessible en écriture de groupe (chmod 2775).");
}
@chgrp($tmpPath, 'asterisk');
@chmod($tmpPath, 0660);
@chmod($tmpPath, 0664);
if (!@rename($tmpPath, $targetPath)) {
@unlink($tmpPath);
// Repli en écriture directe si le renommage échoue
if (@file_put_contents($targetPath, $content, LOCK_EX) !== false) {
@chgrp($targetPath, 'asterisk');
@chmod($targetPath, 0664);
return;
}
throw new RuntimeException("Échec du remplacement atomique de {$targetPath}.");
}
@chgrp($targetPath, 'asterisk');
@chmod($targetPath, 0664);
}
public static function normalizeInboundRoutes(string $json): array
+5 -3
View File
@@ -291,8 +291,6 @@ ignoreip = {$whitelist}
findtime = {$sipFindTime}
bantime = {$sipBanTime}
maxretry = {$sipMaxRetry}
banaction = nftables-multiport
banaction_allports = nftables-allports
[sshd]
enabled = true
@@ -306,7 +304,7 @@ bantime = 3600
[asterisk]
enabled = true
filter = asterisk
logpath = /var/log/asterisk/security.log
logpath = /var/log/asterisk/messages
maxretry = {$sipMaxRetry}
findtime = {$sipFindTime}
bantime = {$sipBanTime}
@@ -326,6 +324,8 @@ protocol = tcp
EOF;
file_put_contents(self::JAIL_LOCAL_PATH, $conf);
@chgrp(self::JAIL_LOCAL_PATH, 'asterisk');
@chmod(self::JAIL_LOCAL_PATH, 0664);
}
/**
@@ -477,6 +477,8 @@ EOF;
$fullNginxConfig = $port80Block . "\n\n" . $phonebookBlock . "\n\n" . $httpsBlock . "\n";
file_put_contents(self::NGINX_CONF_PATH, $fullNginxConfig);
@chgrp(self::NGINX_CONF_PATH, 'asterisk');
@chmod(self::NGINX_CONF_PATH, 0664);
// Test de syntaxe
exec('sudo /usr/sbin/nginx -t 2>&1', $tOut, $tCode);
+3
View File
@@ -6,6 +6,9 @@ namespace App;
use PDO;
use Throwable;
require_once __DIR__ . '/ConfigGenerator.php';
require_once __DIR__ . '/AmiClient.php';
class SystemChecker
{
public static function runDiagnostics(PDO $db): array