Extension (SIP) Caller ID verification

Sorry for the first post. I tried to search for this topic, but I couldn’t really find what I am looking for.

I inherited a rather large asterisk 1.8 deployment with MySQL back end. It works extremely well for handling our call traffic, voicemails, etc. I am now facing a challenge where I need to validate that the Caller ID that is set by the SIP end points are valid for that end point. My criteria is below:

ext 1-234-555-1234 calls outbound number, call is checked if Caller ID is set to 234-555-1234. If it is set to that, then it passes the call on to the outbound trunk. If it is set to “private”, then it passes to the outbound trunk. If it is set to anything else, it is either overwritten with “234-555-1234” or the call is dropped.

This may be as simple as checking the SIP headers, and making sure that either the privacy flag is set, or that the number contained in the from header is the same as in the P-Asserted-Identity header, however I don’t know if the P-Asserted-Identity header can be trusted from the authenticated SIP devices, or if it even exists?

Any thoughts?

This is what I have so far, and it is working for my very limited test of an SP122 that I have configured against my asterisk server, but I’m concerned that this would not work in all situations, if the Caller ID is not set to “anonymous”.

exten => _[2-9]XXXXXXXXX,2,GotoIf($[${CALLERID(number)} = ${CHANNEL:4:10}]?5)

exten => _[2-9]XXXXXXXXX,3,GotoIf($["${CALLERID(number)}" = "anonymous"]?5)

exten => _[2-9]XXXXXXXXX,4,set(CALLERID(number)=${CHANNEL:4:10})

exten => _[2-9]XXXXXXXXX,5,"Dial Out"

Any better suggestions?

If you follow best security practice, this test will always fail, as the peer name will not be the caller ID. Also the way that chan_sip channel IDs are constructed has changed over the years, so it is not a stable way of determining the sip peer.

The safest approach would be to set a variable to the expected caller ID in the peer definition for the device. However, if you ignore the guidance about making device names non-guessable ,there is an option of the CHANNEL function, which I believe did exist in your obsolete version, to get the SIP peer name.

Also, I believe your version does support P-Asserted-ID as a source of caller ID and privacy information, without needing to explicitly parse the headers.

Generally one would use n for the priorities in the exten lines, and use labels for the Goto targets. I think 1.8 supports “same =>” instead of repeating the extension pattern on every line.

Thanks for the advice.

P-Asserted-ID is not set by the end points, at least not in my environment. It is set by the Asterisk gateway. I won’t have access to that where I need it.

Perhaps a better way to do this will be to take a database dip, and look a the number associated with the channel. The SQL query is simple to formulate, however I’m a little unsure how to make the query and assign it to the variable in order to evaluate the number in the dial plan.

Maybe something like:

exten => _X.,1,set(calleridentifier=${CALLERID(number)})
exten => _X.,2,MYSQL(Connect connid localhost dbuser dbpass dbname)
exten => _X.,3,MYSQL(Query resultid ${connid} SELECT [query string where value=${calleridentifier}])
exten => _X.,4,MYSQL(Fetch fetchid ${resultid} queryresult)
exten => _X.,5,GotoIf($[${CALLERID(number)} = ${queryresult}]?8)
exten => _X.,6,GotoIf($["${CALLERID(number)}" = "anonymous"]?8)
exten => _X.,7,set(CALLERID(number)=${CHANNEL:4:10})
exten => _X.,8,"Dial Out"

We already get the sipusers, sippeers, voicemail, and extensions out of MySQL, so perhaps there would be a simpler way and we don’t need to reconnect to the database each time.

Looks like we are using “realtime” in our deployment, and I’m not quite sure how to do a multi-variable filter in “where” using realtime, especially one combining two different tables. Possibly I could do this with a customer view in MySQL… My solution will just be to use realtime twice, then compare a variable that should be identical value in each query. If it is identical, then the caller ID is a number assigned to the same account as the channel, and asterisk server should honor the caller ID.

exten => _X.,1,set(calleridentifier=${CALLERID(number)})
exten => _X.,2,realtime(sipusers|name|${CHANNEL:4:10}|sipusers_)
exten => _X.,3,realtime(extensions|exten|${CALLERID(num)}|internal_)
exten => _X.,4,gotoif($[$["${internal_bitsid}"="${sipusers_accountcode}"] & [${LEN(${internal_bitsid})}>1]]?8)
exten => _X.,6,GotoIf($["${CALLERID(number)}" = "anonymous"]?8)
exten => _X.,7,set(CALLERID(number)=${CHANNEL:4:10})
exten => _X.,8,"Dial Out"

I haven’t tested this yet, but will do so now.

Any thoughts? Is this a better solution, or an I missing something easier?

Please, at least, use ${CHANNEL(peername)}, rather than ${CHANNEL:4:10}. Whilst neither is ideal, for reasons already given, the former is easier for others to understand and is not dependent on implementation details that can and have changed.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.