; ============================================================================= ; VICIdial Security Hardening — Fail2ban, IPtables, AMI & TLS Configuration ; ============================================================================= ; Generated by ViciStack — https://vicistack.com — Free VICIdial optimization ; ; WHAT THIS FILE DOES: ; Locks down a VICIdial server against the most common attacks: ; SIP brute force, AMI exploitation, web interface attacks, and ; man-in-the-middle on agent connections. These aren't theoretical — ; an unprotected VICIdial server WILL get SIP-scanned within 24 hours. ; ; HOW TO USE: ; This file contains configs for multiple services. Each section tells ; you which file to edit. Apply them in order: ; 1. IPtables (base firewall) ; 2. Fail2ban (brute force protection) ; 3. AMI lockdown (Asterisk Manager Interface) ; 4. TLS/SRTP (encryption) ; 5. Web interface hardening ; ; FULL GUIDE: ; https://vicistack.com/blog/vicidial-security-hardening/ ; https://vicistack.com/blog/asterisk-pjsip-tls-openssl3-guide/ ; https://vicistack.com/blog/call-center-compliance-checklist-2026/ ; ; NEED HELP? hello@vicistack.com ; ============================================================================= ; ============================================================================= ; SECTION 1: IPTABLES BASE FIREWALL ; ============================================================================= ; File: /etc/sysconfig/iptables ; Apply: systemctl restart iptables ; ; Strategy: Default-deny. Only open what VICIdial needs. ; Adjust IPs/ranges for your network. ; ============================================================================= ; --- /etc/sysconfig/iptables --- *filter :INPUT DROP [0:0] :FORWARD DROP [0:0] :OUTPUT ACCEPT [0:0] ; Loopback — always allow -A INPUT -i lo -j ACCEPT ; Established connections — let existing sessions continue -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT ; SSH — restrict to your management IPs only ; CHANGE THESE to your office/VPN IPs -A INPUT -p tcp --dport 22 -s YOUR_OFFICE_IP/32 -j ACCEPT -A INPUT -p tcp --dport 22 -s YOUR_VPN_IP/32 -j ACCEPT ; DO NOT open SSH to 0.0.0.0/0 — bots scan port 22 constantly. ; If you must allow SSH from anywhere, use fail2ban (Section 2) and ; key-based auth only (disable password auth in /etc/ssh/sshd_config). ; HTTP/HTTPS — VICIdial web interface ; Option A: Restrict to agent IPs / office network -A INPUT -p tcp --dport 443 -s YOUR_OFFICE_NETWORK/24 -j ACCEPT ; Option B: Open to world (only if agents connect from random IPs) ; -A INPUT -p tcp --dport 443 -j ACCEPT ; If using Option B, enable fail2ban for the web interface (Section 2). ; SIP signaling — UDP 5060 ; Option A: Restrict to your SIP trunk provider IPs (BEST) -A INPUT -p udp --dport 5060 -s SIP_PROVIDER_IP_1/32 -j ACCEPT -A INPUT -p udp --dport 5060 -s SIP_PROVIDER_IP_2/32 -j ACCEPT ; Option B: Open to world (required for remote agents without VPN) ; -A INPUT -p udp --dport 5060 -j ACCEPT ; WARNING: Opening 5060 to the world = guaranteed SIP scanner traffic. ; You MUST use fail2ban (Section 2) if you do this. ; SIP TLS — TCP 5061 (for encrypted SIP from remote agents) -A INPUT -p tcp --dport 5061 -j ACCEPT ; RTP media — UDP 10000-20000 ; Must be open to the world — RTP comes from carrier IPs and agent IPs. -A INPUT -p udp --dport 10000:20000 -j ACCEPT ; WebRTC WebSocket — TCP 8089 -A INPUT -p tcp --dport 8089 -j ACCEPT ; MySQL — ONLY from VICIdial cluster servers (NEVER public) -A INPUT -p tcp --dport 3306 -s DB_REPLICA_IP/32 -j ACCEPT -A INPUT -p tcp --dport 3306 -s WEB_SERVER_IP/32 -j ACCEPT ; If this is a single-server install, don't open 3306 at all. ; Asterisk and Apache connect via localhost. ; AMI — Asterisk Manager Interface — ONLY localhost ; See Section 3 for AMI-specific lockdown. -A INPUT -p tcp --dport 5038 -s 127.0.0.1/32 -j ACCEPT ; NEVER open AMI to the network. AMI gives full control over Asterisk: ; originate calls, dump configs, execute shell commands (via System()). ; If you need remote AMI access, tunnel it through SSH. ; ICMP ping — allow from management IPs for monitoring -A INPUT -p icmp --icmp-type echo-request -s YOUR_OFFICE_IP/32 -j ACCEPT ; Drop everything else (default policy is DROP, but explicit is clearer) -A INPUT -j DROP COMMIT ; ============================================================================= ; SECTION 2: FAIL2BAN CONFIGURATION ; ============================================================================= ; Fail2ban watches log files for failed auth attempts and bans the source IP. ; Install: yum install fail2ban && systemctl enable fail2ban ; ============================================================================= ; --- /etc/fail2ban/jail.local --- ; Create this file (don't edit jail.conf — it gets overwritten on updates). [DEFAULT] ; Ban for 1 hour after 3 failures within 10 minutes. ; Persistent attackers get longer bans (see recidive jail below). bantime = 3600 findtime = 600 maxretry = 3 banaction = iptables-multiport ; Send notifications (optional — configure your email in jail.local) ; action = %(action_mwl)s ; --- Asterisk SIP brute force protection --- [asterisk] enabled = true filter = asterisk action = iptables-multiport[name=asterisk, port="5060,5061", protocol=udp] logpath = /var/log/asterisk/messages maxretry = 3 findtime = 300 bantime = 86400 ; 24-hour ban for SIP auth failures. SIP scanners are automated — they ; won't stop after an hour. A 24-hour ban makes them move on. ; --- SSH brute force --- [sshd] enabled = true filter = sshd action = iptables-multiport[name=sshd, port="22", protocol=tcp] logpath = /var/log/secure maxretry = 3 bantime = 3600 ; --- VICIdial web interface (Apache) --- [apache-auth] enabled = true filter = apache-auth action = iptables-multiport[name=apache, port="80,443", protocol=tcp] logpath = /var/log/httpd/error_log maxretry = 5 findtime = 300 bantime = 3600 ; --- Recidive jail (ban repeat offenders for longer) --- [recidive] enabled = true filter = recidive action = iptables-allports[name=recidive] logpath = /var/log/fail2ban.log maxretry = 3 findtime = 86400 bantime = 604800 ; If an IP gets banned 3 times in 24 hours, ban for 1 week. ; This catches persistent bots that rotate their attack timing. ; --- /etc/fail2ban/filter.d/asterisk.conf --- ; Custom filter for Asterisk PJSIP auth failures. ; Stock fail2ban has an asterisk filter but it misses PJSIP log formats. ; [INCLUDES] ; before = common.conf ; ; [Definition] ; failregex = NOTICE.* No matching endpoint found for.*'' ; NOTICE.* Failed to authenticate.* ; SECURITY.* SecurityEvent="FailedACL".*RemoteAddress.* ; SECURITY.* SecurityEvent="InvalidAccountID".*RemoteAddress.* ; SECURITY.* SecurityEvent="ChallengeResponseFailed".*RemoteAddress.* ; SECURITY.* SecurityEvent="InvalidPassword".*RemoteAddress.* ; ignoreregex = ; ============================================================================= ; SECTION 3: ASTERISK MANAGER INTERFACE (AMI) LOCKDOWN ; ============================================================================= ; File: /etc/asterisk/manager.conf ; ; AMI is how VICIdial controls Asterisk (originating calls, checking channels, ; transferring calls). It MUST be enabled but MUST be locked down. ; An open AMI = full control of your phone system = toll fraud. ; ============================================================================= ; --- /etc/asterisk/manager.conf --- [general] enabled = yes port = 5038 bindaddr = 127.0.0.1 ; CRITICAL: Bind to localhost ONLY. VICIdial's PHP scripts connect locally. ; Combined with the iptables rule above (5038 only from 127.0.0.1), ; this is a belt-and-suspenders approach. Both matter. displayconnects = no ; Don't log every AMI connection in the console. Reduces noise. timestampevents = yes ; Timestamp AMI events for audit trail. ; --- AMI user for VICIdial --- ; VICIdial uses a specific AMI user. Give it ONLY the permissions it needs. [cron] ; This is VICIdial's standard AMI user name. secret = STRONG_RANDOM_PASSWORD_HERE ; Generate: openssl rand -hex 24 ; This password is in VICIdial's astguiclient.conf. Change both at once. deny = 0.0.0.0/0.0.0.0 ; Deny from everywhere first. permit = 127.0.0.1/255.255.255.255 ; Then allow only from localhost. read = system,call,log,verbose,agent,user,config,dtmf,reporting,cdr,dialplan write = system,call,agent,user,config,command,reporting,originate ; These are the permissions VICIdial actually needs. Don't add extras. ; Specifically, do NOT add "all" — that grants dangerous permissions ; like "command" which allows arbitrary CLI execution. ; --- Second AMI user for monitoring (optional) --- ; Read-only user for Grafana, Nagios, etc. [monitor] secret = DIFFERENT_STRONG_PASSWORD deny = 0.0.0.0/0.0.0.0 permit = 127.0.0.1/255.255.255.255 read = system,call,agent,cdr write = ; Empty write = read-only. Can observe but not control. ; See: https://vicistack.com/blog/vicidial-grafana-realtime-dashboard/ ; ============================================================================= ; SECTION 4: TLS / SRTP ENCRYPTION ; ============================================================================= ; Encrypt SIP signaling (TLS) and audio (SRTP). ; Required for: PCI compliance, HIPAA, any time you handle payment cards ; or health info over the phone. ; ; See: https://vicistack.com/blog/asterisk-pjsip-tls-openssl3-guide/ ; ============================================================================= ; --- pjsip.conf: TLS transport --- [transport-tls] type = transport protocol = tls bind = 0.0.0.0:5061 cert_file = /etc/asterisk/keys/asterisk.pem priv_key_file = /etc/asterisk/keys/asterisk.pem ; Use Let's Encrypt certs — see vicidial-remote-agent.conf for setup. method = tlsv1_2 ; Minimum TLS 1.2. TLS 1.0 and 1.1 are deprecated and insecure. ; If you have very old SIP phones that only support TLS 1.0, replace them. cipher = ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256 ; Strong cipher suite only. No RC4, no 3DES, no CBC. external_media_address = YOUR_PUBLIC_IP external_signaling_address = YOUR_PUBLIC_IP local_net = 10.0.0.0/8 local_net = 172.16.0.0/12 local_net = 192.168.0.0/16 ; --- pjsip.conf: Encrypted endpoint template --- [encrypted-endpoint](!) type = endpoint transport = transport-tls media_encryption = sdes ; SDES-SRTP encryption for media. Compatible with most SIP phones. ; For WebRTC, use dtls instead (see remote-agent config). media_encryption_optimistic = yes ; Try encryption, fall back to unencrypted if the phone doesn't support it. ; Set to "no" for strict enforcement (PCI/HIPAA requirement). ; ============================================================================= ; SECTION 5: WEB INTERFACE HARDENING ; ============================================================================= ; Apache / HTTPS configuration for the VICIdial admin and agent interfaces. ; ============================================================================= ; --- /etc/httpd/conf.d/ssl.conf (relevant settings) --- ; ; SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1 ; ; Only TLS 1.2 and 1.3. Everything else is broken. ; ; SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384 ; ; Strong ciphers only. ; ; SSLHonorCipherOrder on ; ; Server picks the cipher, not the client. ; ; Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" ; ; HSTS — force HTTPS for 1 year. No accidental HTTP connections. ; ; Header always set X-Frame-Options "SAMEORIGIN" ; ; Prevent clickjacking attacks on the VICIdial agent screen. ; ; Header always set X-Content-Type-Options "nosniff" ; ; Prevent MIME type sniffing. ; --- Disable directory listing --- ; VICIdial's web directory has sensitive files. Don't let people browse them. ; ; ; Options -Indexes ; ; --- Restrict admin interface by IP --- ; /var/www/html/vicidial/admin.php is the crown jewels. ; ; ; Require ip YOUR_OFFICE_IP ; Require ip YOUR_VPN_IP ; ; ; Or use VICIdial's built-in IP restrictions: ; Admin > Admin > System Settings > Admin IP Restrictions ; --- Change default admin password --- ; This should be obvious but VICIdial ships with admin/admin (user 6666). ; Change it immediately after install: ; Admin > Admin > Users > 6666 > Change Password ; Use a 20+ character password. The admin account has god-mode access. ; --- Disable unused API endpoints --- ; VICIdial exposes several API scripts. Disable the ones you don't use: ; non_agent_api.php — used for external integrations (keep if needed) ; agent_api.php — used by agent screen (keep) ; manager_send.php — AMI passthrough (DISABLE unless specifically needed) ; Disable by adding IP restrictions or renaming the files. ; ============================================================================= ; SECTION 6: ADDITIONAL SECURITY MEASURES ; ============================================================================= ; ; 1. SSH KEY-ONLY AUTH ; /etc/ssh/sshd_config: ; PasswordAuthentication no ; PermitRootLogin no ; AllowUsers your_admin_user ; No passwords, no root login. Period. ; ; 2. AUTO-UPDATES FOR SECURITY PATCHES ; yum install yum-cron ; Enable security-only updates in /etc/yum/yum-cron.conf: ; update_cmd = security ; apply_updates = yes ; ; 3. LOG MONITORING ; Watch these logs for anomalies: ; /var/log/asterisk/messages — SIP auth failures, unusual calls ; /var/log/httpd/access_log — web scans, brute force attempts ; /var/log/secure — SSH auth failures ; /var/log/fail2ban.log — who got banned and why ; Send to a central syslog or SIEM if you have one. ; See: https://vicistack.com/blog/vicidial-grafana-realtime-dashboard/ ; ; 4. REGULAR AUDITS ; Monthly: review AMI users and permissions ; Monthly: review VICIdial admin users (deactivate departed employees) ; Quarterly: update TLS certificates ; Quarterly: review firewall rules ; See: https://vicistack.com/blog/call-center-compliance-checklist-2026/ ; ; For professional security audits: ; https://vicistack.com — hello@vicistack.com ; =============================================================================