← All Tutorials

SIP 403 Forbidden Error — Trunk Authentication Troubleshooting

Infrastructure & DevOps Intermediate 12 min read #82

Master the complete diagnostic and resolution process for SIP 403 Forbidden errors affecting your ViciDial trunks and Asterisk SIP authentication

Overview

A SIP 403 Forbidden error indicates that your Asterisk server attempted to authenticate with a remote SIP trunk provider, but the credentials or authorization rules were rejected. In ViciDial production environments, this manifests as failed outbound calls, dropped inbound routes, and frustrated agents seeing "trunk unavailable" errors.

This tutorial covers the exact troubleshooting methodology used in production ViciDial deployments running hundreds of concurrent calls. You'll learn to diagnose root causes, modify configurations, validate changes, and implement monitoring to prevent future occurrences.

Prerequisites

Understanding SIP 403 Forbidden in Context

What Causes 403 Forbidden Errors

A 403 Forbidden response in SIP means the upstream server understood your request but refused to authorize it. Unlike 401 (Unauthorized, requiring credentials) or 407 (Proxy Authentication Required), a 403 indicates:

Where ViciDial Processes Trunk Authentication

ViciDial manages trunks through:

  1. SIP Configuration Files: /etc/asterisk/sip-vicidial.conf contains peer definitions
  2. Database: vicidial_carrier_log and trunk definitions in Asterisk dialplan
  3. Extensions Dialplan: /etc/asterisk/extensions-vicidial.conf routes calls through specific trunks
  4. Asterisk Core: Processes authentication before sending requests upstream

ViciDial Trunk Configuration Structure

Database Trunk Definition

First, verify your trunk exists in the database:

SELECT * FROM vicidial_list WHERE list_id = 'YOUR_TRUNK_ID'\G

For carrier-level configuration, check:

SELECT carrier_id, carrier_name, auth_type, carrier_user, carrier_pass, ip_address FROM vicidial_carrier_log ORDER BY date_added DESC LIMIT 10;

SIP Peer Configuration

Locate your trunk definition in /etc/asterisk/sip-vicidial.conf:

[mytrunksip]
type=peer
host=sip.provider.com
port=5060
username=youraccountname
secret=yourpassword
fromuser=youraccountname
fromdomain=sip.provider.com
context=from-trunk
insecure=port,invite
qualify=yes
qualifyfreq=60
canreinvite=no
dtmfmode=rfc2833
nat=force_rport,comedia
directmedia=no

Key fields related to 403 errors:

Step 1: Locate and Review SIP Trunk Logs

Enable SIP Debug Logging

First, enable full SIP debugging to capture the actual 403 response:

asterisk -rx "sip set debug on"

Generate a test call and watch the console output in real-time:

tail -f /var/log/asterisk/messages | grep -i "sip\|forbidden\|auth"

Capture Full SIP Trace

For detailed analysis, use tcpdump to capture the raw SIP messages:

sudo tcpdump -i any -s 0 -w /tmp/sip_trace.pcap \
  'host sip.provider.com and port 5060'

Run a test call, then stop the capture (Ctrl+C).

Convert to readable format:

sudo tshark -r /tmp/sip_trace.pcap -Y sip -O sip > /tmp/sip_trace.txt

Review the trace for the exact 403 response:

grep -A 5 -B 5 "403\|Forbidden" /tmp/sip_trace.txt

Asterisk Verbose Logging

Enable Asterisk verbose mode to log SIP transactions:

asterisk -rx "core set verbose 10"

This produces output in /var/log/asterisk/messages. Monitor during test calls:

tail -100 /var/log/asterisk/messages | grep -E "INVITE|SIP/2.0 403|Trying|Calling"

Step 2: Validate Credentials Against Provider

Verify Provider-Supplied Values

Contact your SIP trunk provider and confirm:

  1. Account Username: Case-sensitive, no spaces
  2. Password/Secret: Exactly as configured in their system
  3. Outbound Proxy/Host: SIP server address and port
  4. Your IP Address(es): Whitelisted on their system
  5. DID/Extension: Authorized for your account
  6. Authentication Method: Digest, Basic, or IP-based

Example request to provider:

"We're receiving 403 Forbidden errors from sip.provider.com when authenticating with username 'accountname'. Can you confirm: (1) the exact password configured for this account, (2) whether IP whitelisting is enabled, (3) what our outbound IP should be, (4) the correct SIP URI format for requests?"

Test With SIPp (SIP Protocol Tester)

Use the sipp tool to test authentication independently:

sudo apt-get install sipp

Create a test scenario file /tmp/test_sip.xml:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<scenario name="Basic SIP UAC">
  <send retrans="500">
    <![CDATA[
      INVITE sip:[email protected] SIP/2.0
      Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
      From: <sip:[email protected]>;tag=[call_number]
      To: <sip:[email protected]>
      Call-ID: [call_id]
      CSeq: 1 INVITE
      Contact: <sip:[local_ip]:[local_port]>
      Max-Forwards: 70
      User-Agent: Test SIPp
      Content-Length: 0
    ]]>
  </send>
  <recv response="403" />
</scenario>

Run the test:

sipp -sf /tmp/test_sip.xml -s sip.provider.com -p 5060 -ap youraccountname:yourpassword your_local_ip

This tests basic SIP authentication without Asterisk complexity.

Step 3: Check Credential Configuration in ViciDial

Review SIP Configuration File

Open your trunk definition:

grep -A 20 "\[mytrunksip\]" /etc/asterisk/sip-vicidial.conf

Look for:

username=youraccountname
secret=yourpassword

Common mistakes:

Verify From: Header Construction

The From: header must match provider expectations:

fromuser=youraccountname
fromdomain=sip.provider.com

This constructs: From: "youraccountname" <sip:[email protected]>

Provider may require:

Check Extensions Dialplan

Verify your trunk is invoked correctly in /etc/asterisk/extensions-vicidial.conf:

exten => _9XXXXXXXX,1,Dial(SIP/${EXTEN:1}@mytrunksip)
exten => _9XXXXXXXX,n,Hangup()

The @mytrunksip reference must match your peer definition exactly (case-sensitive).

Step 4: Diagnose IP and Network Issues

Verify Outbound IP Address

Your Asterisk server's outbound IP must match what the provider has whitelisted:

curl -s https://api.ipify.org

Or from within Asterisk:

asterisk -rx "sip show settings" | grep "Bindaddr"

Compare this IP against your provider's whitelist.

Test Network Connectivity

Verify basic connectivity to the SIP server:

ping -c 3 sip.provider.com

Test port-level connectivity:

nc -zv sip.provider.com 5060

Check if firewall rules permit SIP traffic:

sudo iptables -L -n | grep 5060

For proper SIP NAT traversal, ensure:

[mytrunksip]
nat=force_rport,comedia
directmedia=no

Verify DNS Resolution

Confirm the provider's hostname resolves correctly:

nslookup sip.provider.com
dig sip.provider.com @8.8.8.8

DNS issues can cause timeouts that look like authentication failures.

Step 5: Resolve Common 403 Scenarios

Scenario A: Credential Mismatch

Symptom: 403 response immediately upon sending INVITE.

Resolution:

  1. Request fresh credentials from provider
  2. Update both username and secret fields:
sudo vi /etc/asterisk/sip-vicidial.conf
  1. If password contains special characters, escape properly:
secret="pa$$w0rd@2024!"
  1. Reload SIP configuration:
asterisk -rx "sip reload"
  1. Test a call and monitor logs:
asterisk -rx "sip set debug on"
# Make test call
asterisk -rx "sip set debug off"

Scenario B: IP Whitelisting

Symptom: 403 error after successful authentication attempts, only from specific network.

Resolution:

  1. Confirm your public IP:
wget -qO- https://checkip.amazonaws.com
  1. Contact provider to whitelist this IP
  2. If using failover/redundancy, whitelist all potential outbound IPs
  3. Test after provider confirms whitelist update:
asterisk -rx "sip qualify mytrunksip"

Scenario C: Rate Limiting/Blacklisting

Symptom: 403 after initial successful calls, becomes persistent.

Resolution:

  1. Contact provider to check if your IP is temporarily blocked
  2. Check for malformed SIP requests in your logs:
grep "malformed\|invalid\|error" /var/log/asterisk/messages | tail -20
  1. Ensure no SIP scanning attacks from your server:
netstat -tupan | grep 5060
  1. If provider has rate limits, implement call queuing in ViciDial dialplan to space out requests

Scenario D: Account Suspension/Expiration

Symptom: Abrupt 403 errors with no configuration changes.

Resolution:

  1. Log into provider's web portal
  2. Check account status, payment status, and service activation
  3. Verify DID/trunk subscription is current
  4. Request manual account re-activation
  5. Once confirmed active, reload SIP:
asterisk -rx "sip reload"

Scenario E: Inbound Route Mismatch

Symptom: 403 only occurs on inbound calls; outbound works fine.

Resolution:

Inbound calls use different SIP URI matching. Check your inbound context in /etc/asterisk/extensions-vicidial.conf:

[from-trunk]
exten => 5551234567,1,Verbose("Inbound from ${CALLERID(num)}")
exten => 5551234567,n,Dial(Local/5551234567@default)
exten => 5551234567,n,Hangup()

Ensure:

Step 6: Test the Fix

Manual SIP Test Call

Use Asterisk's dial command directly:

asterisk -rx "channel originate SIP/5551234567@mytrunksip Application VoiceMAil"

Monitor the response in real-time:

tail -f /var/log/asterisk/messages | grep -E "INVITE|403|200 OK|Call"

A successful INVITE shows 200 OK response.

Agent Test Call from ViciDial

Log into the ViciDial agent screen at /agc/vicidial.php:

  1. Log in with test agent account
  2. Select a campaign with your fixed trunk
  3. Dial a test number (external cell phone or test service)
  4. Monitor the call completion

Check call logs in the database:

SELECT call_id, caller_id_number, dialed_number, call_status, 
       length_in_sec, call_date FROM vicidial_log 
WHERE dialed_number = '5551234567' 
ORDER BY call_date DESC LIMIT 5;

Look for call_status = 'COMPLETE' or similar success indicators.

Verify SIP Qualify Status

Check if the trunk qualifies (can reach the provider):

asterisk -rx "sip show peers" | grep mytrunksip

Output should show:

mytrunksip/sip.provider.com    sip.provider.com:5060         OK

If showing UNREACHABLE, the trunk cannot reach the provider at all. This may indicate network issues or wrong host address.

Advanced Troubleshooting

Parse Raw SIP Headers

If you have a tcpdump capture, extract the exact failing INVITE:

sudo tshark -r /tmp/sip_trace.pcap -Y "sip.Request.Method == INVITE" \
  -T fields -e sip.From -e sip.To -e sip.Contact -e sip.User-Agent

Compare the From:/To:/Contact: headers against provider requirements.

Check Asterisk SIP Registry

If your trunk uses outbound registration:

asterisk -rx "sip show registry"

Output shows registration status. Registered means the trunk successfully authenticated with the provider for inbound calls.

If Request Sent or Unregistered, the trunk cannot register:

asterisk -rx "sip set debug on"
asterisk -rx "sip register mytrunksip"

Review Authentication Digest Headers

In tcpdump analysis, look for the response to your INVITE. If it's a 407 (Proxy Authentication Required) followed by your 403 response, your credentials are wrong.

The sequence should be:

  1. INVITE (no auth) → 407 Proxy Auth Required
  2. ACK
  3. INVITE (with Authorization header) → 200 OK or 180 Ringing

If the second INVITE still returns 403, credentials are incorrect.

Extract the Authorization header from tcpdump:

tshark -r /tmp/sip_trace.pcap -Y "sip" -T fields -e sip.Authorization

Compare the username in the Authorization header against your configured username.

Preventive Measures and Monitoring

Monitor for 403 Errors Proactively

Create a monitoring script in /usr/local/bin/check_sip_403.sh:

#!/bin/bash

LOG_FILE="/var/log/asterisk/messages"
THRESHOLD=5

# Count 403 errors in last hour
COUNT=$(grep "SIP/2.0 403" $LOG_FILE | \
  awk -v d="$(date -d '1 hour ago' '+%b %d %H')" \
  '$0 ~ d' | wc -l)

if [ $COUNT -gt $THRESHOLD ]; then
  echo "ALERT: $COUNT SIP 403 errors detected in last hour"
  # Send email, page, etc.
  # mail -s "ViciDial SIP 403 Alert" [email protected]
  exit 1
fi

exit 0

Make executable and add to crontab:

sudo chmod +x /usr/local/bin/check_sip_403.sh
*/5 * * * * /usr/local/bin/check_sip_403.sh

Document Trunk Configuration

Maintain a reference document with:

Trunk Name: mytrunksip
Provider: Provider Name
Host: sip.provider.com:5060
Username: accountname (NOT case-sensitive at provider)
Password: (hash, not plaintext) - updated DATE
From Domain: sip.provider.com
Outbound IPs: 203.0.113.45
Inbound DIDs: 555-123-4567, 555-123-4568
Support Contact: +1-555-0000
Rate Limits: 100 CPS
Last Verified: DATE
Known Issues: None

Implement Health Checks

Add to your monitoring system (Nagios, Zabbix, etc.):

check_sip_qualify() {
  local trunk=$1
  asterisk -rx "sip show peers" | grep -q "$trunk.*OK"
}

check_sip_qualify mytrunksip && echo "OK" || echo "CRITICAL"

Log Rotation Configuration

Ensure Asterisk logs don't fill disk, which can mask 403 errors. Check /etc/logrotate.d/asterisk:

/var/log/asterisk/messages {
    daily
    missingok
    rotate 7
    compress
    delaycompress
    notifempty
    create 0640 asterisk asterisk
    postrotate
        /usr/sbin/asterisk -rx "logger rotate" > /dev/null 2>&1 || true
    endscript
}

Troubleshooting Decision Tree

Is the trunk showing in "sip show peers"?
├─ NO → Check sip-vicidial.conf syntax and reload
├─ YES → Does "sip show registry" show it registered?
    ├─ NO (401 or 407) → Credentials are wrong
    ├─ YES → Are you seeing 403 on INVITE only?
        ├─ YES → IP whitelist or rate limit issue
        └─ NO → Check From: header format

Common ViciDial-Specific Issues

Issue: Multiple Trunks, One Returns 403

ViciDial may route calls through the wrong trunk. Check extensions-vicidial.conf:

exten => _9XXXXXXXX,1,Dial(SIP/${EXTEN:1}@mytrunksip)

If this extension pattern is ambiguous, other patterns might match first. Use more specific patterns:

exten => _91NXXXXXX,1,Dial(SIP/${EXTEN:1}@mytrunksip)
exten => _9011.,1,Dial(SIP/${EXTEN:1}@intl_trunk)

Issue: Campaign Trunk Assignment

In ViciDial, verify campaign uses the correct trunk in database:

SELECT campaign_id, campaign_name, vtiger_id FROM vicidial_campaigns 
WHERE campaign_id = 'TESTCAMP';

SELECT trunk_id, carrier_id FROM vicidial_campaign_carriers 
WHERE campaign_id = 'TESTCAMP';

Wrong trunk assignment will route calls through a trunk with bad credentials.

Issue: Lead Filtering by Trunk

Check if leads are filtered to specific trunks in vicidial_list:

SELECT list_id, carrier_id, count(*) FROM vicidial_list 
WHERE carrier_id IS NOT NULL 
GROUP BY list_id, carrier_id;

If a list requires a specific trunk with 403 errors, leads cannot be called.

Summary

SIP 403 Forbidden errors in ViciDial require systematic diagnosis:

  1. Enable debugging to see the actual error in context
  2. Validate credentials match provider configuration exactly
  3. Verify networking allows packets to reach the provider
  4. Check IP whitelisting with your provider
  5. Test independently using sipp before restarting Asterisk
  6. Monitor proactively with log analysis and SIP qualify checks
  7. Document everything for future troubleshooting

The most common causes are wrong credentials, IP whitelisting issues, and provider account problems. Always contact your SIP provider with specific details:

"SIP 403 Forbidden error from [your outbound IP] to [their SIP host] with username [username] at [specific time]. Can you check authentication logs?"

Keep Asterisk SIP logging enabled in production (sip set debug on in verbosity levels), rotate logs regularly, and set up alerts for repeated 403 errors. This prevents lost calls and identifies problems before they impact your operation.

Stuck on something specific?

Book a free 30-minute call. I run ViciDial centers across 3 countries and can usually unblock your setup in one session — or build it for you.

Book a Free Consultation