Why an internet-facing PBX gets attacked
The Asterisk project puts its warning at the top of its security documentation, in a box marked "Danger": "Improper configuration of Asterisk could allow unauthorized use of your facilities, potentially incurring substantial charges."1 The same page says Asterisk security has two parts: "network security (encryption, authentication) as well as dialplan security (authorization - who can access services in your pbx)".1 Most of this guide follows that split.
The attacks are cheap to run, and the tools for them are public. SIPVicious OSS, a widely used open-source audit toolkit, describes itself plainly: it lets you "find SIP servers, enumerate SIP extensions and finally, crack their password".8 Its svmap tool, "when launched against ranges of ip address space, it will identify any SIP servers which it finds on the way".8 Anything listening on a public SIP port will be found, whoever runs the scan. Assume the scan has already happened.
The payoff is the calls themselves. The FCC's consumer guidance on voicemail hacking describes the business version: hackers "change outgoing messages so they will accept automated international collect calls", or break into "a voicemail system's call forwarding feature, programs the system to forward calls to an international number, then uses it to make calls."7 It also says when and how victims find out: hackers "may try to break into business voicemail systems during holiday periods or weekends", and "business victims may not find out they've been hacked until their phone company reports unusual activity".7 The FCC page is written about voicemail, but the same pattern holds for a PBX: get a dial tone somewhere, point it at expensive destinations, and run up the bill while nobody is watching.
The Asterisk best-practices file in the source tree is blunt about the cost: weak passwords expose you to "expensive long distance calls that could potentially cost your company hundreds or thousands of dollars on an expensive monthly phone bill, with little to no recourse to fight the charges."5 Industry loss estimates exist, but we could not read one at source, so this page quotes no loss figure.
Our view: work out the worst bill an attacker could run up before you work on anything else. That number is set by three things you control: which contexts can reach a trunk, how many calls the trunk will carry at once, and how soon you would notice. Everything else in this guide narrows one of those three.
The three ways in
On Asterisk, nearly all toll fraud comes in one of three ways. Each matches a section below.
- Credentials. An attacker registers as one of your phones, or sends calls as it, by guessing its password. The best-practices file warns that "many of the current exploits deal with device configurations which utilize a number, and even worse, a password that matches the devices name", and gives the example of a device named 1000 with the password 1000.5
- Dialplan exposure. A call that was never authenticated lands in a context that can dial out, or a pattern that should only match extensions passes the dialled string straight to
Dial(). The project's dialplan security page states the rule: "Use the extension contexts to isolate outgoing or toll services from any incoming connections."2 - Management interfaces. The Asterisk Manager Interface (AMI) and the REST interface (ARI) can originate calls and set variables. The best-practices file says "you should treat the Manager class authorization 'originate' the same as the class authorization 'system'."5
A fourth way in does not depend on Asterisk at all: voicemail and remote-access features that let a caller reach a dial tone. The FCC's advice for business voicemail applies here too: "Disable remote notification, auto-attendant, call-forwarding and out-paging features if you don't use them", and "Consider blocking international calls."7
Who is calling? PJSIP identification and ACLs
Every inbound SIP request to chan_pjsip is first matched to an endpoint. That match decides which credentials are checked and which dialplan context the call enters, so it is the first security decision Asterisk makes. The sample configuration lists the methods: matching the endpoint section name to the user in the From header, matching an AOR to the To header of a REGISTER, or, "with an identify type section configured", matching "an inbound SIP request of any type to an endpoint or aor based on the IP source address of the request."6
The order is set globally by endpoint_identifier_order, whose default is ip,username,anonymous.6 Per endpoint, identify_by defaults to username,ip.6 Two details in the sample are worth knowing before you write an identify section:
- "If multiple matching criteria are provided then an inbound request will be matched to the endpoint if it matches ANY of the criteria."6 Adding a
match_headerto an IP-based identify makes it looser, not stricter. - The
matchoption takes "IP addresses, networks, or hostnames", and SRV lookups on hostnames are on by default.6 An identify that matches a hostname trusts whatever that name resolves to. Our view: for trunks, list the provider's published signalling addresses as literal IPs or networks.
IP identification is only as good as the code behind it, which is why patch releases matter here. Advisory CVE-2024-35190 reported that in Asterisk 18.23.0, 20.8.0 and 21.3.0, res_pjsip_endpoint_identifier_ip "wrongly matches ALL unauthorized SIP requests" to an IP-identified endpoint, with the stated impact "Unauthorized access/calls"; it was fixed in 18.23.1, 20.8.1 and 21.3.1.10 The trunk endpoint is exactly the one you have deliberately left without inbound authentication, so this is the worst place for an identification bug.
Anonymous calls are off. Keep them off.
The sample is explicit: "By default anonymous inbound calls via PJSIP are not allowed. If you want to route anonymous calls you'll need to define an endpoint named 'anonymous'", and "It is not recommended to accept anonymous calls."6 If someone in your organisation once created an [anonymous] endpoint so that SIP URI calls would reach a menu, its context must contain nothing that can reach a trunk. The sample makes the same point for the default outbound endpoint, configuring it with context=none-invalid.6
ACLs before anything else
A type=acl section in pjsip.conf "is independent of individual endpoint configuration and operates on all inbound SIP communication using res_pjsip."6 It supports permit/deny on the source address, contact_permit/contact_deny on the Contact header, and references to named ACLs in acl.conf.6 Named ACLs "can be shared across multiple modules" (the Manager, chan_pjsip and chan_iax2 are listed consumers) and can be stored in realtime, although "an ACL updated in an ARA backend will not be propagated automatically to consumers using static configuration".9 The sample's own advice is the right default: "If possible, restrict access to only networks and addresses you trust."6
One last setting leaks information. allow_unauthenticated_options defaults to no; if you enable it, "an external party could enumerate and find the endpoint name by sending OPTIONS requests and examining the responses."6 Leave it off unless a device cannot work without it.
Credentials that survive a dictionary attack
The best-practices file recommends naming devices after something that is not an extension number, such as the phone's MAC address, and pairing it with a strong password; its example is a twelve-character mix of upper and lower case letters, digits and symbols. It adds a warning that applies to every staging system: "Some of the holes found in production systems used for exploitations involve finding the one test extension that contains a weak password that was forgotten prior to putting a system into production."5 Because these secrets are only ever pasted into a config file and a phone's provisioning, there is no reason for them to be short. Our view: generate 24 or more random characters per device and never reuse one.
Asterisk now supports stronger digest hashing too. "With the release of Asterisk 20.12.0, 21.7.0 and 22.2.0 and the associated release of PJProject 2.15.1, the chan_pjsip channel driver now supports the SHA-256 and SHA-512-256 authentication digest hash algorithms in addition to the base MD5 algorithm", subject to the PJProject and OpenSSL versions installed.11 The current documentation describes auth_type=digest as the mechanism and userpass as a deprecated value that "will automatically be converted to 'digest'".11 The global defaults for offered and accepted algorithms are still MD5,6 so SHA-256 is something you turn on, phone by phone, as your handsets gain support.
Three more rules come straight from the sample configuration:
- You can store a
password_digest(a hash ofusername:realm:password) instead of a plain-text password,6 so a leakedpjsip.confdoes not hand over the secret in readable form. - "Using the same auth section for inbound and outbound authentication is not recommended."6 Keep the credentials your provider issued to you separate from the ones your phones use.
- The
unidentified_request_count,_periodand_prune_intervaloptions raise a security event when one address sends too many requests that match no endpoint (defaults: 5 requests in 5 seconds). They apply only whenauth_usernamematching is inendpoint_identifier_order.6
Contexts are the security boundary
This is the most important section of the guide. The Asterisk documentation states the principle: "if any channel, incoming line, etc. can enter an extension context that it has the capability of accessing any extension within that context." So "you should not allow access to outgoing or toll services in contexts that are accessible (especially without a password) from incoming channels", and "never ever put outgoing toll services in the 'default' context."2 Build the dialplan as a set of layers: a trunk's context= reaches your menu and your DIDs only, and each phone's context includes just the outbound classes that phone is allowed to use.
Never pass untrusted strings to Dial()
The best-practices file shows the classic injection. With exten => _X.,n,Dial(PJSIP/${EXTEN}), a caller who sends the string 500&PJSIP/itsp/14165551212 turns your extension dial into a second call out through your provider. The fixes it gives are "stricter pattern matching, or using the FILTER() dialplan function".5 FILTER(allowed-chars,string) "permits all characters listed in allowed-chars, filtering all others outs".14 The same file warns that caller ID values passed to System(), MixMonitor() or SHELL() "can allow injection of arbitrary operating system command execution".5
The North American trap: international calls that start with 1
The North American Numbering Plan is "an integrated telephone numbering plan serving 20 North American countries", including the United States, Canada, Bermuda, the Bahamas, Jamaica, the Dominican Republic and other Caribbean countries.12 A call from Toronto or Chicago to Kingston, Jamaica is dialled as 1 plus ten digits, exactly like a domestic long-distance call. So a dialplan that blocks 011 but allows _1NXXNXXXXXX still lets calls reach 18 other countries. NANPA's area code report lists the in-service general-purpose codes outside the US and Canada as 242, 246, 264, 268, 284, 345, 441, 473, 649, 658, 664, 721, 758, 767, 784, 809, 829, 849, 868, 869 and 876, and lists 900 as an "Easily Recognizable Code" for "Premium Services".13 (US territories such as Puerto Rico and Guam are recorded under the US.)13 The same applies in Canada, which shares the plan.12
The example below allows US and Canadian numbers, sends the 21 non-US/Canadian codes and 1-900 to a refusal, caps concurrent outbound calls, and keeps international dialling in a separate context that is included only where it is needed. It uses REGEX("regular expression" string), which returns "'1' on regular expression match or '0' otherwise",15 and GROUP() / GROUP_COUNT(), which count channels in a named group (each channel can belong to "exactly one group per category").1617
; extensions.conf (excerpt). Trunk endpoint "itsp" uses context=from-itsp.
[from-itsp] ; reached by unauthenticated trunk traffic
exten => 5550100,1,Goto(main-menu,s,1) ; your DID(s) only; nothing here dials out
[from-phones] ; context= of every desk phone endpoint
include => internal
include => emergency
include => outbound-nanp
; outbound-intl is NOT included here; give it to the few phones that need it
[emergency] ; 911 with no prefix, and with the 9 users may dial
exten => 911,1,Dial(PJSIP/911@itsp)
exten => 9911,1,Dial(PJSIP/911@itsp)
[outbound-nanp]
exten => _NXXNXXXXXX,1,Goto(1${EXTEN},1)
exten => _1NXXNXXXXXX,1,GotoIf(${REGEX("^1(900|242|246|264|268|284|345|441|473|649|658|664|721|758|767|784|809|829|849|868|869|876)" ${EXTEN})}?refuse,1)
same => n,Set(GROUP(trunk)=itsp-out)
same => n,GotoIf($[${GROUP_COUNT(itsp-out@trunk)} > 4]?busy,1)
same => n,Dial(PJSIP/${EXTEN}@itsp,60)
same => n,Hangup()
exten => refuse,1,Playback(silence/1&invalid)
same => n,Hangup()
exten => busy,1,Congestion(5)
[outbound-intl]
exten => _011X.,1,Set(GROUP(trunk)=itsp-intl)
same => n,GotoIf($[${GROUP_COUNT(itsp-intl@trunk)} > 1]?busy,1)
same => n,Dial(PJSIP/${FILTER(0-9,${EXTEN})}@itsp,60)
same => n,Hangup()
exten => busy,1,Congestion(5)
In the United States, whoever installs, manages or operates a multi-line telephone system must configure it "such that a user may directly initiate a call to 911 from any station equipped with dialing facilities, without dialing any additional digit, code, prefix, or post-fix, including any trunk-access code such as the digit 9".18 The same rule also requires MLTS notification "to a central location" where the system can provide it.18 Test your 911 route after every dialplan change. The Canadian 9-1-1 rules are summarised on our emergency calling page.
Our view on the concurrency cap: it is the cheapest control on this page. Pick the number of simultaneous outside calls your business really makes, add one, and set the cap there, because a fraud run nearly always opens many calls at once. Ask your provider for a spending limit and international blocking on the account as well. Those controls sit outside your server, so they still work when everything on the server has failed.
Finally, the documentation's housekeeping advice: "Do not forget to take the demo context out of your default context."2
AMI, ARI and the HTTP server
The Manager interface is disabled in the sample (enabled = no), and its web variant also needs Asterisk's HTTP server plus webenabled, both of which "default to no". The same sample binds it to bindaddr = 0.0.0.0 on port 5038, so if you enable it, change the bind address to 127.0.0.1.19 The network security page advises that if you enable it, "make sure that you access manager in a safe environment or protect it with SSH or other VPN solutions."3 Every manager user also takes permit/deny lines.19
Treat originate as root-equivalent. The best-practices file shows an Originate action that executes the System application, and notes that "the Manager action Originate allows for channel variables to be set by the account initiating the new call."5 Advisory CVE-2024-42365 showed in practice that a user with only write=originate could use Set with FILE or CURL to "change all configuration files in the /etc/asterisk/ directory"; it was fixed in 18.24.2, 20.9.2 and 21.4.2.20
Two settings in asterisk.conf limit the damage. live_dangerously controls "the execution of 'dangerous' dialplan functions and configuration file access from external sources (AMI, etc.)" such as SHELL,21 and "In Asterisk 12 and later, live_dangerously defaults to no."5 runuser and rungroup set the account Asterisk runs as.21 The best-practices file names "not running Asterisk as root" as the thing that "can prevent serious problems".5 Neither is a complete wall: CVE-2026-57202 (June 2026) showed that an ARI user with read-only credentials could use setChannelVar to bypass live_dangerously and perform FILE() writes. The advisory notes that the HTTP server is "disabled by default" and, when enabled, "bound only to 127.0.0.1 by default".22 Keep those defaults unless you have a reason to change them.
The security event framework and logging
Asterisk raises structured security events from its channel drivers and interfaces. The event types are defined in the source and include failed ACL checks, invalid account IDs, session and memory limits, requests that are not allowed, unexpected addresses, failed challenge responses, invalid passwords, successful authentications and invalid transports.23 The res_security_log module subscribes to them and writes each one to a logger level named SECURITY.24
That level goes nowhere until you route it. The sample logger.conf lists security as a level and ships the file line commented out: ;security.log => security. The live default lines are console => notice,warning,error and messages.log => notice,warning,error.25 Uncomment the security line. The log page also notes that "Asterisk log files, as well as information printed to the Asterisk CLI, may contain sensitive information such as passwords and call history", so restrict who can read them.4 The sample also strongly advises against running debug logging in production, because "Debug mode turns on a LOT of extra messages".25
; /etc/asterisk/logger.conf
[logfiles]
console => notice,warning,error
messages.log => notice,warning,error
security.log => security
fail2ban: a useful backstop, not a control
fail2ban ships an asterisk filter. It matches several kinds of line: SecurityEvent="FailedACL", "InvalidAccountID", "ChallengeResponseFailed" and "InvalidPassword" entries carrying a RemoteAddress; PJSIP's "No matching endpoint found", "Not match Endpoint ACL" and "Failed to authenticate" request failures; and older registration-failure messages.26 The filter's log prefix accepts the NOTICE, SECURITY and WARNING levels.26
The stock jail is less ready to use than it looks. In fail2ban's jail.conf, [asterisk] watches ports 5060,5061 on TCP and UDP with maxretry = 10, and its logpath is /var/log/asterisk/messages.27 Asterisk's own sample names the file messages.log, and security events only reach a file you have routed them to.25 Packagers may change either name, so check which files exist on your system. If the jail points at a file that does not exist or never receives security events, it bans nothing, and nothing tells you so. fail2ban's own instruction is "YOU SHOULD NOT MODIFY THIS FILE", and overrides belong "in a jail.local file or a jail.d/customisation.local".27 Its global defaults are bantime = 10m, findtime = 10m and maxretry = 5.27
# /etc/fail2ban/jail.d/asterisk.local
[asterisk]
enabled = true
logpath = /var/log/asterisk/security.log
/var/log/asterisk/messages.log
maxretry = 5
findtime = 10m
bantime = 1h
Our view: fail2ban reduces noise and slows password guessing, but it only acts after failures happen and it cannot see a correctly authenticated call that should not have been allowed. ACLs, strong secrets and a narrow dialplan prevent fraud. fail2ban only keeps the log readable.
Firewalling SIP and RTP
The network security page reminds you that a sample install "will open a few ports for accepting VoIP calls", and that you should check "the channel configuration files for the ports and IP addresses."3 In practice there are three groups of ports:
- SIP signalling on whatever each PJSIP transport
binds: conventionally 5060 for UDP/TCP and 5061 for TLS, which are also the ports the fail2ban jail assumes.2729 - RTP media on the range in
rtp.conf. The sample setsrtpstart=10000andrtpend=20000, and its comment gives the compiled defaults as 5000 and 31000.28 Open exactly the range you configure. Asterisk's NAT example port-forwards "UDP 10000-20000".31 - Management: AMI (port 5038 in the sample, 5039 for its TLS listener) and the HTTP server should not be reachable from the internet at all.19
Strict RTP is on by default: it "will drop RTP packets that do not come from the recognized source of the RTP stream", and learns the source at the start of a call and on renegotiation.28 It protects you against injected or hijacked media streams, so leave it on.
The most effective rule is not about ports. If your phones are on the LAN or a VPN and your provider publishes its signalling addresses, allow SIP from those addresses only and drop everything else at the firewall. Scanners never reach Asterisk, fail2ban has nothing to do, and the ACL becomes a second layer. An illustrative nftables fragment (the addresses are documentation ranges):
table inet pbx {
set itsp { type ipv4_addr; flags interval; elements = { 203.0.113.0/28 } }
chain input {
type filter hook input priority 0; policy drop;
ct state established,related accept
iif lo accept
ip saddr 192.0.2.0/24 accept # office LAN
ip saddr @itsp udp dport 5060 accept # provider signalling
ip saddr @itsp tcp dport 5061 accept # provider TLS, if used
udp dport 10000-20000 accept # RTP, matches rtp.conf
tcp dport 22 ip saddr 192.0.2.0/24 accept # admin from LAN only
}
}
RTP has to stay open to any address, because media can arrive from provider media servers that are not in the signalling list. Strict RTP is what protects that range.28
TLS for signalling, SRTP for media
The network security page says "The SIP channel supports TLS encryption of the signaling, as well as SRTP (encrypted media)."3 The project's tutorial notes that "SRTP support was added in Asterisk 1.8, TLS was added in 1.6", and shows a PJSIP TLS transport with protocol=tls, bind=0.0.0.0:5061, cert_file, priv_key_file and method, plus an endpoint with media_encryption=sdes.29 It also gives a practical warning: adding transport=transport-tls to an endpoint caused "Connection refused" in some situations with older pjproject versions, and setting rewrite_contact = yes can help.29
The rule that matters most: SDES-SRTP is only as private as the signalling. SDES puts the media keys in the SDP. RFC 4568 is explicit that "Implementations MUST employ security mechanisms that provide confidentiality and integrity for the keying material", and that with SIP "the application SHOULD employ either the SIPS URI or S/MIME".30 media_encryption=sdes over UDP signalling sends the keys in clear text. Pair SDES with a TLS transport, or use DTLS-SRTP (media_encryption=dtls). The sample's webrtc=yes shortcut sets media_encryption=dtls, dtls_verify=fingerprint and dtls_setup=actpass, and notes that "A dtls_cert_file and a dtls_ca_file still need to be specified."6
The default for media_encryption is "no", and media_encryption_optimistic will "Use encryption if possible but don't fail the call if not possible".6 For phones you control, enforce it. For a provider trunk, whether TLS and SRTP are offered is a question for the provider, and many trunks are plain UDP and RTP. If yours is, the firewall rule above (signalling from the provider only) is what you have.
The tutorial's examples use ast_tls_cert to build a self-signed CA, with a key size of 2048 bits passed explicitly.29 That suits phones you provision yourself. For anything that verifies the server name, use a certificate whose name matches the host the phones connect to. The sample notes that cert_file and priv_key_file "can be reloaded resulting in an updated certificate if the filename remains unchanged",6 so routine renewals do not need a restart.
NAT without one-way audio
Most small deployments run Asterisk on a private address behind a router. The project's NAT page names four settings that must be right: "local_net, external_media_address and external_signaling_address in the transport type section and direct_media in the endpoint section."31
local_net: "the IP network that we want to consider our local network. For communication to addresses within this range, we won't apply any NAT-related settings".31 The sample adds that theexternal_options "will only apply to communication with addresses outside the range set with 'local_net='".6external_media_address: when the destination is outsidelocal_net"and the media address in the SDP is within the localnet network, then the media address in the SDP will be rewritten" to this value.31external_signaling_address: the same for SIP, and the two "should be set to the same address unless you separate your signaling and media to different addresses or servers."31direct_media=no"ensures Asterisk stays in the media path", which matters because the provider "cannot route to" a private address.31
For remote phones behind someone else's NAT, the same page points to rtp_symmetric ("Send RTP back to the same address/port we received it from"), force_rport, rewrite_contact and direct_media.31 force_rport defaults to yes; rewrite_contact and rtp_symmetric default to no.6 The RTP range you forward must match rtp.conf.28
Our view: one-way audio after a firewall change is nearly always a mismatch between the forwarded UDP range and rtp.conf, or a missing external_media_address. Check both before touching codecs.
SIP trunks: registration or IP identify
A provider can reach you in two ways, and the sample configuration documents both.
- Registration. Asterisk registers to the provider with
outbound_auth, so the provider knows where to send your calls. "This is a simple registration that works with some SIP trunking providers."6 Withline=yesandendpoint=, alineparameter is added to the Contact so that incoming calls "related to the outbound registration" are tied to the configured endpoint.6 - IP-based identify. "There is no inbound authentication set up since a provider will not normally authenticate when calling you", so an
identifysection matches the provider's addresses, because "the From user may be different every time".6
Most providers use registration so they can find you, and IP identify so you can recognise them. The example below does both, and adds a global ACL, separate transports, a phone named by MAC address and TLS with SRTP for the phone. Section names can repeat when their type differs.6 The NAT values follow the project's NAT example.31
; pjsip.conf: one trunk and one desk phone, hardened.
; Addresses are RFC 5737 documentation ranges; substitute your own.
[global]
type=global
endpoint_identifier_order=ip,username ; no anonymous identifier
user_agent=PBX ; default is "Asterisk PBX"
[acl-sip] ; applies to ALL inbound SIP
type=acl
deny=0.0.0.0/0.0.0.0
permit=203.0.113.0/28 ; provider signalling
permit=192.0.2.0/24 ; office LAN / VPN
[transport-udp-nat]
type=transport
protocol=udp
bind=0.0.0.0:5060
local_net=192.0.2.0/24
external_media_address=198.51.100.5
external_signaling_address=198.51.100.5
[transport-tls]
type=transport
protocol=tls
bind=0.0.0.0:5061
cert_file=/etc/asterisk/keys/pbx.crt
priv_key_file=/etc/asterisk/keys/pbx.key
local_net=192.0.2.0/24
external_media_address=198.51.100.5
external_signaling_address=198.51.100.5
; ---------- trunk ----------
[itsp-reg]
type=registration
transport=transport-udp-nat
outbound_auth=itsp-auth
server_uri=sip:sip.provider.example
client_uri=sip:[email protected]
contact_user=5550100
line=yes
endpoint=itsp
[itsp-auth] ; issued by the provider; outbound only
type=auth
auth_type=digest
username=5550100
password=<from the provider portal>
[itsp]
type=endpoint
transport=transport-udp-nat
context=from-itsp ; DIDs and menu only
disallow=all
allow=ulaw
outbound_auth=itsp-auth
aors=itsp
direct_media=no
from_domain=sip.provider.example
[itsp]
type=aor
contact=sip:sip.provider.example
qualify_frequency=60 ; default 0 = never checked
[itsp]
type=identify
endpoint=itsp
match=203.0.113.1
match=203.0.113.2
; ---------- desk phone, named by MAC ----------
[0004f2a1b2c3]
type=endpoint
transport=transport-tls
context=from-phones
disallow=all
allow=ulaw
auth=0004f2a1b2c3
aors=0004f2a1b2c3
media_encryption=sdes ; keys protected by TLS signalling
direct_media=no
[0004f2a1b2c3]
type=auth ; inbound only, never shared
auth_type=digest
username=0004f2a1b2c3
password=<24+ random characters>
[0004f2a1b2c3]
type=aor
max_contacts=1
remove_existing=yes
qualify_frequency=60
Notes on the choices. endpoint_identifier_order=ip,username drops the default anonymous identifier,6 so an unmatched request cannot fall through to an anonymous endpoint even if someone adds one later. qualify_frequency defaults to 0,6 which means Asterisk never checks the trunk and you only learn it is down when a customer cannot get through. If you run a release older than 20.12.0, 21.7.0 or 22.2.0, check whether it accepts auth_type=digest; userpass is the value older configurations use, and current releases convert it to digest automatically.11
STIR/SHAKEN in Asterisk
Asterisk's STIR/SHAKEN module, res_stir_shaken, was rewritten. The documentation says it "refers to the Stir/Shaken Refactor of 1Q2024. The earlier version was only partially functional and not interoperable with other implementations."32 The change logs place the refactor in Asterisk 18.22.0, 20.7.0 and 21.2.0, with the upgrade note "The stir-shaken refactor is a breaking change", "existing ones WILL need to be changed", and a dependency on libjwt v1.15.3 (or --with-libjwt-bundled).33 The 20.7.0 release was published on 18 March 2024.47 The commit gives the reason: the original implementation "wouldn't actually interoperate with any other stir-shaken implementations".34
Configuration lives in stir_shaken.conf, with four object types: one attestation object for signing outbound calls, tn objects keyed by caller-ID number holding the certificate URL, attestation level and private key, one verification object for inbound calls, and profile objects attached to PJSIP endpoints.32 An endpoint opts in with stir_shaken_profile, and a profile sets endpoint_behavior (for example verify) and a failure_action.35
Before you enable it, know its limits. The documentation lists deviations from the specifications: Asterisk "does not validate the destination TN", supports only the full PASSporT form, performs "only basic validation of certificates" (CA, validity dates and TNAuthList presence, but not the Common Name), and checks only CRLs you have configured. It also says "there is currently no way for Asterisk to verify that the SPC in the certificate has the authority over the TN in the Identity header."32 Verification is also attack surface: CVE-2025-49832 reported a remote denial of service and "possible RCE" in verification.c when verification is enabled on an endpoint, fixed in 18.26.3, 20.15.1, 21.10.1 and 22.5.1.36
Signing is the harder part. The documentation says that "For most Asterisk installation scenarios, you'd receive such a key/certificate from your upstream service provider when they issue you DID telephone numbers."32 Certificates come from a governance regime run for service providers. In Canada that is the CST-GA, "the national governance authority tasked to direct and oversee the STIR/SHAKEN Policy Administrator and Certification Authorities for Canada", whose participants are "TSPs registered with the CRTC to provide voice services in Canada".37 Our view: for a business PBX behind a provider trunk, the provider normally signs your outbound calls, and the attestation level depends on what that provider knows about your numbers. Run res_stir_shaken yourself only if you are the service provider, or if you want to read verification results on inbound calls, and in that case keep it patched.
CDR and CEL: your fraud detector
Asterisk produces two kinds of call records. CDR logging is on by default (enable=yes),38 and since Asterisk 12 "multiple CDRs will be created for a given call" depending on how channels are dialled and bridged, so "Post-processing of these records will be required to determine the overall statistics of the call."39 Two defaults are worth knowing: unanswered calls that are not offered to an outgoing line are not logged (unanswered = no), and batch mode "may result in data loss after unsafe asterisk termination".38
Channel Event Logging (CEL) is a finer-grained stream of channel events, "designed with billing information in mind", with back-ends that include ODBC, PostgreSQL, SQLite and TDS.41 It is off by default (enable defaults to no). The sample tracks apps=dial,park and warns that all "may affect Asterisk's performance significantly".40 The CDR specification describes CEL as the option "if CDRs do not provide the billing information you need".39
Our view: you do not need a billing system to use either. A scheduled query over the CDR table that counts outbound calls per hour, and calls to anything outside your allowed prefixes, is the alarm that catches the attack the FCC describes, the one that happens over a holiday weekend.7 Send the result to a phone, not to an inbox nobody reads on a Saturday. One security note: CVE-2026-57190 (June 2026) was an SQL injection in cel_pgsql and cel_tds through the CELGenUserEvent event type field,44 so the logging back-end is part of what you patch.
Monitoring and alerting
What we would watch on a small production system, and where Asterisk exposes it:
- Trunk reachability and registration. Set
qualify_frequencyon the trunk AOR (default 0, meaning never) so the contact's status is known.6 - Metrics.
res_prometheusserves statistics for a Prometheus server. It is disabled by default ("enabling this without proper securing of your Asterisk system may result in external systems learning a lot about your Asterisk system"), needs the HTTP server, and the sample "highly" recommends Basic Auth on the metrics route.42 It exports core metrics (version, uptime, reload and scrape times) and channel and bridge detail, and listsres_pjsipandres_pjsip_outbound_registrationamong its module dependencies.42 - Security events. Alert on the rate of entries in
security.log, not on single entries. A public server always has a background of failures. A sudden change in that rate, or a successful authentication from an address you do not know, is the signal.23 - Call volume. The CDR query above, plus a threshold on concurrent channels.
- Release and advisory feeds. Covered below.
Backups: what to copy, and how to know it works
asterisk.conf lists where everything lives. The compiled-in defaults are typically /etc/asterisk (configuration), /var/lib/asterisk (data, keys and the internal database, via astdbdir and astkeydir), /var/spool/asterisk (the spool, which holds voicemail and recordings), and /var/log/asterisk. The sample notes the stanza is a template and that "the compiled-in defaults are typically sufficient".21 Back up the first three, plus your CDR/CEL database and the TLS keys. Your distribution may move these paths, so read them from your own asterisk.conf.
Our view: a PBX backup has only been proven when it has been restored onto a fresh machine and that machine has registered to the trunk and completed a call. Do that once when you build the system and again after every major upgrade. Encrypt the copies: they hold every SIP secret you have.
Security releases and the advisories page
The project publishes advisories on asterisk.org's Security Advisories page,43 and since 2023 in the GitHub repository's Security tab: past reports are "On the projects GitHub repository unser the 'Security' tab. (reports for 2023 and later)" and "On the Asterisk downloads site. (reports for 2022 and earlier)", and "All security vulnerabilities are also issued a CVE number".45 Vulnerabilities are reported privately through GitHub's "Report a vulnerability" button, never the public issue tracker.45
Fixes arrive in batches, and recent ones have been large. On 25 June 2026 the project published 20 advisories at once,44 with fixes shipped the same day in 20.20.1, 21.12.3, 22.10.1, 23.4.1 and certified releases 20.7-cert11 and 22.8-cert3.4647 They range from PJSIP parsing bugs to ARI and H.323 issues. Many will not affect a given system, because they sit in modules it does not load. That is the case for removing unused modules: every module you do not load is one fewer advisory to read.
As of 26 October 2026 the latest full releases are 20.21.0, 22.11.0 and 23.5.0 (27 August 2026), and 24.0.0 is at release candidate 3 (22 October 2026).47 Our view on cadence: subscribe to the GitHub advisories for the repository and the asterisk.org page,4344 read every advisory against your list of loaded modules, and apply security point releases within days, not at the next maintenance window. A security point release changes very little; that is what makes it quick to apply.
Upgrade strategy across LTS versions
The project's policy: "A Long Term Support (LTS) release will be fully supported for 4 years, with one additional year of maintenance for security fixes." Standard releases get "at least one year of full support and an additional year of maintenance for security fixes", and new versions come "roughly once a year, alternating between standard and LTS releases".48 Fully supported branches get bug-fix updates "roughly every 4 to 6 weeks", and branches in security-only maintenance are updated "on an as needed basis".48 The yearly schedule puts the first full release of a new branch on "the 3rd Thursday of October".48
| Series | Type | Released | Security fixes only from | End of life | Position on 26 Oct 2026 |
|---|---|---|---|---|---|
| 18.x | LTS | 2020-10-20 | 2024-10-20 | 2025-10-20 | End of life |
| 20.x | LTS | 2022-10-19 | 2026-10-19 | 2027-10-19 | Security fixes only (date passed a week ago) |
| 21.x | Standard | 2023-10-18 | 2025-10-18 | 2026-10-18 | End of life (date passed) |
| 22.x | LTS | 2024-10-16 | 2028-10-16 | 2029-10-16 | Fully supported |
| 23.x | Standard | 2025-10-15 | 2026-10-15 | 2027-10-15 | Security fixes only (date passed) |
| 24.x | LTS | 2026-10-15 (planned) | 2030-10-15 | 2031-10-15 | Release candidate (24.0.0-rc3) |
Scroll the table sideways to see every column.
Dates are from the Asterisk Versions page.48 The last column applies those dates to today and to the published release tags.47 When we read it, the page's own status column still showed 20.x and 23.x as "Fully Supported" and 24.x as "Pre-release". It also notes that 21.x was, "Due to a mistake in scheduling", "supported for 2 years for bug fixes".48
The biggest upgrade decision most long-running systems still face is chan_sip. Asterisk 21.0.0's change log includes "chan_sip: Remove deprecated module".49 A system still on sip.conf cannot move past 20.x without migrating to PJSIP, and 20.x is now in security-only maintenance until October 2027.48
Our recommended strategy, labelled as opinion:
- Run LTS in production, not standard releases. Today that means 22.x, which is fully supported until October 2028.48
- Move from one LTS to the next, about a year after it ships. Let 24.x collect a few point releases before you adopt it. You still get years of overlap: 22.x stays in full support until 2028.48
- Read every change log and upgrade note in between. The STIR/SHAKEN refactor arrived in point releases of existing branches, as a breaking configuration change.33 Point releases are not always as small as they look.
- Rehearse on a copy. Restore last night's backup onto a test machine, upgrade it, and run your call tests: inbound to the menu, an outbound NANP call, a refused 1-876 call, 911 routing (to a test arrangement with your provider, never a live emergency call) and a voicemail deposit. Then repeat on production.
Hardening checklist
Each line is something you can check on a running system. The source column points to the evidence above.
| Area | Check | Where | Why |
|---|---|---|---|
| Firewall | SIP accepted only from provider and LAN/VPN; RTP range equals rtp.conf; AMI/HTTP closed to the internet | host firewall, rtp.conf | Scanners find every open SIP port828 |
| ACL | type=acl deny-all, permit known networks | pjsip.conf, acl.conf | Applies to all inbound SIP69 |
| Identification | Trunk identify by literal IPs; no [anonymous] endpoint; anonymous removed from endpoint_identifier_order | pjsip.conf | ANY-match semantics; CVE-2024-35190610 |
| Credentials | Devices named by MAC; 24+ random characters; separate inbound and outbound auth; SHA-256 where supported | pjsip.conf | Numeric names and weak passwords are what attackers try first511 |
| OPTIONS | allow_unauthenticated_options left at no | pjsip.conf | Endpoint enumeration6 |
| Dialplan | Trunk context reaches DIDs/menu only; nothing in default; demo removed | extensions.conf | Any extension in a context is reachable2 |
| Patterns | No _X. into Dial(); FILTER() on dynamic strings | extensions.conf | Dial-string injection514 |
| Destinations | Block 1-900 and the 21 non-US/Canadian NANP codes; international in its own context | extensions.conf | NANP covers 20 countries1213 |
| Concurrency | GROUP_COUNT() cap on outbound and international | extensions.conf | Limits the size of a fraud run17 |
| 911 | 911 dials with no prefix; 9911 also works; notification configured | extensions.conf | 47 CFR § 9.1618 |
| AMI/ARI | Disabled or bound locally; originate treated as system; live_dangerously = no | manager.conf, asterisk.conf | CVE-2024-42365, CVE-2026-572022022 |
| Privileges | runuser/rungroup set; not root | asterisk.conf | Contains any compromise521 |
| Logging | security.log => security enabled; logs readable by admins only | logger.conf | Security events go nowhere by default254 |
| fail2ban | Jail enabled in a .local file, pointed at files that exist | jail.d/ | Stock logpath may not match2627 |
| Encryption | TLS transport for phones; SRTP enforced; SDES only over TLS | pjsip.conf | RFC 4568 key protection2930 |
| NAT | local_net, both external_* addresses, direct_media=no | pjsip.conf | One-way audio, wrong SDP31 |
| Monitoring | qualify_frequency on trunk; CDR volume alert; security-event rate alert | pjsip.conf, your monitoring | Weekend fraud is found late67 |
| Backups | /etc/asterisk, /var/lib/asterisk, /var/spool/asterisk, CDR DB; restore tested | backup job | Paths from asterisk.conf21 |
| Patching | Advisory feeds watched; security releases applied within days | GitHub, asterisk.org | Large coordinated batches4344 |
| Version | On a supported LTS (22.x today); off chan_sip | core show version | Support windows4849 |
Scroll the table sideways to see every column.
If what you need is a menu in front of your team's mobiles rather than a PBX to run, that is the problem the hosted Auto Attendant service is built for (nothing on this page describes it). If you need a PBX, the checklist above is the minimum we would want in place before giving it a public address.
Further reading
Longer research pieces on this topic, each with its own source list and a downloadable PDF.
Articles on this topic
Topics Auto attendant VoIP Call routing All topics
Sources
Every regulatory and pricing claim on this page links to the primary source it came from. Figures were checked on the date shown at the top of the page; rules and prices change, so verify before relying on one.
- Asterisk Documentation, "Important Security Considerations" (Danger notice; network versus dialplan security). Retrieved 26 Oct 2026
https://docs.asterisk.org/Deployment/Important-Security-Considerations/ - Asterisk Documentation, "Dialplan Security" (isolating toll services by context; never in default; remove demo contexts). Retrieved 26 Oct 2026
https://docs.asterisk.org/Deployment/Important-Security-Considerations/Dialplan-Security/ - Asterisk Documentation, "Network Security" (sample ports, protecting manager, ACLs, TLS and SRTP). Retrieved 26 Oct 2026
https://docs.asterisk.org/Deployment/Important-Security-Considerations/Network-Security/ - Asterisk Documentation, "Log Security" (logs and CLI may contain passwords and call history). Retrieved 26 Oct 2026
https://docs.asterisk.org/Deployment/Important-Security-Considerations/Log-Security/ - Asterisk source tree, README-SERIOUSLY.bestpractices.md (filtering data, device naming, secure passwords, manager class authorizations, live_dangerously). master branch, retrieved 26 Oct 2026
https://github.com/asterisk/asterisk/blob/master/README-SERIOUSLY.bestpractices.md - Asterisk source tree, configs/samples/pjsip.conf.sample (identification, anonymous calls, ACL, auth, trunk examples, transport, NAT, media encryption and global options with defaults). master branch, retrieved 26 Oct 2026
https://github.com/asterisk/asterisk/blob/master/configs/samples/pjsip.conf.sample - FCC Consumer Guide, "Voicemail Hacking" (international collect-call and call-forwarding schemes, timing, tips). fcc.gov refused automated clients; read via an Internet Archive copy. Last updated 6 October 2022; read via an Internet Archive copy, 26 Oct 2026
https://www.fcc.gov/consumers/guides/voicemail-hacking - SIPVicious OSS, README (find SIP servers, enumerate extensions, crack passwords; svmap scanner). Retrieved 26 Oct 2026
https://github.com/EnableSecurity/sipvicious - Asterisk Documentation, "Named ACLs" (acl.conf, consumers, realtime propagation note). Retrieved 26 Oct 2026
https://docs.asterisk.org/Configuration/Core-Configuration/Named-ACLs/ - Asterisk security advisory GHSA-qqxj-v78h-hrf9 / CVE-2024-35190, "res_pjsip_endpoint_identifier_ip: wrongly matches ALL unauthorized SIP requests" (affected and patched versions). Published 17 May 2024
https://github.com/asterisk/asterisk/security/advisories/GHSA-qqxj-v78h-hrf9 - Asterisk Documentation, "PJSIP Authentication" (SHA-256 and SHA-512-256 digests from 20.12.0, 21.7.0, 22.2.0; auth_type values). Retrieved 26 Oct 2026
https://docs.asterisk.org/Configuration/Channel-Drivers/SIP/Configuring-res_pjsip/PJSIP-Authentication/ - NANPA, "About" (the NANP serves 20 countries; list of participating countries). Retrieved 26 Oct 2026
https://www.nanpa.com/about - NANPA, public NPA report (CSV): in-service general-purpose codes by country; 900 as Premium Services. File date 26 Oct 2026
https://reports.nanpa.com/public/npa_report.csv - Asterisk Documentation, FILTER() dialplan function. Generated from branch 23, retrieved 26 Oct 2026
https://docs.asterisk.org/Latest_API/API_Documentation/Dialplan_Functions/FILTER/ - Asterisk Documentation, REGEX() dialplan function. Generated from branch 23, retrieved 26 Oct 2026
https://docs.asterisk.org/Latest_API/API_Documentation/Dialplan_Functions/REGEX/ - Asterisk Documentation, GROUP() dialplan function. Generated from branch 23, retrieved 26 Oct 2026
https://docs.asterisk.org/Latest_API/API_Documentation/Dialplan_Functions/GROUP/ - Asterisk Documentation, GROUP_COUNT() dialplan function. Generated from branch 23, retrieved 26 Oct 2026
https://docs.asterisk.org/Latest_API/API_Documentation/Dialplan_Functions/GROUP_COUNT/ - 47 CFR § 9.16, General obligations: direct 911 dialing, notification, and dispatchable location (read via the eCFR versioner API). Edition of 1 Oct 2026, retrieved 26 Oct 2026
https://www.ecfr.gov/current/title-47/section-9.16 - Asterisk source tree, configs/samples/manager.conf.sample (enabled = no, webenabled, bindaddr, TLS port, permit/deny). master branch, retrieved 26 Oct 2026
https://github.com/asterisk/asterisk/blob/master/configs/samples/manager.conf.sample - Asterisk security advisory GHSA-c4cg-9275-6w44 / CVE-2024-42365, "Write=originate, is sufficient permissions for code execution / System() dialplan". Published 8 Aug 2024
https://github.com/asterisk/asterisk/security/advisories/GHSA-c4cg-9275-6w44 - Asterisk source tree, configs/samples/asterisk.conf.sample (directories, runuser/rungroup, live_dangerously). master branch, retrieved 26 Oct 2026
https://github.com/asterisk/asterisk/blob/master/configs/samples/asterisk.conf.sample - Asterisk security advisory GHSA-vrfp-mg3q-3959 / CVE-2026-57202, "ARI setChannelVar bypasses live_dangerously and permits FILE() writes". Published 25 Jun 2026
https://github.com/asterisk/asterisk/security/advisories/GHSA-vrfp-mg3q-3959 - Asterisk source tree, include/asterisk/security_events_defs.h (security event types). master branch, retrieved 26 Oct 2026
https://github.com/asterisk/asterisk/blob/master/include/asterisk/security_events_defs.h - Asterisk source tree, res/res_security_log.c (security events written to the SECURITY logger level). master branch, retrieved 26 Oct 2026
https://github.com/asterisk/asterisk/blob/master/res/res_security_log.c - Asterisk source tree, configs/samples/logger.conf.sample (log levels, commented security.log line, default messages.log, debug warning). master branch, retrieved 26 Oct 2026
https://github.com/asterisk/asterisk/blob/master/configs/samples/logger.conf.sample - fail2ban, config/filter.d/asterisk.conf (failregex for SecurityEvent and PJSIP failures). master branch, retrieved 26 Oct 2026
https://github.com/fail2ban/fail2ban/blob/master/config/filter.d/asterisk.conf - fail2ban, config/jail.conf ([asterisk] jail ports, logpath, maxretry; global defaults; do-not-modify instruction). master branch, retrieved 26 Oct 2026
https://github.com/fail2ban/fail2ban/blob/master/config/jail.conf - Asterisk source tree, configs/samples/rtp.conf.sample (rtpstart/rtpend, compiled defaults, strictrtp). master branch, retrieved 26 Oct 2026
https://github.com/asterisk/asterisk/blob/master/configs/samples/rtp.conf.sample - Asterisk Documentation, "Secure Calling Tutorial" (TLS transport, SDES endpoint, ast_tls_cert, version notes). Retrieved 26 Oct 2026
https://docs.asterisk.org/Deployment/Secure-Calling/Secure-Calling-Tutorial/ - IETF RFC 4568, Session Description Protocol (SDP) Security Descriptions for Media Streams, section 1 (keying material must be protected). July 2006
https://www.rfc-editor.org/rfc/rfc4568 - Asterisk Documentation, "Configuring res_pjsip to work through NAT" (local_net, external_* addresses, direct_media, remote phone options). Retrieved 26 Oct 2026
https://docs.asterisk.org/Configuration/Channel-Drivers/SIP/Configuring-res_pjsip/Configuring-res_pjsip-to-work-through-NAT/ - Asterisk Documentation, "STIR-SHAKEN" (1Q2024 refactor, configuration objects, deviations from specifications). Retrieved 26 Oct 2026
https://docs.asterisk.org/Deployment/STIR-SHAKEN/ - Asterisk ChangeLog 20.7.0, "Stir/Shaken Refactor" and its upgrade note (the 18.22.0 and 21.2.0 change logs carry the same entry). Retrieved 26 Oct 2026
https://downloads.asterisk.org/pub/telephony/asterisk/releases/ChangeLog-20.7.0.md - Asterisk commit 628f8d7, "Stir/Shaken Refactor" (why the refactor was needed; configuration object changes). Retrieved 26 Oct 2026
https://github.com/asterisk/asterisk/commit/628f8d7a43517e5da5becda33471dc2c44841bb6 - Asterisk source tree, configs/samples/stir_shaken.conf.sample (profile endpoint_behavior, failure_action, stir_shaken_profile on an endpoint). master branch, retrieved 26 Oct 2026
https://github.com/asterisk/asterisk/blob/master/configs/samples/stir_shaken.conf.sample - Asterisk security advisory GHSA-mrq5-74j5-f5cr / CVE-2025-49832, "Remote DoS and possible RCE in asterisk/res/res_stir_shaken/verification.c". Published 31 Jul 2025
https://github.com/asterisk/asterisk/security/advisories/GHSA-mrq5-74j5-f5cr - CST-GA, Canadian Secure Token Governance Authority, home page (role and participation). Retrieved 26 Oct 2026
https://www.cstga.ca/ - Asterisk source tree, configs/samples/cdr.conf.sample (enable, unanswered, batch mode data loss warning). master branch, retrieved 26 Oct 2026
https://github.com/asterisk/asterisk/blob/master/configs/samples/cdr.conf.sample - Asterisk Documentation, "CDR Specification" (multiple CDRs per call since Asterisk 12; CEL as the alternative). Retrieved 26 Oct 2026
https://docs.asterisk.org/Configuration/Reporting/Call-Detail-Records-CDR/CDR-Specification/ - Asterisk source tree, configs/samples/cel.conf.sample (enable defaults to no, apps, events). master branch, retrieved 26 Oct 2026
https://github.com/asterisk/asterisk/blob/master/configs/samples/cel.conf.sample - Asterisk Documentation, "Channel Event Logging (CEL)" overview (purpose and back-ends). Retrieved 26 Oct 2026
https://docs.asterisk.org/Configuration/Reporting/Channel-Event-Logging-CEL/ - Asterisk source tree, configs/samples/prometheus.conf.sample (res_prometheus defaults, HTTP and Basic Auth notes). master branch, retrieved 26 Oct 2026
https://github.com/asterisk/asterisk/blob/master/configs/samples/prometheus.conf.sample - Asterisk.org, Security Advisories (listing of advisories with dates and GHSA links). Behind a browser challenge; read via a scraping router. Retrieved 26 Oct 2026
https://www.asterisk.org/downloads/security-advisories/ - Asterisk GitHub repository, Security advisories (full list with dates, CVEs and severities; read via the GitHub API). Retrieved 26 Oct 2026
https://github.com/asterisk/asterisk/security/advisories - Asterisk Documentation, "Asterisk Security Vulnerabilities" (reporting process; where past advisories are published; CVEs). Retrieved 26 Oct 2026
https://docs.asterisk.org/About-the-Project/Asterisk-Security-Vulnerabilities/ - Asterisk security advisory GHSA-g8q2-p36q-94f6 / CVE-2026-57187 (one of the 25 June 2026 batch; lists the patched releases 20.20.1, 21.12.3, 22.10.1, 23.4.1, 20.7-cert11, 22.8-cert3). Published 25 Jun 2026
https://github.com/asterisk/asterisk/security/advisories/GHSA-g8q2-p36q-94f6 - Asterisk GitHub repository, Releases (tags and publication dates, read via the GitHub API). Retrieved 26 Oct 2026
https://github.com/asterisk/asterisk/releases - Asterisk Documentation, "Asterisk Versions" (support policy and release table). Retrieved 26 Oct 2026
https://docs.asterisk.org/About-the-Project/Asterisk-Versions/ - Asterisk ChangeLog 21.0.0 ("chan_sip: Remove deprecated module"). Retrieved 26 Oct 2026
https://downloads.asterisk.org/pub/telephony/asterisk/releases/ChangeLog-21.0.0.md
