Asterisk 14 DNS: Resolve to Resolve

Asterisk 14: Coming with improved PJSIP DNS Support spoke about the new core DNS API, and mentioned several of the enhancements implemented. In this post we will focus more on the pluggable module that wraps the unbound DNS resolver library mentioned. Specifically with regards to how it can be used.

res_resolver_unbound

Besides the default system resolver Asterisk 14 contains a loadable resolver module that wraps the libunbound library. During the Asterisk configure process if libunbound is installed, and discovered on the system it is automatically selected in menuselect (Resource Modules → res_resolver_unbound) and loaded at startup. The module can be configured via the resolver_unbound.conf file. The following options can be set:

  • hosts – The full path to a hosts file. If “system” is specified (it’s the default) then module uses the system specific host file. Any matching domain is resolved in the resolver itself.
  • resolv – The full path to a resolv.conf file. Similar to the hosts option this too can be set to “system” (the default as well).
  • nameserver – A nameserver used for resolving queries. Note that multiple nameservers can be specified by adding more nameserver lines. The first line is the primary with failover occurring in the listed order. Any address(es) specified here also take precedence over those in any provided resolve.conf file.
  • ta_file – The full path to a trusted anchors key file (DS and DNSKEY records in a zone format), which are used to verify DNSSEC signed results.
  • debug – The debug level to run the unbound resolver at. Higher numbers produce more debug.

Sample Configuration

Here is what a sample configuration might look like:

[general]
nameserver = 127.0.0.1@10053

The above configuration means that when the res_resolver_unbound module attempts to resolve a name it will first check the system hosts file (default for the hosts option remember), then if an associated address is not found there it sends a request to the specified nameserver. In this example our nameserver just happens to be on the same machine listening on port 10053. Failing that it then proceeds to check those addresses listed in the system resolv.conf. What if for some reason we don’t want it to look in the system’s resolv.conf file, or for that matter any resolv.conf file? We can do that with the following configuration:

[general]
nameserver = 127.0.0.1@10053
resolv =

Simply leave the resolv option empty. The same can be done for the hosts option as well if needed.

An Example

This seems like a good time for an example. Using the above res_resolver_unbound configuration we’ll trace a call to a domain our server can resolve. We’ll use “example.com” as our domain (very original I know). Here is a zone configuration for our nameserver:

zone = [
    SOA(
        # For whom we are the authority
        'example.com',
        # This nameserver's name
        mname = "ns1.example.com",
        # Mailbox of individual who handles this
        rname = "root.example.com",
        # Unique serial identifying this SOA data
        serial = 2003010601,
        # Time interval before zone should be refreshed
        refresh = "1H",
        # Interval before failed refresh should be retried
        retry = "1H",
        # Upper limit on time interval before expiry
        expire = "1H",
        # Minimum TTL
        minimum = "1H"
    ),

    NAPTR('example.com', 50, 50, 'S', 'SIP+D2T', '', '_sip._tcp.example.com'),
    NAPTR('example.com', 50, 90, 'S', 'SIP+D2U', '', '_sip._udp.example.com'),
    SRV('_sip._udp.example.com', 0, 1, 5061, 'pbx.example.com'),
    A('pbx.example.com', '127.0.0.1'),
]

Note that the lowest priority NAPTR record points to an SRV record that does not exist. However, the next prioritized NAPTR record does point to a valid SRV record. The call we make will not specify the transport. Since there won’t be an explicit transport on the call the higher priority record should be tried first, failing over to the secondary record when it can’t find it. After making the call we can check the Asterisk logs and should see something similar to the below:

DEBUG[11123] res_pjsip/pjsip_resolver.c: [0x27aaf78] All parallel queries completed
DEBUG[11123] res_pjsip/pjsip_resolver.c: [0x27aaf78] NAPTR record received on target 'example.com'
DEBUG[11123] res_pjsip/pjsip_resolver.c: [0x27aaf78] Added target '_sip._tcp.example.com' with record type '33', transport 'TCP', and port '5060'
DEBUG[11123] res_pjsip/pjsip_resolver.c: [0x27aaf78] NAPTR record received on target 'example.com'
DEBUG[11123] res_pjsip/pjsip_resolver.c: [0x27aaf78] Added target '_sip._udp.example.com' with record type '33', transport 'UDP', and port '5060'
DEBUG[11123] res_pjsip/pjsip_resolver.c: [0x27aaf78] SRV record received on target '_sip._udp.example.com'
DEBUG[11123] res_pjsip/pjsip_resolver.c: [0x27aaf78] Added target 'pbx.example.com' with record type '1', transport 'UDP', and port '5061'
DEBUG[11123] res_pjsip/pjsip_resolver.c: [0x27aaf78] New queries added, performing parallel resolution again
DEBUG[11123] res_pjsip/pjsip_resolver.c: [0x27aaf78] All parallel queries completed
DEBUG[11123] res_pjsip/pjsip_resolver.c: [0x27aaf78] SRV record received on target '_sip._udp.example.com'
DEBUG[11123] res_pjsip/pjsip_resolver.c: [0x27aaf78] Added target 'pbx.example.com' with record type '1', transport 'UDP', and port '5061'
DEBUG[11123] res_pjsip/pjsip_resolver.c: [0x27aaf78] A record being skipped on target 'pbx.example.com' because NAPTR or SRV record exists
DEBUG[11123] res_pjsip/pjsip_resolver.c: [0x27aaf78] New queries added, performing parallel resolution again
DEBUG[11123] res_pjsip/pjsip_resolver.c: [0x27aaf78] All parallel queries completed
DEBUG[11123] res_pjsip/pjsip_resolver.c: [0x27aaf78] A record received on target 'pbx.example.com'
DEBUG[11123] res_pjsip/pjsip_resolver.c: [0x27aaf78] Resolution completed - 1 viable targets
DEBUG[11108] res_pjsip/pjsip_resolver.c: [0x27aaf78] Address '0' is 127.0.0.1:5061 with transport 'UDP'

We can see by the log trace that the resolver (Note, it says pjsip_resolver but that’s just an abstract layer sitting on top of the unbound resolver – more about the DNS pjsip changes here) did exactly as we expected. It attempted the higher priority record with no associated SRV record. Failing that it went on to the next NAPTR record where it found a match.

As mentioned this call did not specify a transport, but if we had specified one, for instance, TCP then it would have failed to resolve the address since the only matching TCP NAPTR record does not resolve. If we would have specified UDP as the transport the query would resolve the name, but this time you would not see it try the TCP one first.

Concluding Remarks

Asterisk 14 has some great new features with the new core DNS API being one of them. The new API is also both robust and efficient. While the pluggable framework found within is also flexible and powerful. Now, having the ability to use a library like libunbound to resolve your DNS queries one can easily and immediately take advantage of a feature full resolver.

Leave a Reply

Your email address will not be published. Required fields are marked *


The reCAPTCHA verification period has expired. Please reload the page.

About the Author

What can we help you find?