Field notes

Field note: the desk phone that could call out but never rang

A SIP phone showed Registered and placed calls fine, but incoming calls never reached it. The firewall was quietly forgetting the phone's NAT session after 40 seconds.

One desk phone at a small government office had a strange problem. It showed Registered, it could place calls, and nobody else’s phone was affected. But calls to it, both direct calls and calls from a queue, never rang.

The phone was registered to a hosted PBX out on the internet, through the office firewall’s hide NAT (many inside devices sharing the firewall’s one public address).

What it looked like

  • The phone’s status page said Registered.
  • Outbound calls worked every time.
  • Inbound calls to that phone never rang, whether dialed directly or sent from a queue.

“Registered” plus working outbound calls tells you the phone can reach the PBX. It doesn’t tell you the PBX can reach the phone. The phone registers by sending a request out, and the firewall builds a NAT session for it so the replies can find their way back. When the PBX later wants to ring the phone, it sends a new request to the address and port it saw at registration time. That only works if the firewall still has the session.

How it was found

The clue was in the firewall’s security log. The PBX’s SIP packets were showing up there as Accepted by an allow rule, as brand-new connections to the firewall’s own public IP.

That looks harmless at first glance, but it’s the whole story. A packet that matched the phone’s existing NAT session would have been translated and passed through to the phone as part of that session. It wouldn’t show up as a fresh hit on an allow rule. These packets were landing on the gateway itself, with no session to tell the firewall which inside device they were meant for, so they went nowhere.

The log also showed a pattern: bursts of the same packet repeated about every 4 seconds for about 30 seconds, roughly once a minute. That’s what SIP over UDP does when a request gets no answer. It resends, backing off until the gap reaches 4 seconds, and gives up after 32 seconds. The PBX was trying to reach the phone, again and again, and every attempt hit a dead end.

The cause

The firewall’s built-in SIP over UDP service object had a 40-second session timeout, and aggressive aging was turned on for it with a 15-second timeout. So whenever the phone went quiet for a bit between re-registrations, the firewall dropped its NAT session. The phone didn’t know anything had changed, so it kept saying Registered. The next inbound call from the PBX arrived to a session that no longer existed.

For comparison, the IETF’s NAT behavior guidance says a UDP mapping shouldn’t expire in less than two minutes, and recommends five minutes or more. Forty seconds is well under either.

The fix

On the SIP UDP service object’s Advanced tab:

  1. Raised the session timeout from 40 to 3600 seconds.
  2. Turned off aggressive aging, for that service only.

I left the firewall’s global UDP timeout alone. Raising it for everything would keep every idle UDP session (DNS lookups and the rest) around far longer than needed, just to fix one protocol.

There was also a phone-side option I kept in my pocket: set a NAT keepalive of about 20 seconds and a shorter registration expiry (about 120 seconds), so the phone itself keeps the session fresh. That’s a reasonable fallback when you can’t change the firewall. It wasn’t needed here.

How it turned out

Since the timeout change, there haven’t been any more complaints about missed calls on that phone. That’s not a formal test result, just the absence of the problem it was reported for, which for a phone that never rang is a pretty good sign.

What I took away from it

  • An allow rule is not a port forward. Inbound traffic that doesn’t match an existing NAT session just lands on the firewall. “Accepted” in the log doesn’t mean it reached anything.
  • “Registered”, outbound fine, inbound silent points at NAT state. Look at session timeouts before you start rebuilding the phone’s config.
  • Change timeouts per service, not globally. Fix the one protocol that needs a long-lived session and leave the rest alone.
  • The firewall log shows the retransmit pattern. Repeated bursts from the PBX to your public IP, every few seconds for about 30 seconds, mean it’s knocking on a door that’s no longer there.

If you’re also chasing dropped calls rather than missing ones, the Switchvox field note covers a different SIP failure, where calls cut off at exactly 32 seconds. And if your phone system is the one sitting on the internet, see locking down an exposed PBX.

Sources

  • RFC 4787: NAT behavioral requirements for unicast UDP (REQ-5): a NAT UDP mapping timer must not expire in less than two minutes, and five minutes or more is recommended
  • RFC 3261: SIP (17.1.2.2): over UDP, a non-INVITE request is retransmitted starting at T1 (500 ms), doubling up to T2 (4 s), until Timer F gives up at 64×T1 (32 s)

All articles