<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Salamtalk</title>
    <description>The latest articles on DEV Community by Salamtalk (@salamtalkteam).</description>
    <link>https://dev.to/salamtalkteam</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4213600%2Fb54e721a-a3a5-4fc5-987a-f30f2a4443ff.png</url>
      <title>DEV Community: Salamtalk</title>
      <link>https://dev.to/salamtalkteam</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/salamtalkteam"/>
    <language>en</language>
    <item>
      <title>How SIP Trunking Actually Works: A Developer's Guide</title>
      <dc:creator>Salamtalk</dc:creator>
      <pubDate>Wed, 28 Oct 2026 17:41:30 +0000</pubDate>
      <link>https://dev.to/salamtalkteam/how-sip-trunking-actually-works-a-developers-guide-3j25</link>
      <guid>https://dev.to/salamtalkteam/how-sip-trunking-actually-works-a-developers-guide-3j25</guid>
      <description>&lt;p&gt;If you've ever wired a phone system into an app, you've probably run into the term &lt;strong&gt;SIP trunk&lt;/strong&gt; and wondered what's really happening under the hood. This guide walks through it from a developer's point of view: what a trunk is, how a call flows, and the gotchas that bite people in production.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a SIP trunk?
&lt;/h2&gt;

&lt;p&gt;A SIP trunk is a virtual connection between your phone system (a PBX, a softswitch, or your own app) and a carrier that connects you to the public phone network (PSTN).&lt;/p&gt;

&lt;p&gt;Instead of physical copper lines, you get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Signalling&lt;/strong&gt; over SIP (Session Initiation Protocol), usually on UDP/TCP 5060 or TLS 5061&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Media&lt;/strong&gt; (the actual audio) over RTP, on a range of UDP ports&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Phone numbers (DIDs)&lt;/strong&gt; routed to your system by the carrier&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One trunk can carry many simultaneous calls. You're limited by your contract's channel count and your bandwidth, not by how many wires you have.&lt;/p&gt;

&lt;h2&gt;
  
  
  The life of an outbound call
&lt;/h2&gt;

&lt;p&gt;Here's a simplified flow when your PBX places a call through a trunk:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PBX                        Carrier
 |  INVITE (+15551234567)  -&amp;gt;  |
 |  &amp;lt;- 407 Proxy Auth Required |
 |  INVITE (with credentials) -&amp;gt;|
 |  &amp;lt;- 100 Trying              |
 |  &amp;lt;- 180 Ringing             |
 |  &amp;lt;- 200 OK (SDP answer)     |
 |  ACK -&amp;gt;                     |
 |  ======= RTP audio ======== |
 |  BYE -&amp;gt;                     |
 |  &amp;lt;- 200 OK                  |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few things worth knowing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The 407 is normal.&lt;/strong&gt; Most carriers challenge the first INVITE with digest authentication. Your SIP stack answers with a hashed response, and the call proceeds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SDP is where media is negotiated.&lt;/strong&gt; The INVITE carries an SDP offer (the IP, port and codecs you can receive on), and the 200 OK carries the carrier's answer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Post-dial delay (PDD)&lt;/strong&gt; is the time from INVITE to the first 180/183. It's the "dead air" the caller hears before ringing, and it's the first metric to watch when quality complaints come in.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Authentication: registration vs. IP-based
&lt;/h2&gt;

&lt;p&gt;Carriers usually support one of two models:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Registration-based:&lt;/strong&gt; your PBX sends a &lt;code&gt;REGISTER&lt;/code&gt; with a username and password every few minutes, like a desk phone does. It's easy to set up and works behind dynamic IPs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IP-based (static):&lt;/strong&gt; the carrier whitelists your public IP, so no registration is needed. It's better for high-volume or multi-server setups, but you need a stable IP.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you run several servers behind a load balancer, IP-based auth with an SBC (session border controller) in front is usually the cleaner design.&lt;/p&gt;

&lt;h2&gt;
  
  
  The NAT problem (and why one-way audio happens)
&lt;/h2&gt;

&lt;p&gt;The most common SIP bug isn't in SIP at all. It's &lt;strong&gt;NAT&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;SIP messages contain IP addresses &lt;em&gt;inside the payload&lt;/em&gt; (in the &lt;code&gt;Contact&lt;/code&gt; header and the SDP). If your server sits behind NAT and advertises its private IP (&lt;code&gt;10.0.0.5&lt;/code&gt;), the carrier will happily send audio to an address it can't reach. The result is a call that connects but where only one side can hear.&lt;/p&gt;

&lt;p&gt;Fixes, in order of preference:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Configure your PBX's &lt;strong&gt;external/public address&lt;/strong&gt; setting so it rewrites SIP and SDP with the public IP&lt;/li&gt;
&lt;li&gt;Put an &lt;strong&gt;SBC&lt;/strong&gt; at the edge that handles NAT traversal for you&lt;/li&gt;
&lt;li&gt;Make sure your &lt;strong&gt;RTP port range&lt;/strong&gt; (e.g. 10000–20000/UDP) is open and forwarded&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Codecs: keep it simple
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;G.711 (PCMU/PCMA):&lt;/strong&gt; uncompressed, ~87 kbps per call with overhead. It's universally supported and the safest default for trunks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;G.729:&lt;/strong&gt; compressed, ~31 kbps. It saves bandwidth but sometimes needs licensing, and quality drops a little.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Opus:&lt;/strong&gt; great quality and adaptive, but many PSTN carriers don't support it on the trunk side.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A good rule is to use Opus between your app and your users, and G.711 between your PBX and the carrier. Let the PBX transcode if needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Capacity planning
&lt;/h2&gt;

&lt;p&gt;A rough formula for bandwidth:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;concurrent_calls × per_call_bandwidth × 1.2 (headroom)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So 50 concurrent G.711 calls needs about 50 × 87 kbps × 1.2 ≈ &lt;strong&gt;5.2 Mbps&lt;/strong&gt; symmetric.&lt;/p&gt;

&lt;p&gt;Don't forget the non-bandwidth limits too:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CPS (calls per second):&lt;/strong&gt; carriers often cap this, and bursts get rejected with &lt;code&gt;503&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Channel limit:&lt;/strong&gt; exceeding your purchased channels also returns &lt;code&gt;503&lt;/code&gt; or &lt;code&gt;486&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;File descriptors:&lt;/strong&gt; each call with media needs sockets. On Linux the default &lt;code&gt;ulimit -n 1024&lt;/code&gt; can become your real ceiling long before CPU does.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Failover and redundancy
&lt;/h2&gt;

&lt;p&gt;Production trunks should never be a single point of failure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;DNS SRV records&lt;/strong&gt; so your PBX can fail over between carrier endpoints automatically&lt;/li&gt;
&lt;li&gt;Configure a &lt;strong&gt;secondary trunk&lt;/strong&gt; (ideally a different carrier) with routing rules that retry on &lt;code&gt;503&lt;/code&gt;/timeout&lt;/li&gt;
&lt;li&gt;Send &lt;strong&gt;SIP OPTIONS pings&lt;/strong&gt; to detect a dead trunk before customers do&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Security checklist
&lt;/h2&gt;

&lt;p&gt;SIP endpoints exposed to the internet get scanned constantly. At minimum:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;TLS (5061) + SRTP&lt;/strong&gt; where your carrier supports it&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;strong, unique credentials&lt;/strong&gt;, never extension-number-as-password&lt;/li&gt;
&lt;li&gt;Run &lt;strong&gt;fail2ban&lt;/strong&gt; or equivalent on SIP auth failures&lt;/li&gt;
&lt;li&gt;Set &lt;strong&gt;geo/destination restrictions&lt;/strong&gt; on outbound calling to block toll fraud to premium international numbers&lt;/li&gt;
&lt;li&gt;Set &lt;strong&gt;spending limits&lt;/strong&gt; with your carrier&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;SIP trunking isn't magic. It's signalling plus RTP plus a carrier on the other end. Most production issues come down to NAT, capacity limits or missing failover, not the protocol itself.&lt;/p&gt;

&lt;p&gt;If you'd rather not run the carrier side yourself, managed providers handle routing, failover and number porting for you. We work on this at &lt;a href="https://www.salamtalk.com" rel="noopener noreferrer"&gt;Salamtalk&lt;/a&gt;, where we run &lt;a href="https://www.salamtalk.com/sip-trunking" rel="noopener noreferrer"&gt;SIP trunking&lt;/a&gt; and cloud PBX infrastructure for growing teams. Happy to answer questions in the comments.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;What's the weirdest SIP bug you've debugged? One-way audio stories welcome.&lt;/em&gt; 👇&lt;/p&gt;

</description>
      <category>voip</category>
      <category>networking</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
