vicigeeksimple guides
Browse
All guides

Running your system · Defense-in-depth analysis

VICIdial hardening priorities and their limits

Close the exposed ports and anonymous SIP first, then stage 2FA and IP controls with tested recovery paths; no single setting makes a dialer secure or compliant.

Reader setup

Before you evaluate

  1. A running VICIdial installation and permission from the person responsible for its access settings
  2. A test account cohort
  3. An out-of-band recovery path
Expected result
A staged hardening plan with recoverable access tests.
Before making changes
No checklist provides a security guarantee or certification.

Begin with an auditable threat boundary

List each exposed Admin, Agent, API, report and recording URL. For each one, test an account that should be allowed and one that should be denied; record the result before changing access rules.

Fast answer: start where a dialer actually gets attacked, which is the ports it exposes to the Internet and whether it accepts anonymous SIP calls, then work up through least-privilege accounts, tested two-factor authentication (2FA), verified route-level Internet Protocol (IP) controls, protected secrets and audit review. Hardening is a staged program, not a checkbox or a promise of security.

An Internet-facing Asterisk server is scanned continuously. The two failures that cost real money are toll fraud, where an attacker places calls through your trunk at your expense, and an exposed management port such as the Asterisk Manager Interface (AMI) on 5038 or the MariaDB database on 3306. Both are network problems before they are application problems, which is why the firewall comes before the admin settings.

An API is an application programming interface; a route is one web, report, media or API entry point. This lab's Admin showed 2FA and IP-list settings present; both 2FA validity-hour settings were at zero at the time of writing — confirm yours. Treat that as an environment observation, not a statement about your deployment.

Terms are defined in VICIdial terminology for complete beginners: users, phones, campaigns and leads.

  • Before changing access, identify who can restore the server and confirm that a console connection works independently of SSH.
  • Non-goal: do not claim certification, compliance or immunity from attack after these checks.
  • Identify admin, agent, report, API, media and integration entry points.
  • Record the installed revision and which test routes currently allow or deny access; omit addresses and credentials from the record.
Trace path · read left to right
01Identity02Route controls03Audit + recovery
Reference screenshots 3 images

Reference capture

Reference screens from the demo

Captured on an isolated VICIdial demo: Administration screens on September 24, 2026, and the idle Agent screen on August 11, 2026. Each caption states its own capture time, and every sanitized image helps you recognize a related screen; none proves that this article's call, command, or result occurred.
Step 1 · Find system administration

Use the Administration map

Open to enlarge
Sanitized VICIdial Administration menu showing phones, carriers, servers, system settings, and system statuses
Captured September 24, 2026 at 21:34:11 UTC on the authorized isolated demo.
Capture detailsThis menu is a navigation map only; it does not show that any system-wide setting was changed or verified.
Step 2 · Check permission scope

Review user-group boundaries

Open to enlarge
Sanitized VICIdial User Groups Listings page showing the fixture user group
Captured September 24, 2026 at 21:53:04 UTC on the authorized isolated demo.
Capture detailsThis page shows group structure only; it does not prove that an account has a particular permission or that access was changed.
Step 3 · Read global settings

Inspect system-wide security and API context

Open to enlarge
Sanitized VICIdial Modify System Settings page showing revision, schema, interface, SIP-stack, and API-related controls
Captured August 11, 2026 at 16:22:08 UTC on the authorized isolated demo.
Capture detailsThis is a read-only view of system-wide settings with no credentials or addresses; it does not prove that a setting was changed or that an API request succeeded.

Roll out 2FA with recovery tested first

The official feature supports admin and agent 2FA with configured email, phone-call or SMS delivery, system-level validity hours and per-user override. Delivery channels introduce operational dependencies: sender reputation, message latency, clock synchronization, attempt limits and account recovery all need testing.

Use this synthetic-cohort scorecard in a change record. PASS means every stated test succeeded for the test account; BLOCK means do not extend enforcement. The placeholders <TEST_ADMIN_USER> and <TEST_AGENT_USER> are labels only, never real user names or phone numbers.

Create a small test cohort and a documented break-glass process held outside the normal account path. Do not put SMS URLs, provider tokens, phone numbers or authorization codes in configuration exports, tickets or this publication.

Before you use it
Use in the access-change record with synthetic account labels only.
2FA rollout scorecard
<TEST_ADMIN_USER>: expiration PASS / recovery PASS / lockout PASS<TEST_AGENT_USER>: delivery PASS / logout PASS / recovery PASSBREAK-GLASS: independently tested PASSRESULT: BLOCK if any required test is not PASS
Not executed · worksheet or reference text

This sample is a template or reading aid, not a terminal command. There is no output to show.

Success looks like
All required tests and the separate recovery path are PASS.
Stop if
Block rollout and escalate if any test is missing or fails.
  • With a test account, try an expired code, repeated invalid codes, logout, account recovery and an unavailable delivery method; record each result.
  • List the test users with per-user overrides, compare each override with the intended access, and remove only overrides confirmed unnecessary.
  • Test account recovery through the documented console or recovery account without disabling access controls for all users.

Verify IP controls on every sensitive route

IP lists are an administrative capability, not evidence that every web, report, API, media or integration route enforces the intended allow/deny policy. Build a route inventory and test each route from an allowed and a denied, controlled test network.

Two controls do most of the work here, and neither lives in the VICIdial web interface. On a ViciBox install the host firewall is firewalld, not ufw: its external zone allows only a short list of named services — the web server, SSH, RTP audio and an asterisk service — and only from source addresses in ipsets that are loaded at runtime rather than configured as static rules: whiteips and whitenets, plus dynamiclist. whiteips and whitenets are fed by VICIdial's own IP List named ViciWhite (Admin → IP Lists); dynamiclist is fed separately by ViciBox's dynamic portal, which adds an address only after someone authenticates through it. VB-firewall (/usr/bin/VB-firewall) is the tool that loads all three ipsets, run from root's crontab at boot; it has no status or carrier subcommand of its own, so confirm its effect through firewalld directly, and never run a bare firewall reload afterward (see the checklist below). The stock asterisk service definition covers 5060/udp, 4569/udp and 8089/tcp only — it does not include 5061/udp, so confirm your own PJSIP bind port and channel driver first, with the checks in the sample below, before assuming an existing rule already covers it. On a cloud VPS the provider security group sits in front of all of this and must permit the same traffic, or nothing arrives regardless of what firewalld allows.

Use route labels, never deployed addresses, in any record you keep. EXPECTED DENY means the controlled denied test receives no protected content; an unexpected response is a stop condition. Put a reverse proxy, firewall or segmentation control under the network team's change process where appropriate, then verify that application and infrastructure policies agree.

Before you use it
Run these on the VICIdial server as a user authorized to read Asterisk and firewall state. Every command only reads; none of them change a rule. Step 1 puts the safety-critical anonymous-call check first: it greps sip show settings for its guest/anonymous-access line instead of printing the roughly 130-line full dump, and prints an explicit note instead of a silent blank when this build's wording does not match that grep, so the check never disappears from view. Do not assume 5060 or 5061 is the PJSIP port on your build — step 2 shows the port this install actually uses. 3306 is MariaDB, 5038 is the Asterisk Manager Interface and 8089 is the raw Asterisk HTTP/WebSocket listener; none of those three belong on a public address. The stock firewalld asterisk service (step 3) covers 5060/udp, 4569/udp and 8089/tcp only, never 5061/udp, so a PJSIP transport bound there needs its own confirmed allowance.
Read-only exposure audit
# 1. Read the safety-critical check first: is an anonymous/guest call path open on either channel driver?asterisk -rx 'pjsip show endpoint anonymous' 2>/dev/nullasterisk -rx 'sip show settings' 2>/dev/null | grep -iE 'unknown access|guest|anonymous' || echo 'no guest/anonymous access line matched in sip show settings output on this build' # 2. Confirm this build's actual PJSIP bind port before assuming 5060 or 5061 either way.asterisk -rx 'pjsip show transports'ss -lntup | grep -E ':(80|443|3306|4577|5038|5060|5061|8088|8089)\b' || echo 'none of those ports are listening' # 3. Identify the firewall backend in front of Asterisk. ViciBox ships firewalld with VB-firewall layered on top, not ufw.if firewall-cmd --state >/dev/null 2>&1; then  echo 'firewall backend: firewalld'  command -v VB-firewall >/dev/null 2>&1 && echo '  VB-firewall present: loads the ViciWhite/dynamic ipsets into firewalld (no status subcommand of its own)'elif command -v ufw >/dev/null 2>&1; then  echo 'firewall backend: ufw (an Ubuntu/Debian install, not the ViciBox default)'else  echo 'no recognized firewall backend found'fi # 4. Confirm which SIP channel driver(s) are loaded, for context on which part of step 1 applies to this build.asterisk -rx 'module show like chan_'
Evidence · ViciBox 12 demo capture

Captured demo response · 2026-09-25 06:55 UTC. Any filtering, hidden values or test-only data are identified in the capture label. Select Replay transcript to read the recorded output.

Command output line: # 1. Read the safety-critical check first: is an anonymous/guest call path open on either channel driver? asterisk -rx 'pjsip show endpoint anonymous' 2>/dev/null asterisk -rx 'sip show settings' 2>/dev/null | grep -iE 'unknown access|guest|anonymous' || echo 'no guest/anonymous access line matched in sip show settings output on this build' # 2. Confirm this build's actual PJSIP bind port before assuming 5060 or 5061 either way. asterisk -rx 'pjsip show transports' ss -lntup | grep -E ':(80|443|3306|4577|5038|5060|5061|8088|8089)\b' || echo 'none of those ports are listening' # 3. Identify the firewall backend in front of Asterisk. ViciBox ships firewalld with VB-firewall layered on top, not ufw. if firewall-cmd --state >/dev/null 2>&1; then echo 'firewall backend: firewalld' command -v VB-firewall >/dev/null 2>&1 && echo ' VB-firewall present: loads the ViciWhite/dynamic ipsets into firewalld (no status subcommand of its own)' elif command -v ufw >/dev/null 2>&1; then echo 'firewall backend: ufw (an Ubuntu/Debian install, not the ViciBox default)' else echo 'no recognized firewall backend found' fi # 4. Confirm which SIP channel driver(s) are loaded, for context on which part of step 1 applies to this build. asterisk -rx 'module show like chan_'
Unable to find object anonymous.
Allow unknown access: No
Transport: <TransportId........> <Type> <cos> <tos> <BindAddress....................>
==========================================================================================
Transport: transport-udp udp 0 96 0.0.0.0:5061
Transport: transport-wss wss 0 0 0.0.0.0:5060
Objects found: 2
udp UNCONN 0 0 0.0.0.0:5060 0.0.0.0:* users:(("asterisk",pid=3019,fd=16))
udp UNCONN 0 0 0.0.0.0:5061 0.0.0.0:* users:(("asterisk",pid=3019,fd=13))
tcp LISTEN 0 10 127.0.0.1:5038 0.0.0.0:* users:(("asterisk",pid=3019,fd=9))
tcp LISTEN 0 10 0.0.0.0:8089 0.0.0.0:* users:(("asterisk",pid=3019,fd=8))
tcp LISTEN 0 10 0.0.0.0:8088 0.0.0.0:* users:(("asterisk",pid=3019,fd=7))
tcp LISTEN 0 450 0.0.0.0:3306 0.0.0.0:* users:(("mysqld",pid=1481,fd=33))
tcp LISTEN 0 4096 *:4577 *:* users:(("FastAGI_log.pl",pid=8355,fd=3),("FastAGI_log.pl",pid=2148,fd=3),("FastAGI_log.pl",pid=2147,fd=3),("FastAGI_log.pl",pid=2146,fd=3),("FastAGI_log.pl",pid=2145,fd=3),("FastAGI_log.pl",pid=2086,fd=3))
tcp LISTEN 0 4096 *:443 *:* users:(("httpd-prefork",pid=19537,fd=6),("httpd-prefork",pid=19533,fd=6),("httpd-prefork",pid=19529,fd=6),("httpd-prefork",pid=13442,fd=6),("httpd-prefork",pid=5619,fd=6),("httpd-prefork",pid=5348,fd=6),("httpd-prefork",pid=5265,fd=6),("httpd-prefork",pid=5218,fd=6),("httpd-prefork",pid=5216,fd=6),("httpd-prefork",pid=5215,fd=6),("httpd-prefork",pid=1444,fd=6))
tcp LISTEN 0 4096 *:80 *:* users:(("httpd-prefork",pid=19537,fd=4),("httpd-prefork",pid=19533,fd=4),("httpd-prefork",pid=19529,fd=4),("httpd-prefork",pid=13442,fd=4),("httpd-prefork",pid=5619,fd=4),("httpd-prefork",pid=5348,fd=4),("httpd-prefork",pid=5265,fd=4),("httpd-prefork",pid=5218,fd=4),("httpd-prefork",pid=5216,fd=4),("httpd-prefork",pid=5215,fd=4),("httpd-prefork",pid=1444,fd=4))
firewall backend: firewalld
VB-firewall present: loads the ViciWhite/dynamic ipsets into firewalld (no status subcommand of its own)
Module Description Use Count Status Support Level
chan_audiosocket.so AudioSocket Channel 0 Running extended
chan_bridge_media.so Bridge Media Channel Driver 0 Running core
chan_dahdi.so DAHDI Telephony w/PRI & SS7 & MFC/R2 0 Running core
chan_iax2.so Inter Asterisk eXchange (Ver 2) 0 Running core
chan_mgcp.so Media Gateway Control Protocol (MGCP) 0 Running extended
chan_motif.so Motif Jingle Channel Driver 0 Running core
chan_pjsip.so PJSIP Channel Driver 1 Running core
chan_rtp.so RTP Media Channel 0 Running core
chan_sip.so Session Initiation Protocol (SIP) 0 Running deprecated
9 modules loaded
Success looks like
Step 1 inspects one endpoint named anonymous and the chan_sip settings. An absent endpoint does not rule out anonymous matching through another endpoint or identify rule; inspect the full loaded PJSIP configuration and test the intended policy separately. Step 2 shows a real bound port with no unaccounted listener; on our ViciBox 12 lab the database and Asterisk HTTP listeners bind to all interfaces and are gated by the firewall zone in step 3 instead, so an all-interfaces bind here is a prompt to confirm step 3, not a failure by itself. Step 3 checks whether firewalld responds or whether the ufw command exists. An installed ufw command does not prove its policy is active; inspect actual firewall rules separately. Step 4 shows which channel driver or drivers are actually loaded, which is what decides which half of step 1 applies to this build.
Stop if
Stop and escalate first on step 1: chan_sip accepting guest calls or a reachable anonymous PJSIP endpoint is an open toll-fraud or data-exposure path, not a finding to schedule for later. If step 1's chan_sip line instead prints the 'no guest/anonymous access line matched' note, treat that as inconclusive rather than a pass, and read the full sip show settings output by hand before signing off. Also stop if step 2 shows a listener you cannot account for on any port, or if step 3 finds no recognized firewall backend on a server with a public address.
  • Compare the allowed ports and source ranges in the provider security group with the host firewall; investigate any mismatch.
  • Test Admin, Agent, reports, Non-Agent API and media/export paths.
  • Check the proxy configuration for trusted source addresses; test that a direct request cannot impersonate a trusted proxy using forwarded headers.
  • Never run a bare firewall reload after VB-firewall has loaded whiteips/whitenets/dynamiclist — it empties those ipsets until VB-firewall runs again.
  • Keep an out-of-band console/recovery route under controlled access.

Reduce secret exposure and privilege

Use dedicated, least-privilege identities for API clients, database maintenance, report delivery and external providers. Rotate a credential through its approved secret store and configuration deployment mechanism; never place it in source, shell history, browser URLs or diagnostic output.

On a dialer the highest-value secrets are the SIP credentials your trunk uses, because they convert directly into fraudulent calls. Give every SIP endpoint a long unique password, never reuse the extension number as its secret, and keep AMI and MariaDB bound to localhost or a private interface rather than a public address. If an integration genuinely needs remote AMI or database access, carry it over a VPN or an SSH tunnel instead of opening the port.

Guard database access regardless of storage format; confirm the target build’s handling without exposing the values. On this lab, system_settings.pass_hash_enabled is 0, which means vicidial_users.pass and phones.conf_secret are plain text rather than a hash — never SELECT either column, screenshot one, or paste one into a ticket, even for read-only troubleshooting, because a plain-text value is the credential itself.

Review settings containers, scheduled jobs, integration endpoints and backup destinations because these often bridge the web application to external services. A read-only report can still create an audit-log write, so account scope and retention matter.

  • Separate human, API and service identities.
  • For each credential, record who rotates it, how to revoke it and the next rotation date; do not record the secret.
  • Test failures using non-sensitive observability, not live credentials.

Audit authorization and retain a safe reversal

Route audit should test authentication, authorization, campaign/group/report scope, session behavior and audit-log evidence independently. UI hiding is not authorization; sensitive endpoints and fragment routes need their own checks.

Stop rollout if a break-glass path is untested, a necessary integration fails, or audit evidence cannot distinguish test from production activity. Roll back the narrow configuration or policy change after preserving sanitized evidence, then investigate without weakening unrelated controls.

  • Use an independent reviewer for route tests and access review.
  • Re-test after upgrades, reverse-proxy changes and new integrations.
  • Do not represent this checklist as a certification, penetration test or compliance determination.

Checks and sources

What was checked

  • This lab's Admin UI exposes 2FA and IP-list settings; route enforcement varies and must be independently verified.
  • No penetration test, security certification, deployed configuration, incident history or guarantee is claimed.

Primary references

Sources

  1. VICIdial Two-Factor AuthenticationVICIdial · accessed September 23, 2026
  2. NIST Cybersecurity Framework 2.0National Institute of Standards and Technology · accessed September 23, 2026

Follow without guesswork

Get the next article

RSS is live now. Email delivery below is an explicit local preview and sends nothing.Open the RSS feed
Email preview only. The address stays in this browser and is never transmitted.