This post is a bit different, but I think some people will find it very interesting. What got me to write this was an interesting article posted by Kevin Mitnick via his twitter account: Kevin’s claim is that “Any 15-year-old that knows how to write a simple script can find a VoIP provider that spoofs caller ID and set this up in about 30 minutes”, and my only question is: what will you do with the other 25 minutes?

Spoofing your Caller ID is legal in the US only if done via VOIP services for legal and legitimate uses, or to block sending your caller ID, but again, only if it is used for legal purposes. An example of a legitimate use is spoofing your own home/cell phone number when making outbound calls via VOIP/SIP. Another example would be spoofing an outgoing number (a bit like NATing) when sitting at a private (let’s say for example 2,3,4, or 5 digit) extension. There are many scenarios where this is absolutely needed — like offices, enterprises, remote employees/road warriors, and phone support.
Spoofing your Caller ID is not legal for false identity, threatening/harassing someone, pranking, lying, or other such negative and immoral actions. If you are interested in some more information, you can find some here:, and here: This said, I am providing this information for anyone who wants to learn about how this is done, or/and is interested in setting it up for their business or personal use, but ONLY for legal and legitimate uses. I am in no way responsible if you do something stupid or illegal. Here is a good background/history and more information on Caller ID Spoofing:

The assumption here is that you have some things already setup and working. The article is titled “Spoofing Caller ID on the fly from any phone” and not “how to spoof your Caller ID”. I am assuming that you have: a sip trunk provider with an outgoing plan, a DID, a SIP server with some advanced features (Asterisk and OpenPBX, or something like TrixBox), and most of all — a working setup. The first step is getting DISA (Direct Inward System Access – The idea is that you will dial your DID phone number, and the sip trunk provider will route it to your IP address. From there, your server will handle the call and connect you inside your system. I absolutely suggest setting up a DISA password/passcode, otherwise, you leave yourself open to abuse and other people will be able to potentially make calls and use your sip account. It is also important to note that generally, you can simply set a from name and number right here in the DISA outbound options. But again, the idea is to make this dynamic. Ones you dial into your system, the next step is to setup an extension that will handle the rest of this. Leave your context “from-internal” if you want to be able to make external calls by default — necessary in order to bridge the active call to your destination. If you are using Asterisk or TrixBox, go to /etc/asterisk/extensions_custom.conf, and enter something like this:

Now here’s what’s happening: When you get your DID, you get the DISA context. From there, after you authenticate yourself with a pin and now you are in your system. At this point, you would hook in your custom context, in this case called “proof-of-concept-custom”. Make sure that the word “custom” is present somewhere. At this point, your recipe will be executed. The first thing you want to do is answer. You can look up each of these commands at the website. For example, Answer: The next step is to wait 2 seconds. Then you will speak out the current caller ID. This is really just so you know where you are coming from – it is not neccessary. The play (mp3/wav/etc…) play is not really necessary either, but it can be used to queue up different actions. If you will play something, the suggestion is to Answer the channel before hand, and pause/wait for a bit. The next step is to read 10 digits into the “digito” variable. For good measure, and to prevent a mistake, you can speak out the digits again, and then set them as the current Caller ID (the spoofing part). At this point, you can play another sound to queue up the next action. As an extra precaution/security-by-obscurity step, you can prompt for another pin. In this case, it’s “98765”. After the pin has been successfully entered, you can signal via a sound, and then dial and bridge the call to the same number that you set as your Caller ID (impractical, but just for the purpose of a proof of concept). You can very easily modify this to ask for a destination number and call that destination number instead. Please note that this will charge you a twice from the point that you dial the call and bridge it — once for the current/already active call, and once for the new call that you are making to your destination.

Again, there are many legitimate and absolutely necessary cases for this. If you work in any company, most of the time they will not disclose private numbers. If the company is very large, they might simply not have/want to buy individual “routable” phone numbers. Your desk extension of “1234” can be masked behind a general number which routes to “directory/support” when called back. Another great case is someone who works from remote. Say that you work from home and are part of a support group. A customer calls you and reports a problem. Now you want to call the customer back, but you don’t want him to have your personal home number/cellphone – you can spoof your support number and call the customer back.

Something interesting to note is that VOIP/SIP system can choose to not respect Caller ID (cid) blocking/spoofing, and and 1-800/other TOLL-FREE numbers simply do not respect it.

The only point of this article is to demonstrate how easy it is to achieve this dynamically. Again, this is something that you can very easily set statically in the extension or DISA settings. This is not something new or mind blowing. You could have done this over 10 years ago. The point is that you can have a setup which can be activated from any phone and within 30 seconds or less, you can have a dynamically spoofed Caller ID number.

9 Thoughts on “Spoofing Caller ID on the fly from any phone for legal and legitimate purposes

  1. Old post, but wondering if I understood this correctly: We already use DISA on our PBX, but need a way to be able to set the DISA outbound CID during the call. We simply have too many DID’s to setup in DISA, and would rather just have one DISA that we can dial into, and then set our outbound CID while in the DISA extension. Is this possible? Like, we’d dial ext 12345, enter an optional pin number, and then the system asks us for our CID (lets say 800-555-1234) and then would give us a dialtone to dial outbound. After we dial our destination number, our call would be connected with the 800-555-1234 CID. Any insight?

  2. Hi – that scenario is exactly what the example demonstrates.

    See the code snippet: “proof-of-concept-custom” in the post.

    This part specifically:

    The example uses the input numbers both to set the caller ID, and to dial out to that number — thus you would call that number from itself essentially.

    Essentially asks you to punch in a # which is then used directly as the caller ID.

  3. Pinellas Computers on August 29, 2016 at 3:25 pm said:

    Interesting. I did copy/paste that code into our extensions_custom.conf file, but no joy. After I type in the phone number after being prompted (line 7) I just get the call dropped? I don’t imagine this is any conflict with Elastix instead of just Asterisk? My code (I eliminated the playback of my extension):

    exten => 12345,1,Answer
    exten => 12345,n,Wait(2)
    exten => 12345,n,Playback(privacy-prompt)
    exten => 12345,n(collect),Read(digito,,10)
    exten => 12345,n,SayDigits($digito})
    exten => 12345,n,Set(CALLERID(number)=1${digito})
    exten => 12345,n,Answer
    exten => 12345,n,Wait(2)
    exten => 12345,n,Playback(custom/would-you-like-to-connect,skip)
    exten => 12345,n(collect),Read(digito,,5)
    exten => 12345,n,GotoIf($[${digito}==98765]?call:hangup)=
    exten => 12345,n(end),Hangup()
    exten => 12345,n(call),Answer
    exten => 12345,n,Wait(2)
    exten => 12345,n,Playback(activated,skip)
    exten => 12345,n,Dial(SIP/Provider/${CALLERID(number)},300)

    After I enter in the phone number it asks for, there is about a 10 second pause, and then it drops to nothing. It doesn’t prompt for a pin number or anything. Could it be due to a custom recording we don’t have, or the ,300 part on the last line?

    I can’t see what else is wrong. Please advise?

  4. So you get to:

    But not anything after that? That is, you never get to:

    Have you tried hitting # after you enter the 10 digits?

    I haven’t done any sip related work in quite some time, so I don’t have a test environment for it anymore, but if you have a dummy/testing VM (possibly restrict outbound to one number/etc), I can take a look.

  5. That is correct. I don’t get anything for feedback/announce after entering the 10 digit number in. It’s almost like it’s waiting for another response and then times out. Tried to continue pressing numbers and it still drops 10 seconds later.

    If you don’t want to pollute your post with replies, you can also email me at the address I use to post this. Thanks!

  6. I setup a test environment just to go through this, and because I wanted to do it quickly, I went with a standalone Asterisk setup under docker. After getting the signaling/calling to work, I didn’t pay much attention to the audio (RTC). In the process, I noticed that because it’s on the same system, there were RTC issues due to the way the ports get proxied/NATed to docker. My guess is that you are running into something similar potentially (probably via your firewall/NAT setup).

    Here’s how to debug it:

    1.) Start asterisk
    2.) Connect to it via the client with a larger debug level — ex: “asterisk -r -vvvvvvvv”
    3.) Dial your local extension (in this case, 12345) and take a look at what happens.

    Here’s my example with a failing RTC channel:

    In this case I am using my SIP client with extension 100, and dialing 12345

    I modified the extension to Answer, and then wait for 10 digits, but because the RTC channel is not NATing properly, the digits never make it there:

    Anyway, this should allow you to see what is happening in you case.

  7. Just verified – that’s exactly what was causing it in my test case. After adding the proper NAT settings in sip.conf (localnet for the private bridge net in my case, externaddr, nat=comedia, and media_address), the digits are now picked up from a sip client. (still no audio back, but again, that’s because of the weird double-NAT/proxy I am doing through my system)

    Check your side — my guess is that this is what’s happening.

    I got a tiny typo, specifically, a missing brace for SayDigits, so I updated that in the blog post to:

    Wanted to mention just in case you have that missing too.

  8. Hi Ventz,

    We’re actually not NAT’ed at all. Our system is on a public IP with IPTables locking down ports 80 and 443 to only 2 of our private IPs. So NAT definitely isn’t our problem. Looks like an issue with the recordings, but not sure why that drops completely.

    I did identify these issues:
    1. Playback of (custom/would-you-like-to-connect,skip) fails. I don’t have that recording? In any case, I just deleted that line an it continues fine. But still fails in the end (see
    2. Playback of exten => 12345,n(collect),Read(digito,,5) fails. Again, I was able to bypass this by knowing when to dial 98765, but this would be good to hear announcing the prompt for the passcode. And, it still fails after (see

    Any insight on how to get the passcode prompt to actually announce, and what is making it fail even after entering that?

    Thanks, really close!

  9. Interesting.
    I am definitely up for spending some time on this if you are — I am genuinely curious at this point.

    ps: just saw your comment about emailing you – I’ll send you an email directly.

    For the time being, try:
    “rtp set debug on”
    “sip set debug on”

    and take a look at the logs.

Leave a Reply

Your email address will not be published. Required fields are marked *

Post Navigation