Skip to content

Dahua VTO2111D-P-S2: registration flapping (digest nonce/nc reuse) and call teardown after answer #85

Description

@teuchezh

Dahua VTO2111D-P-S2: registration flapping (nonce/nc reuse) + call media negotiation fails (PCM/16000)

Environment

  • VoIP Stack version: 2026.8.0
  • Home Assistant Core: 2026.7.3 (HAOS 18.1, running as a Proxmox VM, --network=host)
  • Device: Dahua VTO2111D-P-S2, firmware V4.700.0.3, User-Agent: Dahua UAC/3.0 VTO2111D-P-S2
  • SIP transport: UDP, port 5060
  • Auth: local SIP account created in VoIP Stack (username 100, digest auth, realm="voip_stack")
  • VTO configured as Third-party SIP server client (its own "SIP Server" toggle OFF), registering to HA.

Summary

A Dahua VTO can register to the VoIP Stack local registrar and signaling reaches HA, but I run into three separate Dahua-specific interop problems. All three are reproducible and I have full tcpdump traces for each.


1. Registration flapping (digest nonce / nc reuse)

The VTO reuses the same cnonce="0a4f113b" on every request and always sends nc=00000001. On the periodic re-REGISTER (Expires: 60) it also reuses the previous nonce. The result: one REGISTER succeeds with 200 OK, but subsequent refreshes with the same nonce/nc get 401, so the contact flaps online/offline roughly every 60 seconds.

Username in Authorization matches From/Contact (both 100), and response is recomputed correctly — it still gets 401 on refresh:

REGISTER sip:192.168.1.112 SIP/2.0
From:    <sip:100@192.168.1.112:5060>;tag=...
To:      <sip:100@192.168.1.112:5060>
Contact: <sip:100@192.168.1.108:5060>
Authorization: Digest username="100", realm="voip_stack",
  nonce="3fc65932afe543221c87b7786c11246d", uri="sip:192.168.1.112",
  response="5c298e37bcfba35afe8c7b4a3de856e4", algorithm=MD5,
  cnonce="0a4f113b", qop=auth, nc=00000001
Expires: 60
User-Agent: Dahua UAC/3.0 VTO2111D-P-S2 V4.700.0.3

-> SIP/2.0 200 OK          (first REGISTER)
-> SIP/2.0 401 Unauthorized (subsequent refreshes, same nonce + nc=00000001)

Question: can the registrar tolerate Dahua's non-incrementing nc / nonce reuse (or issue a fresh nonce) without dropping the binding, so the endpoint stays stable? Similar Dahua deployments report the device also expects OPTIONS/keepalive after registration.

tcpdump — registration flap (successful 200 OK surrounded by 401 refreshes)
# initial REGISTER (no auth) -> 401 challenge
18:20:38 In  192.168.1.108.5060 > 192.168.1.112.5060: REGISTER sip:192.168.1.112 SIP/2.0
  Call-ID: 9ec5b5b1152be0e4341c0876f2f3fef4
  From:    <sip:100@192.168.1.112:5060>;tag=09dd7576ce183adb2a78115eb529b00c
  Contact: <sip:100@192.168.1.108:5060>
  CSeq: 1 REGISTER   Expires: 60
18:20:38 Out 192.168.1.112.5060 > 192.168.1.108.5060: SIP/2.0 401 Unauthorized
  WWW-Authenticate: Digest realm="voip_stack", nonce="e513d352dad9c93e767c1c17e98227e9", algorithm=MD5, qop="auth"

# authed REGISTER, username matches From/Contact, response recomputed
18:34:20 Out ... 401 Unauthorized
18:34:21 In  192.168.1.108.5060 > 192.168.1.112.5060: REGISTER sip:192.168.1.112 SIP/2.0
  Authorization: Digest username="100", realm="voip_stack",
    nonce="...", uri="sip:192.168.1.112",
    response="faa90fe346dc97fbbb79d4416778a6ea", algorithm=MD5,
    cnonce="0a4f113b", qop=auth, nc=00000001
  Expires: 60
18:34:21 Out 192.168.1.112.5060 > 192.168.1.108.5060: SIP/2.0 200 OK   <-- succeeds once

# next refresh reuses same nonce + nc=00000001 -> 401 again, contact flaps offline
18:34:49 Out ... SIP/2.0 401 Unauthorized
18:34:50 Out ... SIP/2.0 401 Unauthorized
18:34:51 Out ... SIP/2.0 401 Unauthorized

Note: across many capture sessions the cnonce is always 0a4f113b and nc is always 00000001.


2. Call media negotiation fails — VTO offers PCM/16000, HA sends BYE

Calling HA softphone -> VTO: INVITE -> 180 Ringing -> 200 OK, then HA immediately sends ACK followed by BYE, so the call drops right after answer.

HA offered:

a=rtpmap:98 OPUS/48000/2
a=rtpmap:8  PCMA/8000/1
a=rtpmap:0  PCMU/8000/1
a=rtpmap:96 L16/16000/1

VTO 200 OK SDP answer:

a=rtpmap:96 PCM/16000
a=rtpmap:99 telephone-event/8000
a=fmtp:99 0-15
a=sendrecv
a=rtpmap:103 H264/90000
a=sendonly

The VTO advertises Dahua wideband PCM/16000 (payload 96) for audio plus H264 sendonly video, which does not match HA's offered L16/16000 / PCMA / PCMU / OPUS. HA appears unable to select a common audio format and tears the call down with BYE right after ACK.

Question: is Dahua PCM/16000 (payload 96) meant to be treated as L16/16000, or is a G.711-only (PCMA/PCMU) path the expected way to interoperate with Dahua VTO? Is there a way to force/pin the negotiated audio codec for a given account or route?

tcpdump — HA softphone -> VTO: INVITE -> 180 -> 200 OK -> ACK -> immediate BYE
# HA offers OPUS / PCMA / PCMU / L16
17:55:43 Out 192.168.1.112.43269 > 192.168.1.108.5060: INVITE sip:DOORBELL@192.168.1.108:5060 SIP/2.0
  From: <sip:Home%20Assistant@192.168.1.112:43269;transport=udp>;tag=2f112417ef5364c6
  To:   <sip:DOORBELL@192.168.1.108:5060>
  a=rtpmap:98 OPUS/48000/2
  a=rtpmap:8  PCMA/8000/1
  a=rtpmap:0  PCMU/8000/1
  a=rtpmap:96 L16/16000/1

17:55:43 In  192.168.1.108.5060 > 192.168.1.112.43269: SIP/2.0 180 Ringing
17:55:43 In  192.168.1.108.5060 > 192.168.1.112.43269: SIP/2.0 200 OK
  Content-Type: application/sdp   (VTO answer)
  a=rtpmap:96 PCM/16000
  a=rtpmap:99 telephone-event/8000
  a=fmtp:99 0-15
  a=sendrecv
  a=rtpmap:103 H264/90000
  a=sendonly

17:55:43 Out 192.168.1.112.43269 > 192.168.1.108.5060: ACK sip:DOORBELL@192.168.1.108:5060 SIP/2.0
17:55:43 Out 192.168.1.112.43269 > 192.168.1.108.5060: BYE sip:DOORBELL@192.168.1.108:5060 SIP/2.0
  <-- HA hangs up immediately after ACK; call never streams audio

3. Button-call routing

  • Pressing the door button also emits Dahua-proprietary MESSAGE requests with alarm JSON (e.g. "SenseMethod": "DoorMagnetism"), which HA answers with 405 Method Not Allowed.
  • The button's voice INVITE targets the Dahua "management centre" number, not a normal phonebook contact.
  • Routing the button call to a TCP-registered softphone yields 480 Temporarily Unavailable with X-Voip-Stack-Decline-Reason: transport_unreachable, because the VTO leg is UDP and the softphone registered over TCP.
INVITE sip:102@192.168.1.112 SIP/2.0     (from VTO, UDP)
-> SIP/2.0 480 Temporarily Unavailable
   Reason: X-Voip-Stack;cause=480;text="transport_unreachable"
   X-Voip-Stack-Decline-Reason: transport_unreachable

Question: is cross-transport bridging (UDP caller -> TCP-registered callee) expected to work through HA, or must both legs share a transport?

tcpdump — Dahua MESSAGE (alarm JSON) + UDP INVITE to TCP-registered softphone -> 480
# Dahua-proprietary MESSAGE on button/event -> 405
In  192.168.1.108.5060 > 192.168.1.112.5060: MESSAGE sip:100@192.168.1.112:5060 SIP/2.0
  Content-Type: json/aplication
  { "Alarm": { "Channel": 5, "RoomNumber": "DOORBELL", "SenseMethod": "DoorMagnetism" } }
Out 192.168.1.112.5060 > 192.168.1.108.5060: SIP/2.0 405 Method Not Allowed

# VTO (UDP) INVITEs softphone registered over TCP -> transport_unreachable
In  192.168.1.108.5060 > 192.168.1.112.5060: INVITE sip:102@192.168.1.112:5060 SIP/2.0
  From: <sip:DOORBELL@192.168.1.112>;tag=...
  To:   <sip:102@192.168.1.112:5060>
Out 192.168.1.112.5060 > 192.168.1.108.5060: SIP/2.0 480 Temporarily Unavailable
  Reason: X-Voip-Stack;cause=480;text="transport_unreachable"
  X-Voip-Stack-Decline-Reason: transport_unreachable

# the softphone in question is registered over TCP:
In  192.168.1.160.58266 > 192.168.1.112.5060: REGISTER sip:192.168.1.112:5060 SIP/2.0
  Via: SIP/2.0/TCP 192.168.1.160:58266;alias;...
  From: "phone" <sip:phone@192.168.1.112>;tag=...
Out SIP/2.0 200 OK

Notes

  • Registration only became stable-ish once From/Contact identity and the Authorization username were both aligned to the same value (100). Earlier the VTO put its device number (8001) in From/Contact while sending a different Authorization username, which never authenticated.
  • I can attach full tcpdump captures for registration (the 401/200 flap) and for the call (INVITE -> 200 OK -> BYE) on request.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions