Configuring SRV Records for SIP and XMPP Services
SIP and XMPP rely on DNS SRV records for service discovery, load balancing, and failover across distributed endpoints. A misconfigured SRV record causes silent connection drops, client fallback to A/AAAA resolution, and unintended bypass of your load balancers. This guide walks through the exact zone syntax, provider-specific deployment via the Cloudflare and Route 53 APIs, and the diagnostic workflows you need to run real production VoIP and messaging infrastructure. By the end you will have working _sip._tcp, _sip._tls, _xmpp-client._tcp, and _xmpp-server._tcp records, verified against authoritative nameservers and live socket tests.
Key objectives:
- Author RFC-compliant SRV records that decouple service discovery from static IP addressing, enabling dynamic failover and proportional traffic distribution.
- Deploy SIP (
_sip._tcp,_sip._tls) and XMPP (_xmpp-client,_xmpp-server) records that follow RFC 3263 and RFC 6120 naming conventions exactly. - Point every SRV target at an A/AAAA host directly — CNAME targets violate RFC 1034 and break most SIP/XMPP stacks.
- Validate records against the authoritative nameserver and live ports before routing production traffic.
SRV Record Anatomy
The wire format is: _service._proto.name. TTL IN SRV priority weight port target.
- Priority: lower value = higher preference; traffic goes to the lowest-priority tier first.
- Weight: proportional distribution among records sharing the same priority. A weight of 0 disables proportional distribution; only one target at that priority is used.
- Port: the TCP/UDP port the target listens on.
- Target: an FQDN with a trailing dot. Must resolve directly to an A/AAAA record.
SIP uses _sip._tcp (unencrypted/STARTTLS) and _sip._tls (TLS-only, port 5061). XMPP uses _xmpp-client._tcp (client-to-server, port 5222) and _xmpp-server._tcp (server-to-server, port 5269). The leading underscore on the service and protocol labels is mandatory — it is reserved by RFC 2782 precisely so these labels can never collide with a real hostname, which is also why SRV targets resolve to ordinary A/AAAA hosts rather than to other underscore labels.
The same priority/weight algorithm that governs SRV selection also governs MX record selection, so if you operate mail alongside voice and chat, the mental model carries directly over to Advanced SRV & MX Routing. For broader zone hierarchy and resolver behavior, see DNS Fundamentals & Advanced Record Configuration.
dig SRV _sip._tcp.example.com
Expected output (answer section): one line per record, each showing priority weight port target, for example 10 70 5060 sip-node1.example.com.. If the ANSWER: 0 counter is zero, the label is wrong or the record is absent.
Prerequisites & Environment Setup
Before authoring records, confirm the following:
- Authoritative DNS access — either a registrar/managed DNS dashboard, the Cloudflare API token (
Zone.DNS:Edit), AWS credentials withroute53:ChangeResourceRecordSets, or write access to a BIND/PowerDNS zone file. - The A/AAAA records for every intended SRV target already exist and resolve. SRV records reference these targets by FQDN; if
sip-node1.example.comhas no address record, clients will sort it into the candidate list and then fail to connect. - Local tooling:
dig(bind-utils / dnsutils),host,nslookup,nc, andopensslfor verification. On the SIP/XMPP servers, confirm the listening ports withss -tlnp. - A non-production label or low TTL for the first deployment so you can iterate without long cache waits.
# Confirm the target host actually resolves to an address before referencing it
dig +short A sip-node1.example.com
dig +short AAAA sip-node1.example.com
Expected output: at least one IPv4 (and optionally IPv6) address. An empty result means the target does not exist yet — create the A/AAAA record first.
Step 1: Author the SIP SRV Records
Production SIP trunking requires primary, failover, and TLS entries. Modern clients enforce encryption by default — deploy _sip._tls records or those clients will reject connections.
; Primary SIP (70% traffic)
_sip._tcp.example.com. 300 IN SRV 10 70 5060 sip-node1.example.com.
; Primary SIP (30% traffic)
_sip._tcp.example.com. 300 IN SRV 10 30 5060 sip-node2.example.com.
; Cold standby
_sip._tcp.example.com. 300 IN SRV 20 0 5060 sip-dr.example.com.
; Secure SIP (TLS, port 5061)
_sip._tls.example.com. 300 IN SRV 10 100 5061 sip-node1.example.com.
Priority 10 records share a 70/30 split. Priority 20 activates only when all priority-10 targets fail. The TTL of 300s balances cache freshness against authoritative query load — covered in depth alongside the trade-offs in Mastering TTL Strategies.
host -t SRV _sip._tcp.example.com
Expected output: two lines for priority 10 plus one for priority 20, each ending in the target FQDN. The TLS query (host -t SRV _sip._tls.example.com) should return a single port-5061 line.
Step 2: Author the XMPP SRV Records
XMPP splits client-to-server and server-to-server traffic across distinct service names per RFC 6120.
; Client-to-server (port 5222)
_xmpp-client._tcp.example.com. 300 IN SRV 5 0 5222 xmpp.example.com.
; Server-to-server federation (port 5269)
_xmpp-server._tcp.example.com. 300 IN SRV 5 0 5269 xmpp.example.com.
For weighted distribution across federated nodes, assign equal priority with non-zero weights:
_xmpp-client._tcp.example.com. 300 IN SRV 5 70 5222 xmpp-primary.example.com.
_xmpp-client._tcp.example.com. 300 IN SRV 5 30 5222 xmpp-secondary.example.com.
Missing _xmpp-client records force clients into direct A/AAAA resolution, bypassing load balancers entirely. For the priority/weight interaction details that apply identically to SIP, XMPP, and mail, see Advanced SRV & MX Routing.
nslookup -type=SRV _xmpp-server._tcp.example.com
Expected output: one service = 5 0 5269 xmpp.example.com line. A ** server can't find ... NXDOMAIN response means the label is malformed — check for a missing underscore or a typo in _xmpp-server.
Step 3: Deploy at the Authoritative DNS Level
SRV records must be deployed at the authoritative DNS level — CDNs do not proxy SRV, SIP, or XMPP traffic.
Cloudflare: Use the DNS dashboard, select record type SRV. The proxy toggle is forced to DNS-only for SRV records — there is no CDN proxying for non-HTTP protocols.
AWS Route 53: Use the console or API with explicit priority, weight, port, and target fields. Do not use Alias targets for SRV records.
BIND9/PowerDNS: All FQDNs require a trailing dot. Omitting it causes the zone origin to be appended, corrupting the target hostname (sip-node1.example.com silently becomes sip-node1.example.com.example.com).
Cloudflare API (correct SRV payload format):
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/{zone_id}/dns_records" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
--data '{
"type": "SRV",
"data": {
"service": "_sip",
"proto": "_tcp",
"name": "example.com",
"priority": 10,
"weight": 60,
"port": 5060,
"target": "sip-node1.example.com"
},
"ttl": 300
}'
Expected output: a JSON body with "success": true and a populated result.id. Note that the Cloudflare SRV API uses a data object with separate fields — not a single content string.
AWS Route 53 JSON (change-batch format):
{
"ChangeBatch": {
"Changes": [{
"Action": "UPSERT",
"ResourceRecordSet": {
"Name": "_sip._tls.example.com.",
"Type": "SRV",
"TTL": 300,
"ResourceRecords": [{"Value": "10 60 5061 sip-node1.example.com."}]
}
}]
}
}
The trailing dot in both Name and the Value target prevents domain suffix duplication. UPSERT is idempotent and safe for CI/CD pipelines. Apply it with aws route53 change-resource-record-sets --hosted-zone-id ZID --change-batch file://srv.json; the response returns a ChangeInfo.Status of PENDING, which flips to INSYNC once the change has propagated to all Route 53 nameservers.
Verification
Validate every record against the authoritative server and against the live socket before sending production calls or sessions through it.
# Query the authoritative server directly (bypasses recursive caches)
dig @ns1.provider.com SRV _sip._tcp.example.com +short
# Trace the full resolution path from the root
dig +trace SRV _xmpp-client._tcp.example.com
# Verify the target resolves to an address (not a CNAME)
dig +short A sip-node1.example.com
# Verify the port is open and accepting connections
nc -zv sip-node1.example.com 5060
# Verify TLS terminates on port 5061
openssl s_client -connect sip-node1.example.com:5061 -quiet
# Display only the answer section for a clean diff in CI
dig SRV _sip._tcp.example.com +noall +answer
Expected output:
dig ... +shortprints10 70 5060 sip-node1.example.com.style lines — one per record.nc -zvreportsConnection to sip-node1.example.com 5060 port [tcp/*] succeeded!.openssl s_clientprints a certificate chain andVerify return code: 0 (ok).
Monitor application logs for SRV lookup failed or fallback to A record warnings. These indicate malformed entries or resolver timeouts and mean clients are no longer honoring your routing policy.
Because SIP and XMPP servers also originate email (alerts, voicemail-to-email, federation notices), treat the SRV rollout as the moment to harden the rest of the zone: publish SPF records to prevent spoofing for the same sending hosts so receivers can distinguish your legitimate traffic from forgeries.
Troubleshooting
CNAME as SRV target
Diagnosis: dig +short A <target> returns a hostname rather than an IP, or the client logs reject the record. RFC 1034 prohibits CNAME records as SRV targets, and most SIP/XMPP clients explicitly refuse them. Fix: replace the CNAME with a direct A/AAAA record on the target name, or repoint the SRV target at a host that already has address records.
XMPP or SIP client ignores the records
Diagnosis: dig SRV _xmpp-client._tcp.example.com returns ANSWER: 0, or the port/label is wrong. Clients silently fall back to A/AAAA on the bare domain. Fix: verify the exact _service._proto label, confirm the trailing dot on the target, and confirm the port matches the listener (ss -tlnp on the server).
Missing _sip._tls records
Diagnosis: TLS-only clients fail to register while _sip._tcp works fine. Modern SIP clients enforce encryption by default and may ignore the plaintext record entirely. Fix: deploy _sip._tls records pointing to a host that accepts TLS on port 5061 (or STARTTLS on 5060), then re-test with openssl s_client.
Trailing-dot corruption in BIND/PowerDNS
Diagnosis: dig SRV returns a target like sip-node1.example.com.example.com.. The origin was appended because the target FQDN lacked its trailing dot. Fix: add the trailing dot to every fully qualified target in the zone file and reload (rndc reload).
Slow failover after an outage Diagnosis: clients keep hitting a dead priority-10 target for minutes. They cache SRV records for the configured TTL. Fix: set TTL to 60–300s and drive record changes from health checks via the provider API so the standby tier is promoted as soon as the primary is marked down.
Related
- Configuring SPF Records to Prevent Spoofing — once your voice and chat records are live, lock down the mail side of the same zone against forged senders.
- Setting Up DKIM Signing for Your Domain — add cryptographic signatures so receivers can verify mail from your domain.
- Advanced SRV & MX Routing — the shared priority/weight model behind SRV and MX selection.
- Mastering TTL Strategies — choosing TTLs that balance failover speed against query load.
Back to Advanced SRV & MX Routing
Frequently Asked Questions
Can I use CNAME records as SRV targets? No. RFC 1034 and RFC 3263 both prohibit CNAMEs at SRV targets, and most clients reject them outright. Point the target at an A/AAAA record directly.
Why is my XMPP client ignoring my SRV records?
Clients fall back to A/AAAA on the bare domain when _xmpp-client._tcp records are missing, malformed, or use the wrong port. Verify the exact service/protocol label and port mapping with dig SRV _xmpp-client._tcp.example.com.
How do I distribute traffic evenly across multiple SIP proxies?
Assign identical priority values and equal weights (for example 10 50 for both records). Clients distribute new sessions proportionally by weight within the lowest-priority tier.
Do edge CDNs support SRV record routing? No. CDNs operate at Layer 7 (HTTP/HTTPS) and do not proxy SRV, SIP, or XMPP traffic. Deploy SRV records as DNS-only at the authoritative level; Cloudflare forces DNS-only mode for SRV automatically.
What TTL should I set on SRV records for fast failover? Use 60–300 seconds. Lower TTLs shorten the window during which clients cling to a failed target, at the cost of more authoritative queries. Pair a short TTL with health-check-driven API updates for the fastest convergence.