Version: v1.13.17
Summary
When unregistering a SIP gateway with:
sofia profile <profile> unregister <gateway>
FreeSWITCH sends a REGISTER with Expires: 0, receives 407 Proxy Authentication Required with a fresh nonce, but does not send a second authenticated REGISTER Expires: 0.
As a result, the remote registrar keeps the registration active until the registration TTL expires.
This was observed with a SIP registrar that challenges unregister requests with 407 Proxy Authentication Required.
Environment
FreeSWITCH version: 1.10.12-release+git~20240802T210227Z~a88d069d6f~64bit
Module: mod_sofia
Registrar/PBX: 3CX-compatible registrar
Transport: UDP
Profile: external
Gateway: gw_test
Gateway behavior
The gateway is registered successfully. On unregister, FreeSWITCH sends:
REGISTER sip:REDACTED_REGISTRAR_IP:5060;transport=udp SIP/2.0
Via: SIP/2.0/UDP REDACTED_FREESWITCH_IP:5080;rport;branch=z9hG4bK_REDACTED
Max-Forwards: 70
From: <sip:REDACTED_EXTENSION@REDACTED_REGISTRAR_IP>;tag=REDACTED_TAG
To: <sip:REDACTED_EXTENSION@REDACTED_REGISTRAR_IP>
Call-ID: REDACTED_CALL_ID
CSeq: REDACTED_CSEQ REGISTER
Contact: <sip:gw+gw_test@REDACTED_FREESWITCH_IP:5080;transport=udp;gw=gw_test>
Expires: 0
User-Agent: FreeSWITCH-mod_sofia/1.10.12-release+git~20240802T210227Z~a88d069d6f~64bit
Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE, REGISTER, REFER, NOTIFY
Supported: timer, path, replaces
Proxy-Authorization: Digest username="REDACTED_AUTH_USERNAME", realm="REDACTED_REALM", nonce="REDACTED_OLD_NONCE", algorithm=MD5, uri="sip:REDACTED_REGISTRAR_IP:5060;transport=udp", response="REDACTED_DIGEST_RESPONSE"
Content-Length: 0
The registrar responds:
SIP/2.0 407 Proxy Authentication Required
Via: SIP/2.0/UDP REDACTED_FREESWITCH_IP:5080;rport=5080;branch=z9hG4bK_REDACTED
Proxy-Authenticate: Digest nonce="REDACTED_NEW_NONCE",algorithm=MD5,realm="REDACTED_REALM"
To: <sip:REDACTED_EXTENSION@REDACTED_REGISTRAR_IP>;tag=REDACTED_TAG
From: <sip:REDACTED_EXTENSION@REDACTED_REGISTRAR_IP>;tag=REDACTED_TAG
Call-ID: REDACTED_CALL_ID
CSeq: REDACTED_CSEQ REGISTER
Content-Length: 0
After this, FreeSWITCH does not send another REGISTER Expires: 0 using the fresh nonce from the 407.
Actual behavior
FreeSWITCH sends one unregister request:
REGISTER ... Expires: 0
Proxy-Authorization: Digest ... old/cached nonce ...
The registrar replies:
407 Proxy Authentication Required
Proxy-Authenticate: Digest nonce="new_nonce"
FreeSWITCH does not retry with:
REGISTER ... Expires: 0
Proxy-Authorization: Digest ... new_nonce ...
The gateway remains registered on the registrar side until the remote registration timeout expires.
Expected behavior
On receiving 407 Proxy Authentication Required for a gateway unregister transaction, FreeSWITCH should retry the unregister request using the new nonce:
REGISTER ... Expires: 0
407 Proxy Authentication Required
REGISTER ... Expires: 0 + Proxy-Authorization using fresh nonce
200 OK
This is especially important for registrars that always challenge unregister requests, or that reject stale/preemptive digest credentials and issue a new nonce.
Steps to reproduce
-
Configure a Sofia gateway against a registrar that challenges unregister requests with 407 Proxy Authentication Required.
-
Confirm the gateway is registered:
sofia status gateway gw_test
- Enable SIP trace:
sofia profile external siptrace on
- Run:
sofia profile external unregister gw_test
-
Observe that FreeSWITCH sends REGISTER Expires: 0.
-
Observe that the registrar responds with 407 Proxy Authentication Required and a new nonce.
-
Observe that FreeSWITCH does not send the second authenticated REGISTER Expires: 0.
Related command behavior
The same issue is visible when using:
sofia profile external killgw gw_test
In that case, FreeSWITCH attempts to unregister, receives 407, and then deletes the gateway object before a successful authenticated unregister completes.
Observed log:
[NOTICE] sofia_reg.c:141 UN-Registering gw_test
...
SIP/2.0 407 Proxy Authentication Required
...
[NOTICE] sofia_reg.c:342 Deleted gateway gw_test
Gateway config shape
Relevant gateway parameters are approximately:
<gateway name="gw_test">
<param name="username" value="REDACTED_EXTENSION"/>
<param name="auth-username" value="REDACTED_AUTH_USERNAME"/>
<param name="password" value="REDACTED_PASSWORD"/>
<param name="realm" value="REDACTED_REALM"/>
<param name="proxy" value="REDACTED_REGISTRAR_HOST:5060"/>
<param name="register-proxy" value="REDACTED_REGISTRAR_HOST:5060"/>
<param name="from-domain" value="REDACTED_REGISTRAR_HOST"/>
<param name="extension" value="REDACTED_EXTENSION"/>
<param name="register" value="true"/>
<param name="register-transport" value="udp"/>
<param name="expire-seconds" value="60"/>
<param name="retry-seconds" value="10"/>
</gateway>
The issue also occurs when attempting a direct registration style without proxy, using only register-proxy.
Why this matters
Without a successful authenticated unregister, the registrar keeps the contact binding active until timeout. This causes operational issues when dynamically disabling or removing gateways, especially in systems that need to rapidly register/unregister many SIP accounts.
Lowering expire-seconds is only a workaround; it does not make unregister immediate or reliable.
Suggested fix area
The likely area is gateway unregister handling in:
src/mod/endpoints/mod_sofia/sofia_reg.c
FreeSWITCH should keep the gateway/register transaction alive long enough to complete the digest challenge flow for unregister, and should retry the Expires: 0 REGISTER after receiving 401 or 407 with a fresh nonce.
In particular, the expected flow should be:
REGISTER Expires: 0
407 Proxy Authentication Required
REGISTER Expires: 0 with fresh Proxy-Authorization
200 OK
For killgw, it may also be necessary to delay actual gateway deletion until the unregister transaction completes or fails definitively.
Workaround
Set a short registration expiry:
<param name="expire-seconds" value="60"/>
<param name="retry-seconds" value="10"/>
Then treat unregister as best effort:
fs_cli -x "sofia profile external unregister gw_test"
sleep 2
fs_cli -x "sofia profile external killgw gw_test"
However, this does not solve the actual issue when the registrar requires a fresh digest challenge response for unregister.
Version: v1.13.17
Summary
When unregistering a SIP gateway with:
FreeSWITCH sends a
REGISTERwithExpires: 0, receives407 Proxy Authentication Requiredwith a fresh nonce, but does not send a second authenticatedREGISTER Expires: 0.As a result, the remote registrar keeps the registration active until the registration TTL expires.
This was observed with a SIP registrar that challenges unregister requests with
407 Proxy Authentication Required.Environment
Gateway behavior
The gateway is registered successfully. On unregister, FreeSWITCH sends:
The registrar responds:
After this, FreeSWITCH does not send another
REGISTER Expires: 0using the fresh nonce from the407.Actual behavior
FreeSWITCH sends one unregister request:
The registrar replies:
FreeSWITCH does not retry with:
The gateway remains registered on the registrar side until the remote registration timeout expires.
Expected behavior
On receiving
407 Proxy Authentication Requiredfor a gateway unregister transaction, FreeSWITCH should retry the unregister request using the new nonce:This is especially important for registrars that always challenge unregister requests, or that reject stale/preemptive digest credentials and issue a new nonce.
Steps to reproduce
Configure a Sofia gateway against a registrar that challenges unregister requests with
407 Proxy Authentication Required.Confirm the gateway is registered:
Observe that FreeSWITCH sends
REGISTER Expires: 0.Observe that the registrar responds with
407 Proxy Authentication Requiredand a new nonce.Observe that FreeSWITCH does not send the second authenticated
REGISTER Expires: 0.Related command behavior
The same issue is visible when using:
In that case, FreeSWITCH attempts to unregister, receives
407, and then deletes the gateway object before a successful authenticated unregister completes.Observed log:
Gateway config shape
Relevant gateway parameters are approximately:
The issue also occurs when attempting a direct registration style without
proxy, using onlyregister-proxy.Why this matters
Without a successful authenticated unregister, the registrar keeps the contact binding active until timeout. This causes operational issues when dynamically disabling or removing gateways, especially in systems that need to rapidly register/unregister many SIP accounts.
Lowering
expire-secondsis only a workaround; it does not make unregister immediate or reliable.Suggested fix area
The likely area is gateway unregister handling in:
FreeSWITCH should keep the gateway/register transaction alive long enough to complete the digest challenge flow for unregister, and should retry the
Expires: 0REGISTER after receiving401or407with a fresh nonce.In particular, the expected flow should be:
For
killgw, it may also be necessary to delay actual gateway deletion until the unregister transaction completes or fails definitively.Workaround
Set a short registration expiry:
Then treat unregister as best effort:
However, this does not solve the actual issue when the registrar requires a fresh digest challenge response for unregister.