Home   Blog   Evan Doorbell Tapes   Projects   Docs   Mirror

BulkVS SIP Trunks on a Cisco ISR using IP Authentication

My go-to SIP trunk provider these days for US domestic calling is BulkVS. As with most over-the-top SIP trunk providers, no one is perfect. However, I have found that they generally have decent routes, and pricing is pretty good at $0.004/min outbound, $0.0003 inbound (not a typo), and most DIDs around $0.06/month (pricing as of 2026-01-17).

Here are some rough instructions on how to get going using a Cisco ISR. As with anything, your specific environment may vary, but hopefully this helps others with getting started.

BulkVS Inbound

In your BulkVS account, create a trunk group.

  1. Go to Interconnection and choose Trunk Group - Manage
  2. Click Create under IP Authenticated Trunk Group
  3. Set the name and description of the trunk group to whatever you desire
  4. Set the Primary IP as the public IP your ISR will be sourcing from
  5. Leave Secondary IP blank
  6. Set Max Calls In (from PSTN) to whatever you feel is a reasonable value (I typically default to 23 to pretend it's a PRI)
  7. Leave Verstat Header and Identity Header as is
  8. Set Digit Delivery to 10DIGITS. This dictates the format BulkVS sends your DIDs for inbound calls.
  9. Save Changes

BulkVS Outbound

In your BulkVS account, we need to add the public IP the ISR is sourcing from as an allowed host.

  1. Go to Interconnection and choose Hosts
  2. Under Add IP Host click Create
  3. Enter the public IP address the ISR is sourcing from, an appropriate description, and whatever reasonable amount of channels you want to allow. Similarly to the inbound trunk group, I like to pretend it's a PRI and usually set this to 23.
  4. Click Create

Configuring the ISR

Since we're using IP auth, most of what you need is appropriate outbound and inbound dial-peers. If your ISR is behind NAT, there's a bit of extra config which I will include as well.

NOTE: BulkVS, like most SIP trunk providers these days, will reject any calls that do not have a properly formatted calling number. It does not have to be a BulkVS DID and can be any 10 or 11 digit number. If you choose, you can use a translation-profile to control this. However, I handle this at another layer so it is not covered here.

If your ISR is behind NAT, you need to configure your public IP as a /32 on a loopback interface. I am using Loopback99 in this example, but it can be any Loopback interface number of your choosing. This is so we can tell it to rewrite the source IP in the SIP header. You will also want to make sure you forward UDP 5060 (SIP signaling) and UDP 10000-65535 (RTP media, yes this excssive but I have found at times to be necessary as you cannot predict what port a media gateway will choose for RTP, and RTP is not guaranteed to use symmetrical ports). If your ISR is not behind NAT, this is not necessary.

interface Loopback99
 ip address 1.1.1.1 255.255.255.255
 
voice service voip
 sip
  bind all source-interface Loopback99

Inbound example:

voice translation-rule 3945
 rule 1 /^.+/ /3945/
voice translation-profile DID-TO-DN-XLATE
 translate called 3945
 
dial-peer voice 2489945 voip
 description BULKVS DID EXAMPLE
 translation-profile incoming DID-TO-DN-XLATE
 signaling forward none
 incoming called-number 5555551212
 codec g711ulaw bytes 80
 no vad

In the case above, calls inbound destined to 555-555-1212 will be sent to DN 3945

Outbound example:

voice translation-profile STRIP-FIRST-TWO
 translate called 199
 
voice translation-rule 199
 rule 1 /^../ //
 
dial-peer voice 78001 voip
 description BULKVS TRUNK
 translation-profile outgoing STRIP-FIRST-TWO
 preference 1
 destination-pattern 781..........
 signaling forward none
 session protocol sipv2
 session target ipv4:162.249.171.198
 codec g711ulaw bytes 80
 no vad
 
dial-peer voice 78002 voip
 description BULKVS TRUNK
 translation-profile outgoing STRIP-FIRST-TWO
 preference 2
 destination-pattern 781..........
 signaling forward none
 session protocol sipv2
 session target ipv4:23.190.16.198
 codec g711ulaw bytes 80
 no vad
 
dial-peer voice 78003 voip
 description BULKVS TRUNK
 translation-profile outgoing STRIP-FIRST-TWO
 preference 3
 destination-pattern 781..........
 signaling forward none
 session protocol sipv2
 session target ipv4:76.8.29.198
 codec g711ulaw bytes 80
 no vad

BulkVS has 3 SBC's and we want to make sure that if one is unreachable we fail over to the next. I have these ordered by latency (lowest to highest). I'm not sure how much this matters, but it also doesn't hurt. Also in my set up, I have assigned trunk code "78" to BulkVS which the outgoing translation-profile strips.