Asterisk Solutions & Troubleshooting

20 practical, step-by-step solutions for the most common Asterisk PBX problems — from one-way audio to TLS encryption

20
Solutions
100+
Config Examples
Real
World Tested

1. One-Way Audio Fix

Problem: Caller can hear the remote party but the remote party cannot hear the caller (or vice versa). Audio flows in only one direction.
Cause: Almost always caused by NAT (Network Address Translation) or firewall issues. The SIP signaling gets through but RTP (audio) packets are sent to the wrong IP address or blocked by a firewall. SIP ALG on routers can also rewrite SDP headers incorrectly.

Configuration / Commands

; === sip.conf (chan_sip) ===
[general]
nat=force_rport,comedia
externaddr=YOUR_PUBLIC_IP       ; or externhost=your.domain.com
localnet=192.168.0.0/255.255.0.0
localnet=10.0.0.0/255.0.0.0
localnet=172.16.0.0/255.240.0.0
directmedia=no                  ; Prevent direct RTP between endpoints

; Per-peer settings
[my-peer]
nat=force_rport,comedia
directmedia=no
qualify=yes

; === pjsip.conf (PJSIP) ===
[transport-udp]
type=transport
protocol=udp
bind=0.0.0.0:5060
external_media_address=YOUR_PUBLIC_IP
external_signaling_address=YOUR_PUBLIC_IP
local_net=192.168.0.0/16
local_net=10.0.0.0/8

[my-endpoint]
type=endpoint
rtp_symmetric=yes
force_rport=yes
rewrite_contact=yes
direct_media=no

; === rtp.conf ===
[general]
rtpstart=10000
rtpend=20000

; === Firewall (iptables) ===
# Open RTP port range
iptables -A INPUT -p udp --dport 10000:20000 -j ACCEPT
# Open SIP signaling
iptables -A INPUT -p udp --dport 5060 -j ACCEPT

Step-by-Step Fix

  1. Set nat=force_rport,comedia in sip.conf [general] and per-peer sections
  2. Configure externaddr with your public IP (or externhost for dynamic IP)
  3. Set localnet for all your private subnets
  4. Set directmedia=no (or direct_media=no for PJSIP) to force media through Asterisk
  5. Open UDP ports 10000-20000 in your firewall for RTP traffic
  6. Disable SIP ALG on your router/firewall (this is critical)
  7. For PJSIP: set rtp_symmetric=yes and force_rport=yes on endpoints
  8. Test with: asterisk -rx "rtp set debug on" to trace RTP packets

2. NAT Traversal Configuration

Problem: Phones behind NAT cannot register, calls drop after 30 seconds, or audio issues occur. Remote workers and branch offices behind consumer routers are most affected.
Cause: NAT translates private IPs to public IPs, but SIP embeds IP addresses inside the SIP headers and SDP body. The remote end tries to send audio to the private IP, which is unreachable. Additionally, NAT bindings timeout causing registrations to drop.

Configuration / Commands

; === sip.conf - Complete NAT configuration ===
[general]
nat=force_rport,comedia
externaddr=203.0.113.1           ; Your public IP
; For dynamic IP, use externhost instead:
; externhost=pbx.example.com
; externrefresh=60               ; DNS refresh interval
localnet=192.168.1.0/255.255.255.0
localnet=10.0.0.0/255.0.0.0
directmedia=no
qualify=yes                      ; Send OPTIONS to keep NAT binding alive
qualifyfreq=30                   ; Every 30 seconds

; === pjsip.conf - Complete NAT configuration ===
[transport-udp]
type=transport
protocol=udp
bind=0.0.0.0:5060
external_media_address=203.0.113.1
external_signaling_address=203.0.113.1
local_net=192.168.1.0/24
local_net=10.0.0.0/8

[remote-phone]
type=endpoint
rtp_symmetric=yes
force_rport=yes
rewrite_contact=yes
direct_media=no
ice_support=yes                  ; Enable ICE for better NAT traversal

[remote-phone-aor]
type=aor
max_contacts=1
qualify_frequency=30             ; Keep NAT binding alive
remove_existing=yes

Step-by-Step Fix

  1. Configure externaddr (or external_media_address for PJSIP) with your server's public IP
  2. Define all local/private subnets with localnet directives
  3. Set directmedia=no to keep all media flowing through Asterisk
  4. Enable qualify with a frequency of 25-30 seconds to keep NAT pinholes open
  5. Disable SIP ALG on all routers between endpoints and Asterisk
  6. For phones behind NAT: set nat=force_rport,comedia per peer
  7. Consider using STUN/TURN for WebRTC or complex NAT scenarios
  8. Test NAT with: asterisk -rx "sip show peer <name>" and check the Addr->IP mapping

3. SIP Registration Failures

Problem: Phones or trunks show "UNREACHABLE" or fail to register. SIP REGISTER requests return 401 Unauthorized, 403 Forbidden, or timeout with no response.
Cause: Common causes include wrong credentials (username/password), incorrect host/port settings, firewall blocking port 5060, DNS resolution failure, or IP authentication mismatch. For trunks, the provider may require specific registration format.

Configuration / Commands

; === Debugging SIP registration ===
; Enable SIP debugging in Asterisk console:
asterisk -rx "sip set debug on"
; or for PJSIP:
asterisk -rx "pjsip set logger on"

; === sip.conf - Trunk registration ===
[general]
register => username:password@sip.provider.com/inbound_ext

[my-trunk]
type=peer
host=sip.provider.com
username=your_username
secret=your_password
fromuser=your_username
fromdomain=sip.provider.com
insecure=invite,port
qualify=yes
dtmfmode=rfc2833

; === pjsip.conf - Trunk registration ===
[my-trunk]
type=registration
outbound_auth=my-trunk-auth
server_uri=sip:sip.provider.com
client_uri=sip:your_username@sip.provider.com
retry_interval=60
max_retries=10

[my-trunk-auth]
type=auth
auth_type=userpass
username=your_username
password=your_password

[my-trunk-endpoint]
type=endpoint
context=from-trunk
disallow=all
allow=ulaw,alaw
outbound_auth=my-trunk-auth
aors=my-trunk-aor

[my-trunk-identify]
type=identify
endpoint=my-trunk-endpoint
match=sip.provider.com

Step-by-Step Fix

  1. Enable SIP debugging: sip set debug on (or pjsip set logger on)
  2. Check the SIP REGISTER request and response in the debug output
  3. For 401: verify username and password match exactly (case-sensitive)
  4. For 403: check if IP-based ACLs are blocking you; verify the fromuser/fromdomain
  5. For timeout: check firewall allows outbound UDP/TCP 5060; try telnet to provider:5060
  6. Verify DNS resolution: nslookup sip.provider.com from the Asterisk server
  7. Check registration status: sip show registry or pjsip show registrations
  8. For PJSIP: ensure the identify section matches the provider's IP to route incoming calls

4. Call Quality / Jitter / Packet Loss Diagnosis

Problem: Calls have choppy audio, robotic voice, echo, clicking sounds, or intermittent silence. Voice quality degrades during peak hours.
Cause: Network issues: packet loss >1%, jitter >30ms, or latency >150ms. Can also be caused by insufficient bandwidth, QoS misconfiguration, codec mismatch forcing transcoding, or CPU overload on the Asterisk server.

Configuration / Commands

; === Diagnose call quality issues ===

; 1. Check network quality to a SIP peer
ping -c 100 -i 0.02 PEER_IP
; Look for packet loss % and latency variation

; 2. Enable RTP debugging during a call
asterisk -rx "rtp set debug on"
; Watch for gaps in sequence numbers (= packet loss)

; 3. Check Asterisk system resources
asterisk -rx "core show sysinfo"
asterisk -rx "core show channels count"

; 4. Configure jitter buffer in sip.conf
[general]
jbenable=yes          ; Enable jitter buffer
jbforce=yes           ; Force jitter buffer on all channels
jbmaxsize=200         ; Max jitter buffer size in ms
jbimpl=adaptive       ; Use adaptive jitter buffer
jbtargetextra=40      ; Extra buffer space in ms
jblog=no              ; Enable for debugging

; 5. Configure jitter buffer in pjsip.conf
[my-endpoint]
type=endpoint
jitter_buffer=adaptive   ; adaptive, fixed, or disabled
jitter_buffer_max_size=200
jitter_buffer_resynch_threshold=1000

; 6. QoS / DSCP marking
; In rtp.conf:
[general]
tos_audio=ef           ; DSCP EF (Expedited Forwarding) for RTP
cos_audio=5            ; 802.1p CoS value

; In sip.conf:
[general]
tos_sip=cs3            ; DSCP CS3 for SIP signaling
cos_sip=3

Step-by-Step Fix

  1. Run ping test to the remote endpoint: ping -c 100 to check loss and jitter
  2. Enable RTP debug during a problem call: rtp set debug on
  3. Check server load: core show sysinfo and top (CPU should be <70%)
  4. Enable adaptive jitter buffer: jbenable=yes, jbimpl=adaptive
  5. Configure QoS/DSCP marking (tos_audio=ef) and ensure your network honors it
  6. Avoid transcoding: use the same codec end-to-end (check core show translation)
  7. Check bandwidth: each G.711 call needs ~87kbps; ensure enough headroom
  8. Use a dedicated VLAN for voice traffic to isolate from data
  9. Monitor ongoing quality with: asterisk -rx "rtp set debug on"

5. Dialplan Debugging

Problem: Calls are not routing correctly, extensions are not matching, or the dialplan executes unexpected paths. Calls go to the wrong context or fail with "No such extension."
Cause: Pattern matching errors, wrong context assignment for a peer, missing priorities in the dialplan, variable substitution failures, or include statements pointing to non-existent contexts.

Configuration / Commands

; === Dialplan debugging commands ===

; 1. Set high verbosity to see dialplan execution
asterisk -rx "core set verbose 5"

; 2. Show the dialplan for a specific context
asterisk -rx "dialplan show my-context"

; 3. Test pattern matching without making a call
asterisk -rx "dialplan show 15551234567@from-trunk"
; This shows which pattern would match

; 4. Show all contexts
asterisk -rx "dialplan show"

; 5. Add NoOp() for debugging in extensions.conf
[from-trunk]
exten => _X.,1,NoOp(== Incoming call: ${CALLERID(all)} -> ${EXTEN} in ${CONTEXT} ==)
 same => n,NoOp(Channel: ${CHANNEL}, Unique: ${UNIQUEID})
 same => n,Set(CDR(userfield)=debug)
 same => n,Verbose(2,Caller: ${CALLERID(num)} Ext: ${EXTEN})
 same => n,Goto(ivr-main,s,1)

; 6. Log specific events
exten => _X.,1,Log(NOTICE,Call from ${CALLERID(num)} to ${EXTEN})

; 7. Dump all channel variables
exten => _X.,1,DumpChan()

; 8. Common pattern matching reference
; _X.    = one or more digits (most greedy)
; _NXXNXXXXXX = 10-digit US number
; _1NXXNXXXXXX = 11-digit US number with 1 prefix
; _011. = international (011 + anything)
; _[2-9]XX = 3-digit starting with 2-9

Step-by-Step Fix

  1. Set verbose level to 5: core set verbose 5 in the Asterisk console
  2. Add NoOp() statements at key points to trace execution flow
  3. Use DumpChan() to see all channel variables at any point
  4. Test pattern matching: dialplan show <number>@<context>
  5. Check the peer's context= setting matches your intended dialplan context
  6. Verify include statements: ensure included contexts exist
  7. Check pattern priority: more specific patterns match before _X.
  8. Use Log() application for persistent debugging output in /var/log/asterisk/
  9. After changes, reload dialplan: dialplan reload

6. CDR and Call Recording Setup

Problem: Call Detail Records (CDR) are not being written to the database or CSV files. Call recordings are missing, incomplete, or saving in the wrong format/location.
Cause: CDR backend misconfigured, database connection down, insufficient disk space, wrong file permissions on recording directory, or MixMonitor/Monitor application not in the dialplan.

Configuration / Commands

; === CDR Configuration (cdr.conf) ===
[general]
enable=yes
unanswered=yes          ; Log unanswered calls too
congestion=yes          ; Log congested calls
endbeforehexten=yes     ; End CDR before h extension
batch=no                ; Write immediately (set yes for high volume)

; === CSV CDR (cdr_csv.conf) ===
[csv]
usegmtime=no
loguniqueid=yes
loguserfield=yes
accountlogs=no

; === MySQL CDR (cdr_mysql.conf) ===
[global]
hostname=localhost
dbname=asteriskcdr
table=cdr
user=asterisk
password=your_db_password
port=3306

; === Call Recording in dialplan (extensions.conf) ===
[from-trunk]
exten => _X.,1,Answer()
 same => n,Set(MONITOR_FILENAME=/var/spool/asterisk/monitor/${STRFTIME(${EPOCH},,%Y/%m/%d)}/${UNIQUEID})
 same => n,System(mkdir -p /var/spool/asterisk/monitor/${STRFTIME(${EPOCH},,%Y/%m/%d)})
 same => n,MixMonitor(${MONITOR_FILENAME}.wav,b)
 same => n,Dial(PJSIP/${EXTEN},30)
 same => n,StopMixMonitor()
 same => n,Hangup()

; Alternative: Record only after answer
exten => _X.,1,Dial(PJSIP/${EXTEN},30,U(record-call))
 same => n,Hangup()

[record-call]
exten => s,1,Set(MONITOR_FILENAME=/var/spool/asterisk/monitor/${UNIQUEID})
 same => n,MixMonitor(${MONITOR_FILENAME}.wav,b)
 same => n,Return()

Step-by-Step Fix

  1. Check CDR status: asterisk -rx "cdr show status"
  2. Verify database connection (for MySQL): test with mysql -u asterisk -p from the server
  3. Check disk space: df -h /var/spool/asterisk/
  4. Set proper permissions: chown -R asterisk:asterisk /var/spool/asterisk/monitor/
  5. Use MixMonitor() (not Monitor()) for combined audio in one file
  6. Create date-based subdirectories to organize recordings
  7. For high-volume systems, enable CDR batching: batch=yes with size=100
  8. Test CDR writing: make a test call, then check: asterisk -rx "cdr show status"
  9. For missing recordings, check: ls -la /var/spool/asterisk/monitor/

7. Fail2Ban for Asterisk Security

Problem: Asterisk is receiving brute-force SIP registration attempts, toll fraud calls, or scanning from botnets. The server logs show thousands of failed authentication attempts from unknown IPs.
Cause: SIP port 5060 is exposed to the internet. Attackers scan for open SIP servers and attempt to brute-force credentials to make unauthorized calls (toll fraud). Without protection, this can result in massive phone bills.

Configuration / Commands

; === Step 1: Configure Asterisk security logging ===
; /etc/asterisk/logger.conf
[logfiles]
security_log => security

; Reload logger:
; asterisk -rx "logger reload"

; === Step 2: Fail2Ban filter ===
; /etc/fail2ban/filter.d/asterisk.conf
[Definition]
failregex = SECURITY.* SecurityEvent="FailedACL".*RemoteAddress=".+//.+/<HOST>/.*"
            SECURITY.* SecurityEvent="InvalidAccountID".*RemoteAddress=".+//.+/<HOST>/.*"
            SECURITY.* SecurityEvent="ChallengeResponseFailed".*RemoteAddress=".+//.+/<HOST>/.*"
            SECURITY.* SecurityEvent="InvalidPassword".*RemoteAddress=".+//.+/<HOST>/.*"
            SECURITY.* SecurityEvent="ChallengeSent".*RemoteAddress=".+//.+/<HOST>/.*"

ignoreregex =

; === Step 3: Fail2Ban jail ===
; /etc/fail2ban/jail.d/asterisk.conf
[asterisk]
enabled  = true
filter   = asterisk
action   = iptables-allports[name=asterisk, protocol=all]
logpath  = /var/log/asterisk/security_log
maxretry = 3
findtime = 600
bantime  = 86400
ignoreip = 127.0.0.1/8 YOUR_OFFICE_IP

; === Step 4: Asterisk ACLs (additional layer) ===
; sip.conf
[general]
alwaysauthreject=yes     ; Don't reveal valid usernames
allowguest=no            ; Reject unauthenticated calls

; pjsip.conf - ACL
[acl]
type=acl
deny=0.0.0.0/0.0.0.0
permit=YOUR_OFFICE_IP/32
permit=YOUR_PROVIDER_IP/32

; === Step 5: Restart fail2ban ===
; systemctl restart fail2ban
; fail2ban-client status asterisk

Step-by-Step Fix

  1. Enable Asterisk security logging in logger.conf (security_log => security)
  2. Reload logger: asterisk -rx "logger reload"
  3. Create fail2ban filter at /etc/fail2ban/filter.d/asterisk.conf
  4. Create fail2ban jail at /etc/fail2ban/jail.d/asterisk.conf
  5. Set maxretry=3, bantime=86400 (24 hours), findtime=600 (10 minutes)
  6. Add your trusted IPs to ignoreip to avoid locking yourself out
  7. Set alwaysauthreject=yes in sip.conf to not reveal valid usernames
  8. Set allowguest=no to reject unauthenticated calls
  9. Restart fail2ban and verify: fail2ban-client status asterisk
  10. Monitor banned IPs: fail2ban-client status asterisk

8. TLS/SRTP Encrypted Calls Setup

Problem: SIP signaling and RTP audio are transmitted in plaintext, making them vulnerable to eavesdropping. Need to encrypt both signaling (TLS) and media (SRTP).
Cause: Default Asterisk configuration uses unencrypted UDP for SIP and unencrypted RTP for audio. Regulatory requirements (HIPAA, GDPR) or security policy may require encryption.

Configuration / Commands

; === Step 1: Generate TLS certificates ===
; Using Let's Encrypt (recommended):
; certbot certonly --standalone -d pbx.example.com
;
; Or self-signed (for testing):
mkdir -p /etc/asterisk/keys
cd /etc/asterisk/keys
openssl req -x509 -nodes -days 3650 \
  -newkey rsa:2048 \
  -keyout asterisk.key \
  -out asterisk.crt \
  -subj "/CN=pbx.example.com"
cat asterisk.crt asterisk.key > asterisk.pem
chmod 640 asterisk.pem asterisk.key
chown asterisk:asterisk asterisk.*

; === pjsip.conf - TLS Transport ===
[transport-tls]
type=transport
protocol=tls
bind=0.0.0.0:5061
cert_file=/etc/asterisk/keys/asterisk.crt
priv_key_file=/etc/asterisk/keys/asterisk.key
method=tlsv1_2
external_media_address=YOUR_PUBLIC_IP
external_signaling_address=YOUR_PUBLIC_IP
local_net=192.168.0.0/16

; === pjsip.conf - Encrypted Endpoint ===
[secure-phone]
type=endpoint
context=internal
transport=transport-tls
disallow=all
allow=ulaw,alaw
media_encryption=sdes        ; SRTP encryption
media_encryption_optimistic=no
auth=secure-phone-auth
aors=secure-phone-aor

[secure-phone-auth]
type=auth
auth_type=userpass
username=secure-phone
password=StrongPass!23

[secure-phone-aor]
type=aor
max_contacts=1
remove_existing=yes

; === sip.conf (legacy) - TLS ===
[general]
tlsenable=yes
tlsbindaddr=0.0.0.0:5061
tlscertfile=/etc/asterisk/keys/asterisk.pem
tlscafile=/etc/asterisk/keys/ca.crt
tlscipher=ALL
tlsclientmethod=tlsv1_2

[secure-peer]
type=peer
transport=tls
encryption=yes       ; Require SRTP
host=dynamic
qualify=yes

Step-by-Step Fix

  1. Generate TLS certificates (Let's Encrypt recommended for production)
  2. Set proper permissions: chown asterisk:asterisk on certificate files
  3. Configure TLS transport on port 5061 in pjsip.conf
  4. Set media_encryption=sdes on endpoints for SRTP
  5. Open firewall port 5061/TCP for TLS signaling
  6. Configure phones/softphones to use TLS transport and SRTP
  7. Test TLS: openssl s_client -connect pbx.example.com:5061
  8. Verify in Asterisk: pjsip show endpoints (check transport column)
  9. For WebRTC: use WSS (WebSocket Secure) with DTLS-SRTP

9. High Availability / Failover Setup

Problem: Single Asterisk server is a single point of failure. When it goes down, all phone service is lost. Need redundancy for production environments.
Cause: Hardware failure, software crash, network outage, or planned maintenance on a single server takes down the entire phone system.

Configuration / Commands

; === Option 1: DNS-based failover (simplest) ===
; Configure SIP phones with two servers:
; Primary: pbx1.example.com
; Secondary: pbx2.example.com
;
; In phone config:
; outbound_proxy=pbx1.example.com
; fallback_proxy=pbx2.example.com

; === Option 2: Corosync/Pacemaker cluster ===
; Install on both nodes:
; yum install corosync pacemaker pcs
;
; Configure shared/floating IP:
; pcs resource create ClusterIP ocf:heartbeat:IPaddr2 \
;   ip=192.168.1.100 cidr_netmask=24 \
;   op monitor interval=30s

; === Option 3: Database replication (for Realtime) ===
; Use MySQL/MariaDB replication for Asterisk Realtime
; Master (pbx1): /etc/my.cnf
[mysqld]
server-id=1
log-bin=mysql-bin
binlog-do-db=asterisk

; Slave (pbx2): /etc/my.cnf
[mysqld]
server-id=2
relay-log=relay-bin
read-only=1

; === Option 4: Shared filesystem for configs ===
; Use GlusterFS or NFS for shared config and recordings
; /etc/fstab on both nodes:
; nfs-server:/asterisk-shared /etc/asterisk nfs defaults 0 0

; === Monitoring script (keepalive check) ===
#!/bin/bash
# /usr/local/bin/asterisk-check.sh
if ! asterisk -rx "core show version" > /dev/null 2>&1; then
    systemctl restart asterisk
    sleep 5
    if ! asterisk -rx "core show version" > /dev/null 2>&1; then
        # Failover: release floating IP
        ip addr del 192.168.1.100/24 dev eth0
        # Alert admin
        echo "Asterisk DOWN on $(hostname)" | mail -s "PBX Alert" admin@example.com
    fi
fi

Step-by-Step Fix

  1. Choose HA strategy: DNS failover (simple) vs Corosync/Pacemaker (advanced)
  2. For DNS failover: configure phones with primary and secondary SIP servers
  3. For Pacemaker: install corosync and pacemaker on both nodes
  4. Set up a floating/virtual IP that moves between nodes
  5. Replicate database (MySQL replication) for Realtime configurations
  6. Share call recordings via NFS or GlusterFS
  7. Sync configuration files with rsync or shared filesystem
  8. Create monitoring scripts for automated failover
  9. Test failover by stopping Asterisk on primary and verifying calls route to secondary

10. Queue and Agent Configuration

Problem: Call queues are not distributing calls correctly, agents are not receiving calls, or queue statistics are not accurate. Hold times are too long.
Cause: Queue strategy misconfigured, agents not logged in or paused, penalty settings blocking call delivery, or wrapup time too long between calls.

Configuration / Commands

; === queues.conf ===
[general]
persistentmembers=yes        ; Remember dynamic members across restarts
autofill=yes                 ; Distribute calls to all available agents
shared_lastcall=yes          ; Share lastcall info across queues
log_membername_as_agent=yes

[sales-queue]
musicclass=default
strategy=rrmemory            ; Round-robin with memory
timeout=15                   ; Ring agent for 15 seconds
retry=5                      ; Wait 5 seconds before trying next agent
wrapuptime=10                ; 10 second wrap-up between calls
maxlen=0                     ; Unlimited queue length (0=unlimited)
weight=2                     ; Higher priority queue
announce-frequency=30        ; Announce position every 30 seconds
announce-holdtime=yes
announce-position=yes
joinempty=yes                ; Allow callers to join even if no agents
leavewhenempty=no
ringinuse=no                 ; Don't ring agents already on a call

; Static members
member => PJSIP/100,0,Agent Smith,SIP/100
member => PJSIP/101,0,Agent Jones,SIP/101

; === agents.conf (if using Agent channel) ===
[agents]
maxlogintries=3
autologoff=60
wrapuptime=10

; === Dialplan for queue (extensions.conf) ===
[incoming]
exten => s,1,Answer()
 same => n,Set(CHANNEL(language)=en)
 same => n,Queue(sales-queue,tTcC,,,300)
 same => n,VoiceMail(100@default,u)
 same => n,Hangup()

; Dynamic agent login/logout
exten => *100,1,NoOp(Agent Login/Logout)
 same => n,Set(QUEUEMEMBER=PJSIP/${CALLERID(num)})
 same => n,GotoIf($[${QUEUE_MEMBER(${QUEUEMEMBER},sales-queue,status)} = 0]?login)
 same => n,RemoveQueueMember(sales-queue,${QUEUEMEMBER})
 same => n,Playback(agent-loggedoff)
 same => n,Hangup()
 same => n(login),AddQueueMember(sales-queue,${QUEUEMEMBER})
 same => n,Playback(agent-loginok)
 same => n,Hangup()

; Agent pause/unpause
exten => *101,1,PauseQueueMember(sales-queue,PJSIP/${CALLERID(num)},,Break)
 same => n,Playback(beep)
 same => n,Hangup()
exten => *102,1,UnpauseQueueMember(sales-queue,PJSIP/${CALLERID(num)})
 same => n,Playback(beep)
 same => n,Hangup()

Step-by-Step Fix

  1. Choose a queue strategy: ringall, rrmemory, leastrecent, fewestcalls, random, or wrandom
  2. Set autofill=yes in [general] to distribute multiple waiting calls simultaneously
  3. Set ringinuse=no to avoid ringing agents already on a call
  4. Configure appropriate timeout (ring time) and retry (pause between attempts)
  5. Set wrapuptime to give agents time between calls (10-30 seconds typical)
  6. Use persistentmembers=yes to remember dynamic agents across restarts
  7. Create dialplan extensions for agent login (*100), pause (*101), unpause (*102)
  8. Monitor queues: asterisk -rx "queue show" or "queue show sales-queue"
  9. Check agent status: asterisk -rx "queue show" and look for (Not in use) vs (In use)

11. Calls Dropping After 30 Seconds

Problem: Calls connect successfully with audio, but consistently drop after exactly 30 seconds (or another fixed interval like 32 or 60 seconds).
Cause: SIP ACK not reaching Asterisk due to NAT or firewall. After sending 200 OK, Asterisk waits for ACK. If it does not arrive within the timer, Asterisk hangs up. Can also be caused by session timers or qualify timeout.

Configuration / Commands

; === Fix 1: NAT settings (most common cause) ===
; sip.conf
[general]
nat=force_rport,comedia
directmedia=no

; pjsip.conf
[my-endpoint]
type=endpoint
rtp_symmetric=yes
force_rport=yes
rewrite_contact=yes
direct_media=no

; === Fix 2: Disable SIP session timers ===
; sip.conf
[general]
session-timers=refuse    ; or "originate" if you need them

; pjsip.conf
[my-endpoint]
type=endpoint
timers=no                ; Disable session timers
; or set a longer session timer:
timers_sess_expires=1800 ; 30 minutes

; === Fix 3: Firewall - allow established connections ===
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p udp --dport 5060 -j ACCEPT
iptables -A INPUT -p udp --dport 10000:20000 -j ACCEPT

; === Fix 4: Disable SIP ALG on router ===
; This is router-specific. Common commands:
; Mikrotik: /ip firewall service-port disable sip
; Linux iptables: modprobe -r nf_nat_sip nf_conntrack_sip

Step-by-Step Fix

  1. Check if the drop is exactly 30/32 seconds (SIP timer issue) or variable
  2. Enable SIP debug and watch for missing ACK after 200 OK
  3. Configure NAT settings: force_rport, comedia, directmedia=no
  4. Disable SIP ALG on your router/firewall (most common root cause)
  5. Try disabling session timers: session-timers=refuse (sip.conf) or timers=no (pjsip.conf)
  6. Verify firewall allows ESTABLISHED/RELATED connections
  7. Check if qualify timeout is causing disconnects: set qualifyfreq=25

12. Codec Mismatch / 488 Errors

Problem: Calls fail with SIP 488 "Not Acceptable Here" or 606 "Not Acceptable". No common codec can be negotiated between endpoints.
Cause: The calling and called endpoints have no codec in common. One side offers only G.729 while the other only supports G.711, or the disallow/allow order is wrong.

Configuration / Commands

; === Always disallow all first, then allow specific codecs ===

; sip.conf
[general]
disallow=all
allow=ulaw       ; G.711 ulaw (North America)
allow=alaw       ; G.711 alaw (Europe/International)
allow=g729       ; G.729 (if module installed)
allow=gsm        ; GSM (low bandwidth fallback)

; For a specific peer that only supports G.729:
[g729-only-trunk]
type=peer
disallow=all
allow=g729
allow=ulaw       ; Always add a fallback!

; pjsip.conf
[my-endpoint]
type=endpoint
disallow=all
allow=ulaw,alaw,g729

; === Check current codec negotiation ===
; asterisk -rx "core show codecs"
; asterisk -rx "core show translation"
; asterisk -rx "sip show peer <name>"  (look for "Codecs" line)
; asterisk -rx "pjsip show endpoint <name>"

; === Common codec priority for compatibility ===
; Best practice: offer multiple codecs in priority order
disallow=all
allow=g729    ; Preferred for WAN (low bandwidth)
allow=ulaw    ; Fallback (highest compatibility)
allow=alaw    ; Fallback for European systems

Step-by-Step Fix

  1. Always use disallow=all before allow= directives
  2. Add at least 2-3 codecs for fallback compatibility
  3. Check what codecs the remote side supports (ask your SIP provider)
  4. Verify codec module is loaded: module show like codec
  5. Check negotiated codecs during a call: core show channels verbose
  6. For G.729, ensure codec_g729.so is loaded (see our G.729 installation guide)
  7. List codecs in priority order (first = preferred)

13. Asterisk Won't Start

Problem: Asterisk fails to start or crashes immediately after starting. Systemctl shows the service as failed.
Cause: Configuration syntax errors, port 5060 already in use by another process, missing modules, permission issues on files/directories, or corrupted AstDB.

Configuration / Commands

; === Debugging startup failures ===

; 1. Start Asterisk in foreground with verbose output:
asterisk -cvvvvv
; This shows all errors during startup

; 2. Check for port conflicts:
ss -tulnp | grep 5060
; or
netstat -tulnp | grep 5060
; Kill any conflicting process

; 3. Check configuration syntax:
asterisk -C /etc/asterisk/asterisk.conf -cvvv
; Look for "ERROR" or "WARNING" lines

; 4. Check file permissions:
ls -la /var/run/asterisk/
ls -la /var/lib/asterisk/
ls -la /var/log/asterisk/
ls -la /var/spool/asterisk/
; All should be owned by asterisk:asterisk

; Fix permissions:
chown -R asterisk:asterisk /var/lib/asterisk
chown -R asterisk:asterisk /var/log/asterisk
chown -R asterisk:asterisk /var/run/asterisk
chown -R asterisk:asterisk /var/spool/asterisk
chown -R asterisk:asterisk /etc/asterisk

; 5. Check for corrupted AstDB:
ls -la /var/lib/asterisk/astdb.sqlite3
; If corrupted, rename and restart:
; mv /var/lib/asterisk/astdb.sqlite3 /var/lib/asterisk/astdb.sqlite3.bak

; 6. Check system logs:
journalctl -u asterisk -n 50
tail -50 /var/log/asterisk/messages

Step-by-Step Fix

  1. Start Asterisk in foreground: asterisk -cvvvvv to see all startup errors
  2. Check for port 5060 conflicts: ss -tulnp | grep 5060
  3. Verify file permissions: all Asterisk directories owned by asterisk:asterisk
  4. Check for config syntax errors in the verbose output
  5. Look for missing module errors and install missing dependencies
  6. Check system logs: journalctl -u asterisk -n 50
  7. If AstDB is corrupted, rename it and restart to create a fresh one
  8. Verify SELinux is not blocking: setenforce 0 (temporary) or fix policies

14. DTMF (Keypad) Not Working

Problem: Pressing keys during a call (IVR menus, voicemail PIN, conference controls) does not register or registers incorrectly. DTMF tones are heard but not detected by Asterisk.
Cause: DTMF mode mismatch between endpoints. In-band DTMF can be distorted by compression codecs (G.729, GSM). Different endpoints may use RFC 2833, SIP INFO, or in-band, and they must match.

Configuration / Commands

; === sip.conf - DTMF configuration ===
[general]
dtmfmode=rfc2833         ; Recommended for most scenarios

[my-peer]
dtmfmode=rfc2833         ; RFC 2833 (out-of-band, in RTP)
; Other options:
; dtmfmode=info          ; SIP INFO method (not recommended)
; dtmfmode=inband        ; In-band audio (codec-dependent, unreliable)
; dtmfmode=auto          ; Auto-detect (can cause issues)

; === pjsip.conf - DTMF configuration ===
[my-endpoint]
type=endpoint
dtmf_mode=rfc4733        ; RFC 4733 (same as RFC 2833, updated standard)
; Other options:
; dtmf_mode=info         ; SIP INFO
; dtmf_mode=inband       ; In-band
; dtmf_mode=auto         ; Auto-detect
; dtmf_mode=auto_info    ; Try RFC4733 first, fall back to INFO

; === Debugging DTMF ===
; In Asterisk console:
asterisk -rx "core set verbose 5"
; Make a call and press keys - look for:
; "DTMF begin '1' received on channel..."
; If you see nothing, DTMF is not reaching Asterisk

; Test DTMF with a simple IVR:
[dtmf-test]
exten => 999,1,Answer()
 same => n,Read(digit,,1,,,5)
 same => n,SayDigits(${digit})
 same => n,Goto(999,1)

Step-by-Step Fix

  1. Set dtmfmode=rfc2833 (sip.conf) or dtmf_mode=rfc4733 (pjsip.conf) on both sides
  2. Ensure both endpoints use the SAME DTMF method
  3. If using G.729 or other compressed codecs, NEVER use inband DTMF
  4. Enable verbose logging and test: look for "DTMF begin" messages in console
  5. Create a test extension that reads and plays back DTMF to verify detection
  6. Check phone/softphone settings to match the server's DTMF mode
  7. For SIP trunks, ask the provider which DTMF mode they support

15. Voicemail Configuration and Email

Problem: Voicemail is not recording messages, email notifications are not being sent, or voicemail messages cannot be retrieved by users.
Cause: Voicemail context mismatch, missing mail configuration (sendmail/postfix), wrong file permissions on voicemail spool directory, or SMTP blocked by firewall.

Configuration / Commands

; === voicemail.conf ===
[general]
format=wav49|wav|gsm      ; Recording formats (wav49 for email attachment)
serveremail=pbx@example.com
attach=yes                 ; Attach voicemail to email
maxmsg=100                 ; Max messages per mailbox
maxsecs=180                ; Max recording length (seconds)
minsecs=3                  ; Min recording length
maxgreet=60                ; Max greeting length
skipms=3000                ; Skip forward/back milliseconds
maxsilence=10              ; Hang up after 10 seconds of silence
emailsubject=[PBX] New voicemail from ${VM_CALLERID}
emailbody=You have a new voicemail:\n\nFrom: ${VM_CALLERID}\nDate: ${VM_DATE}\nDuration: ${VM_DUR}\n\n
emaildateformat=%A, %B %d, %Y at %r
pollmailboxes=yes          ; For MWI (Message Waiting Indicator)
pollfreq=15

; Mailbox definitions
[default]
100 => 1234,John Smith,john@example.com,,attach=yes|tz=eastern
101 => 5678,Jane Doe,jane@example.com,,attach=yes|tz=eastern
102 => 0000,Bob Wilson,bob@example.com,,attach=yes|delete=yes

; === Dialplan (extensions.conf) ===
[internal]
; Send to voicemail on no answer
exten => _1XX,1,Dial(PJSIP/${EXTEN},20)
 same => n,VoiceMail(${EXTEN}@default,u)  ; u=unavailable
 same => n,Hangup()

; Direct to voicemail (busy)
exten => _1XX,1,VoiceMail(${EXTEN}@default,b)  ; b=busy

; Check voicemail
exten => *98,1,VoiceMailMain(${CALLERID(num)}@default)
 same => n,Hangup()

; Check any mailbox
exten => *99,1,VoiceMailMain(@default)
 same => n,Hangup()

Step-by-Step Fix

  1. Configure mailboxes in voicemail.conf with passwords and email addresses
  2. Set format=wav49|wav for email-friendly attachments
  3. Install and configure sendmail or postfix for email delivery
  4. Test email: echo "test" | mail -s "test" your@email.com
  5. Check permissions: chown -R asterisk:asterisk /var/spool/asterisk/voicemail/
  6. Ensure the mailbox context in dialplan matches voicemail.conf context
  7. Set attach=yes and configure emailsubject/emailbody templates
  8. Test: call an extension, let it go to voicemail, check for email delivery
  9. For MWI (blinking light): set pollmailboxes=yes and pollfreq=15

16. Music on Hold Not Playing

Problem: Callers on hold hear silence instead of music. Music on Hold (MOH) was working but stopped after an update or configuration change.
Cause: MOH files missing or in wrong format, musiconhold.conf misconfigured, file permissions wrong, or the MOH class referenced in the dialplan does not exist.

Configuration / Commands

; === musiconhold.conf ===
[general]

[default]
mode=files
directory=/var/lib/asterisk/moh
sort=random

[custom-hold]
mode=files
directory=/var/lib/asterisk/moh/custom
sort=alpha

; === Converting audio files to correct format ===
; Asterisk needs specific audio formats. Best practice:
; WAV: 16-bit, 8000Hz, mono, PCM
; Using sox:
sox input.mp3 -r 8000 -c 1 -t wav output.wav

; Using ffmpeg:
ffmpeg -i input.mp3 -ar 8000 -ac 1 -acodec pcm_s16le output.wav

; Convert entire directory:
for f in *.mp3; do
  sox "$f" -r 8000 -c 1 -t wav "/var/lib/asterisk/moh/custom/$(basename "$f" .mp3).wav"
done

; Set permissions:
chown -R asterisk:asterisk /var/lib/asterisk/moh/
chmod 644 /var/lib/asterisk/moh/*.wav

; === Test MOH ===
; asterisk -rx "moh show classes"
; asterisk -rx "moh show files"
; asterisk -rx "moh reload"

Step-by-Step Fix

  1. Check if files exist: ls -la /var/lib/asterisk/moh/
  2. Verify file format: file /var/lib/asterisk/moh/*.wav (should be 8000Hz, mono, PCM)
  3. Convert files to proper format using sox or ffmpeg (8000Hz, mono, 16-bit WAV)
  4. Set correct permissions: chown asterisk:asterisk on all MOH files
  5. Verify MOH configuration: asterisk -rx "moh show classes"
  6. Check that the MOH class used in dialplan exists: moh show files
  7. Reload MOH: asterisk -rx "moh reload"
  8. Test in dialplan: MusicOnHold(default) should play files from the default class

17. WebRTC Calls Setup

Problem: Need to enable browser-based voice/video calls using WebRTC. Calls fail with ICE errors, no audio, or TLS handshake failures.
Cause: WebRTC requires a specific stack: WSS (WebSocket Secure), DTLS-SRTP, ICE/STUN/TURN. Missing any component causes failure. Valid TLS certificates are mandatory (self-signed won't work in browsers).

Configuration / Commands

; === http.conf - Enable WebSocket ===
[general]
enabled=yes
bindaddr=0.0.0.0
bindport=8088
tlsenable=yes
tlsbindaddr=0.0.0.0:8089
tlscertfile=/etc/letsencrypt/live/pbx.example.com/fullchain.pem
tlsprivatekey=/etc/letsencrypt/live/pbx.example.com/privkey.pem

; === pjsip.conf - WebSocket transport ===
[transport-wss]
type=transport
protocol=wss
bind=0.0.0.0

; === pjsip.conf - WebRTC endpoint ===
[webrtc-phone]
type=endpoint
context=internal
disallow=all
allow=opus,ulaw          ; Opus is preferred for WebRTC
webrtc=yes               ; Shortcut that enables:
                         ;   use_avpf=yes
                         ;   media_encryption=dtls
                         ;   dtls_auto_generate_cert=yes (or manual certs)
                         ;   ice_support=yes
                         ;   media_use_received_transport=yes
                         ;   rtcp_mux=yes
transport=transport-wss
auth=webrtc-phone-auth
aors=webrtc-phone-aor

[webrtc-phone-auth]
type=auth
auth_type=userpass
username=webrtc
password=SecureWebRTC!23

[webrtc-phone-aor]
type=aor
max_contacts=5
remove_existing=yes

; === Firewall rules ===
; Open WSS port
iptables -A INPUT -p tcp --dport 8089 -j ACCEPT
; Open RTP ports
iptables -A INPUT -p udp --dport 10000:20000 -j ACCEPT

Step-by-Step Fix

  1. Get a valid TLS certificate (Let's Encrypt) - self-signed will NOT work in browsers
  2. Enable HTTPS WebSocket in http.conf (port 8089 for WSS)
  3. Create a WSS transport in pjsip.conf
  4. Configure WebRTC endpoint with webrtc=yes (enables DTLS-SRTP, ICE, AVPF, RTCP-MUX)
  5. Use Opus codec for best WebRTC quality
  6. Open firewall ports: 8089/TCP (WSS) and 10000-20000/UDP (RTP)
  7. Configure STUN server (or deploy your own TURN server for restrictive NATs)
  8. Test with a WebRTC client like SIP.js or JsSIP
  9. Debug with browser developer tools: check WebSocket connection and ICE candidates

18. Migrating from chan_sip to PJSIP

Problem: Running legacy chan_sip (sip.conf) which is deprecated since Asterisk 17 and removed in Asterisk 21. Need to migrate to PJSIP without disrupting service.
Cause: chan_sip is no longer maintained, lacks WebRTC support, has limited multi-transport capability, and will not receive security updates.

Configuration / Commands

; === Mapping sip.conf concepts to pjsip.conf ===

; --- sip.conf peer ---
[my-phone]
type=friend
host=dynamic
username=100
secret=MyPassword
context=internal
disallow=all
allow=ulaw,alaw
nat=force_rport,comedia
qualify=yes
dtmfmode=rfc2833

; --- Equivalent pjsip.conf ---
; One sip.conf [peer] becomes FOUR pjsip sections:

[my-phone]                ; ENDPOINT
type=endpoint
context=internal
disallow=all
allow=ulaw,alaw
auth=my-phone-auth
aors=my-phone
dtmf_mode=rfc4733
rtp_symmetric=yes
force_rport=yes
rewrite_contact=yes
direct_media=no

[my-phone-auth]           ; AUTH
type=auth
auth_type=userpass
username=100
password=MyPassword

[my-phone]                ; AOR (Address of Record)
type=aor
max_contacts=1
qualify_frequency=30
remove_existing=yes

[my-phone-identify]       ; IDENTIFY (for IP matching)
type=identify
endpoint=my-phone
match=dynamic              ; Not needed for dynamic/registering phones

; === SIP Trunk mapping ===
; sip.conf:
; register => user:pass@provider.com
;
; pjsip.conf:
[my-trunk-reg]
type=registration
outbound_auth=my-trunk-auth
server_uri=sip:provider.com
client_uri=sip:user@provider.com

[my-trunk-auth]
type=auth
auth_type=userpass
username=user
password=pass

[my-trunk]
type=endpoint
context=from-trunk
disallow=all
allow=ulaw,alaw
outbound_auth=my-trunk-auth
aors=my-trunk-aor

[my-trunk-aor]
type=aor
contact=sip:provider.com

[my-trunk-identify]
type=identify
endpoint=my-trunk
match=provider.com

Step-by-Step Fix

  1. Document all current sip.conf peers, trunks, and registrations
  2. Map each sip.conf [peer] to four pjsip sections: endpoint, auth, aor, identify
  3. Convert register => lines to pjsip type=registration sections
  4. Update dialplan: change SIP/ channel references to PJSIP/
  5. Update dialplan: ${SIPCHANINFO()} becomes ${CHANNEL(pjsip,...)}
  6. Test each phone and trunk individually before going live
  7. In modules.conf: noload => chan_sip.so to prevent conflicts
  8. Reload PJSIP: asterisk -rx "pjsip reload"
  9. Verify all endpoints: asterisk -rx "pjsip show endpoints"

19. Call Parking and Pickup

Problem: Call parking is not working, parked calls are not retrievable, or the parking lot timeout is too short causing calls to bounce back.
Cause: res_parking module not loaded, parking lot misconfigured, extension conflicts with parking slots, or timeout set too low.

Configuration / Commands

; === res_parking.conf (Asterisk 12+) ===
[general]
parkeddynamic=yes

[default]
parkext => 700              ; Dial 700 to park a call
parkpos => 701-720          ; Parking slots 701 through 720
context => parkedcalls      ; Context for retrieving parked calls
parkinghints => yes         ; Enable BLF hints for parking slots
parkingtime => 120          ; Timeout in seconds (2 minutes)
comebacktoorigin => yes     ; Ring back original parker on timeout
comebackcontext => default  ; Context for comeback
courtesytone => beep        ; Tone played when call is picked up
parkedplay => both          ; Who hears the courtesytone
parkedmusicclass => default ; MOH for parked calls

; === Dialplan for parking (extensions.conf) ===
[internal]
; Include parked calls context
include => parkedcalls

; Directed call pickup (pick up a ringing phone)
exten => *8,1,Pickup()                 ; Pick up any ringing call
exten => **,1,Pickup(${EXTEN:2}@internal) ; Pick up specific extension

; Park via feature code (during call, press #700)
; This is configured in features.conf:
; [general]
; parkext = #700

; === features.conf (for in-call feature codes) ===
[general]
parkext = #700              ; Feature code to park during a call
parkcall => default         ; Which parking lot to use

[featuremap]
blindxfer => ##             ; Blind transfer
atxfer => *2                ; Attended transfer
parkcall => #700            ; Park call
pickup => *8                ; Call pickup

Step-by-Step Fix

  1. Verify res_parking is loaded: module show like parking
  2. Configure res_parking.conf with park extension (700) and slot range (701-720)
  3. Include the parkedcalls context in your dialplan: include => parkedcalls
  4. Set appropriate parkingtime (120 seconds recommended)
  5. Enable comebacktoorigin=yes so timed-out calls ring back the parker
  6. Configure BLF hints with parkinghints=yes for visual parking status
  7. Test: dial 700 during a call to park, then dial the slot number (701) to retrieve
  8. For directed pickup: configure *8 or a custom pickup extension

20. AMI/ARI External Integration

Problem: External applications cannot connect to Asterisk for call control, monitoring, or integration. AMI connection refused or ARI returning 403 errors.
Cause: manager.conf or ari.conf not configured, wrong credentials, ACL blocking the connection, or HTTP server not enabled for ARI.

Configuration / Commands

; === manager.conf (AMI) ===
[general]
enabled=yes
port=5038
bindaddr=0.0.0.0          ; Or specific IP for security
displayconnects=yes
timestampevents=yes

[myapp]
secret=SuperSecretPass!
read=system,call,log,agent,user,config,dtmf,reporting,cdr,dialplan
write=system,call,agent,user,config,originate,reporting
deny=0.0.0.0/0.0.0.0
permit=192.168.1.0/255.255.255.0
permit=127.0.0.1/255.255.255.255
writetimeout=5000
eventfilter=!Event: RTCP*  ; Filter out noisy RTCP events
eventfilter=!Event: VarSet  ; Filter out VarSet events

; === ari.conf ===
[general]
enabled=yes
pretty=yes
allowed_origins=https://myapp.example.com

[myariuser]
type=user
read_only=no
password=AriSecretPass!

; === http.conf (required for ARI) ===
[general]
enabled=yes
bindaddr=0.0.0.0
bindport=8088
tlsenable=yes
tlsbindaddr=0.0.0.0:8089
tlscertfile=/etc/asterisk/keys/asterisk.crt
tlsprivatekey=/etc/asterisk/keys/asterisk.key

; === Test AMI connection ===
; telnet localhost 5038
; Action: Login
; Username: myapp
; Secret: SuperSecretPass!
;
; Action: Ping

; === Test ARI connection ===
; curl -u myariuser:AriSecretPass! http://localhost:8088/ari/asterisk/info
;
; WebSocket for events:
; wscat -c "ws://localhost:8088/ari/events?api_key=myariuser:AriSecretPass!&app=myapp"

Step-by-Step Fix

  1. For AMI: enable in manager.conf, create a user with appropriate read/write permissions
  2. For ARI: enable in ari.conf, ensure http.conf is also enabled
  3. Set strict ACLs: deny=0.0.0.0/0.0.0.0 then permit only specific IPs
  4. Use eventfilter to reduce noisy events (RTCP, VarSet)
  5. Test AMI: telnet localhost 5038 and send Login action
  6. Test ARI: curl -u user:pass http://localhost:8088/ari/asterisk/info
  7. For ARI WebSocket events: connect to ws://host:8088/ari/events?api_key=user:pass&app=name
  8. Open firewall: 5038/TCP for AMI, 8088/TCP (or 8089 for HTTPS) for ARI
  9. Use TLS for production: configure http.conf with valid certificates
Asterisk is a registered trademark of Sangoma Technologies. Configuration examples are for educational purposes. Always test changes in a non-production environment first.