Setup Asterisk

Asterisk is the most well-known open-source VoIP server. It serves as the core for an internal telephony network with SIP softphones and can be extended to integrate with the public switched telephone network (PSTN gateways) and computer telephony integration (CTI).

Preliminary knowledge

Before diving into the setup of Asterisk itself, it is effective to phase the deployment project and build it gradually. Here are the key phases:

  1. Implement robust brute-force protection, as exposing SIP ports make it susceptible to attacks.
  2. Ensure basic internal call connections, addressing NAT issues to establish connectivity.
  3. Add additional features and extensions.

SIP clients, including smartphone apps, enable SIP networks that can be used anywhere with an internet connection. However, in such cases, the configuration assumes that SIP endpoints like Asterisk are accessible from the internet.

Given the active nature of attacks on SIP hosts, implementing an IP-based firewall is essential for proper defense. Effective measures include the deployment of tools like fail2ban.

While there are mitigation strategies such as avoiding the well-known port 5060 and using longer passwords, attacks cannot be deterred unless trial attempts are limited.

Alternatively, you can choose not to expose the SIP network to the internet by connecting the entire internal network through a VPN. However, this configuration comes with trade-offs, including the challenges and usability issues associated with VPNs.

Build & container environments

Asterisk itself is actively maintained, but due to a lack of maintainers for Debian, Debian-based packages have been once removed from bookworm (June 2023). You need to either build it yourself or use some alternative packages.

For Docker container images, the build script of andrius/asterisk is well thought out.
Since features like voicemail management require audio files, you can install additional packages such as asterisk-core-sounds-en-wav. These files can then be symlinked to $astdatadir/sounds/en.

However, there are different constraints in a container environment.
Significant one is the potential incompatibility of iptables. Existing security implementations like fail2ban assume iptables, requiring an alternative means for firewall construction.
For example, in a Kubernetes cluster, NetworkPolicy might be promising.

Also, limitations on access to device files can result in constraints on audio control.
Since each SIP client supports diverse codecs, Asterisk has a feature to convert codecs, but the daemon responsible for this might not start.
While it outputs errors in the startup logs, it continues to operate with the missing functionality.

In configurations where the codec transcoder is missing, proper operation occurs only when both ends of the clients select a codec supported by both.
If audio data with an unsupported codec flows, the connection may be dropped or become silent. The behavior of “connection is established but no audio” can also happen due to other reasons, making troubleshooting more challenging.
This issue can sometimes be avoided by narrowing down the supported codecs.

Configuration

Building a SIP network is essentially centralized in Asterisk’s configuration, and it will work if configured correctly.
However, ensuring appropriateness is not straightforward. The following approaches for information gathering can be effective:

  • Understand the official documentation
    • While this might seem obvious, it is not widely listed in search engine results due to being an unorthodox static site.
    • The links between pages are aggregated in a hidden left navigation, and it’s important to open the left navigation on each page to check for related information.
  • Refer to the sample configurations
    • Asterisk’s configuration consists of a collection of configuration files for each module, making it complex. These samples are likely the most comprehensive reference.
    • The syntax is a simple TOML. It’s beneficial to understand Templates for reuse.
  • Deepen the understanding of SIP networks
    • The complexity of Asterisk is derived from the complexity of SIP networks. Ultimately, operating Asterisk without understanding SIP technology is not realistic.
    • The core elements necessary for basic SIP setup are SIP, RTP, and ICE.

It’s also crucial not to rely on outdated information.
Over the long history of Asterisk, the core SIP functionality transitioned from chan_sip to chan_pjsip, and in version 21.0, released in 2023, chan_sip was finally removed.

Currently, pjsip.conf is one of the main configuration files.
As sip.conf is no longer in use, it would be challenging to apply outdated information that resembles but is different from the current configuration.

Additionally, the dial plan configuration is explained in a separate article.

Debug logs

The difficulty in network engineering lies in the challenge of directly grasping causality.
Asterisk, like any other system, experiences seemingly unexplained issues until the call session is established and voice data starts flowing.

While logs are scarce in indicating causality, trying to troubleshoot without logs makes speculation even more challenging.
The most useful information up to the initial SIP call establishment comes from SIP logs that include SDP.

You can initiate the TUI interactive tool with asterisk -r and switch to log output mode by executing pjsip set logger on.
With the logger on, SIP messages will flow to the console when you perform a SIP connection. The tool can be exited with the quit command.

While cases directly readable from the logs are almost non-existent, common causes often include:

  • Routing issues on the Asterisk server side, leading to requests not reaching at all, possibly due to TCP/UDP mismatch.
  • Prioritizing private networks and messages not reaching properly.
  • The client-side router discarding packets.
  • Codec selection issues leading to session abandonment.
  • Configuration not meeting the request to enforce a specific security communication method, resulting in session abandonment.
  • Necessary modules not loaded during startup or excluded from the build altogether.

Since the fact that messages are not reaching can be a significant hint, it’s relatively smoother during construction to use a tool that allows both Asterisk and all clients to output all SIP logs.

Furthermore, logs may include entries that seem like errors but are not the cause of the problem, adding to the confusion:

  • Private IP being related to packet non-delivery, but the SDP displaying private IP may still work, often resolved by ICE.
  • 401 Unauthorized is often part of the normal operation process.

Until one comprehensively understands the SIP architecture, understanding behavior can be challenging.

Other CLI commands

In addition to logs, there are interactive subcommands in the Asterisk command that allow for situational analysis.
For example, the connection status of SIP clients can be viewed with show endpoints, and the history of SIP messages can be displayed using show history.

asterisk*CLI> pjsip show endpoints
asterisk*CLI> pjsip set history on
asterisk*CLI> pjsip show history
asterisk*CLI> pjsip show history entry 1

The most confusing and frequently encountered case in history analysis is when there is no response. It’s important to note that only the request message is recorded and there is no error response.

No response can occur due to various reasons such as IP translation by NAT, filtering by a firewall, or the destination service dropping the request in case of an authentication error.

In this case, it will be necessary to adjust the network configuration and connection settings until some response can be obtained.

pjsip.conf

pjsip.conf primarily configures the Asterisk SIP service, defining transport for SIP service and blocks like endpoint for connection information of SIP clients.
The official guide provides an explanation of the roles of each section.

transport section

transport would be configured in a more complex case, such as for sips, like the following:

[transport-tls]
type = transport
protocol = tls
bind = 0.0.0.0:5061
; need to have external address for internet
external_media_address=203.0.113.1
external_signaling_address=203.0.113.1
local_net = 192.168.0.0/255.255.255.0
; SSL settings
cert_file = /etc/asterisk/cert.pem
priv_key_file = /etc/asterisk/privkey.pem
; tlsv1 | sslv23 can be specified, too.
method = tlsv1_2

Whether TLS certificates work using self-signed files depends on the configuration of the connecting client.
If you disregards destination verification, it should work without any issues. As long as encryption is functioning, this might be sufficient for certain operational scenarios.

Within the transport settings, a potentially confusing point is the local_net, which has a significant impact on behavior.
This setting is used to exclude internal IPs, and it should be appropriately specified to represent the local network of the Asterisk host.

Even if you don’t specify local_net, client-to-client connections can be completed without errors, but there may be situations where the audio packets don’t reach, resulting in no sound.
This behavior arises from the way the SDP in the INVITE guides the internal IP of the Asterisk server to the called party. Checking the SDP logs of the incoming client can help diagnose this issue.

UDP-based RTP doesn’t treat packet loss as an anomaly and simply results in silence.
Because there are no errors, identifying the root cause becomes more challenging.

endpoint section

The structure of specifying endpoint on the client side, along with aor and auth, can be initially challenging to grasp. auth contains authentication information, while aor is the address used for inbound routing searches.

Within the endpoint, you specify the reference relationships of the blocks and SIP options.

[101]
type = endpoint
context = default
auth = 101
outbound_auth = 101
aors = 101
; must have codec list
allow = g729,ulaw,alaw,ilbc
; almost all configuration requires NAT settings
direct_media = no
ice_support = yes
rewrite_contact = yes
rtp_symmetric = yes
force_rport = yes

The options for NAT must be appropriately specified along with the network configuration.
Unless it is a SIP network limited to the LAN, additional settings for NAT are essential.
In many cases, especially for networks beyond the LAN, STUN is likely a necessary part of ICE, and if a more secure router (Symmetric NAT) is in use, TURN might also be required.

Another point that may be unclear is the need to accurately specify the codec list.
If no codecs are specified, a 488 Not Acceptable Here error will be returned during a SIP call. More generally, it’s a 488 error if the proposed codec list in the INVITE request from the SIP client doesn’t match.
This error does not log related information, making it difficult to notice that it indicates a situation where there was no matching codec candidate.
Additionally, if the call cannot be routed to the intended destination, the error code will be 404 Not Found.

As mentioned earlier, if the codecs between peers do not match, Asterisk attempts transcoding, but this may not work in container environments, resulting in silence.

SIP Trunking Connection

Connecting with SIP trunking requires adapting to the specifications of each service provider.
For services that require REGISTER, you need to add a type = registration setting. For services that connect via INVITE for calls, specify the destination host in endpoint.outbound_proxy.

If user authentication is required, configure the auth settings in either registration.outbound_auth or endpoint.outbound_auth, depending on your configuration.

For incoming calls to Asterisk, user authentication settings can be specified in endpoint.auth. Additionally, IP restrictions for incoming calls can be implemented using identity.match. Although not documented, multiple IPs can be listed using a comma-separated format.

Apart from connection settings, outbound_proxy and aor.contact can affect the Request-URI and To headers of SIP messages during outbound calls. Some services may expect specific URIs in SIP message fields, and they may reject requests if a simple local network request is sent.

If there is no response or if you receive a 403 FORBIDDEN despite the request being sent from the correct IP, it is advisable to verify the validity of the SIP request and adjust the configuration to generate an appropriate message.

TLS & SRTP

Regarding encryption with TLS and SRTP, configurations that enforce support are naturally more secure. By excluding settings that fall back to non-TLS or non-SRTP, clients without these capabilities won’t be able to connect.

For SIP TLS protection, as mentioned earlier, you create a TLS-configured transport and use it accordingly in the configuration.
As for SRTP, you add the media_encryption setting to the endpoint:

[101]
type = endpoint

media_encryption = sdes

;media_encryption_optimistic=no ; Use encryption if possible but don't fail the call
                                ; if not possible.

The option may not be intuitive, but for SRTP, the specification is sdes. Considering that the default is no, specifying yes will likely result in a Parse Error on start-up.
SRTP has few configuration items and is less prone to unexpected impacts. If it doesn’t work, there may be a possibility that the module is not loaded.

Since there is no way to know the loading status of modules, executing the command module load res_srtp.so from the console will reload the module, and if there are issues, they should be reproducible.
If the module was loaded correctly, a WARNING stating already loaded and running will appear.

The official guide also provides information on encryption.

rtp.conf

The configuration itself of rtp.conf is relatively simple. However, RTP often does not work properly, and in many cases, error logs may not be generated.
If there are deficiencies in the RTP configuration, there will be no audio.

[general]
;
; RTP start and RTP end configure start and end addresses
;
; Defaults are rtpstart=5000 and rtpend=31000
;
rtpstart=10000
rtpend=20000

; Hostname or address for the STUN server used when determining the external
; IP address and port an RTP session can be reached at. The port number is
; optional. If omitted the default value of 3478 will be used. This option is
; disabled by default. Name resolution will occur at load time, and if DNS is
; used, name resolution will occur repeatedly after the TTL expires.

stunaddr=stun.l.google.com:19302

; Hostname or address for the TURN server to be used as a relay. The port
; number is optional. If omitted the default value of 3478 will be used.
; This option is disabled by default.
;
; e.g. turnaddr=myturn.server.com:34780
;
; turnaddr=
;
; Username used to authenticate with TURN relay server.
; turnusername=
;
; Password used to authenticate with TURN relay server.
; turnpassword=

A key point in the configuration is to ensure proper routing for UDP access to the range of ports specified by rtpstart and rtpend.
If there is a behavior where packets are not sent to the server’s IP and the ports are closed, it can become difficult to troubleshoot.

STUN is generally considered essential in many cases.
The need for TURN depends on the type of router you have installed. There are many network configurations where TURN is not necessary, and if needed, it can be set up separately. It’s important to note that Asterisk does not provide functionality for STUN/TURN servers.

The issue of no audio can be attributed to various factors, including client issues and codec selection problems. However, server-side problems are likely related to misconfigurations in ICE, including STUN/TURN settings.
Regarding ICE, it seems that misconfigurations are more likely to occur in the pjsip.conf section than in rtp.conf.

⁋ Dec 6, 2023↻ Sep 12, 2024
中馬崇尋
Chuma Takahiro