Tag Archives: voip

Snom VoIP phones: OpenVPN and multicast audio

Snom voice-over-IP phones have a built-in OpenVPN client, and they can also have audio transmitted to them via multicast. However, in my case a phone logged into OpenVPN did not play back audio received from the local ethernet network

I had multicast reception configured correctly on the phone:

multicast_listen=on
mc_address=239.255.255.245:5555

(Remember that you need to push the Apply button at the bottom of the page and then the Save button at the top of the page for the setting to actually take effect.)

To diagnose the problem, you can use multicast pings. Running

ping -I eth0 -t 2 239.255.255.245

on the local network showed no reactions from the phone. However, running

ping -I tun2 -t 2 239.255.255.245

on the VPN server showed responses from the phone. So clearly the phone wanted to do multicast exclusively via VPN. The cause of this was the following line in my OpenVPN config on the server:

push "redirect-gateway def1"

The obvious solution was to replace this line with routes that excluded the multicast IP addresses:

push "route 0.0.0.0 128.0.0.0"
push "route 128.0.0.0 192.0.0.0"
push "route 192.0.0.0 224.0.0.0"

While this worked, the phone wouldn’t complete booting up the next time I power-cycled it. So I switched back to the old OpenVPN config and instead turned on multicast routing on the VPN server:

apt-get install smcroute
echo 'mgroup from eth0 group 239.255.255.245' >> /etc/smcroute.conf
echo 'mroute from eth0 group 239.255.255.245 to tun0 tun1 tun2' >> /etc/smcroute.conf
service smcroute restart

Multicast audio now works and it even goes across the VPN.

Below you can find some commands that use FFMPEG to send the multicast audio:

ffmpeg -re -i song.mp3 -filter_complex 'aresample=16000,asetnsamples=n=160' -acodec g722 -ac 1 -vn -f rtp udp://239.255.255.245:5555
ffmpeg -re -i song.mp3 -filter_complex 'aresample=8000,asetnsamples=n=160' -acodec pcm_mulaw -ac 1 -vn -f rtp udp://239.255.255.245:5555
ffmpeg -re -i song.mp3 -filter_complex 'aresample=8000,asetnsamples=n=160' -acodec pcm_alaw -ac 1 -vn -f rtp udp://239.255.255.245:5555

Interestingly, you don’t even need to set the rtp_codec_type setting — the phone automatically determines the codec from the stream. I wasn’t able to get the Opus codec working though, the phone just makes crackling noises when I tried.

Asterisk 11 und Sipgate Basic

Für ältere Asterisk-Versionen hat Sipgate in seinen FAQs passende Einträge für die sip.conf aufgeführt. Unter Asterisk 11 hat sich leider die NAT-Behandlung etwas verändert (nat=yes gibt es nicht mehr), deswegen hier meine funktionierende Konfiguration (SIPID durch die Kundennummer und SIPPWD durch das SIP-Passwort ersetzen):

[sipgate-SIPID]
type=friend
insecure=invite
nat=force_rport
username=SIPID
fromuser=SIPID
fromdomain=sipgate.de
secret=SIPPWD
host=sipgate.de
qualify=yes
canreinvite=no
dtmfmode=rfc2833
context=sipgate-in
callbackextension=SIPID
outboundproxy=sipgate.de
trustrpid=yes
sendrpid=no

In der [global]-Section habe ich außerdem

disallow=all
allow=g722
allow=alaw
allow=ulaw

Erläuterungen zu den Einstellungen, die potentiell problematisch sind:

  • nat: wenn hier was anderes steht, werden eingehende Anrufe nicht immer signalisiert. Unter Asterisk 1.8 und früher ging nat=yes.
  • qualify: sendet regelmäßig SIP-Pakete, um in der NAT-Tabelle des Routers zu bleiben. Wenn das nicht aktiviert ist,w erden eingehende Anrufe nicht immer signalisiert.
  • canreinvite: muss deaktiviert sein, weil sonst der UDP-Port für RTP nach der Anrufannahme noch geändert werden kann. Der Router hat den Port dann nicht in seiner NAT-Tabelle und verwirft die Pakete, dementsprechend wird kein Ton übertragen.
  • callbackextension: hiermit spart man sich eine Zeile wie register => SIPID:SIPPWD@sipgate.de/SIPID in der [global]-Sektion. Wichtig: die lokale Extension (das ist der Wert von callbackextension bzw. der nach dem Schrägstrich in der register-Zeile) muss unbedingt gleich der SIPID sein. Wenn er das nicht ist, wird der erste eingehende Anruf nach einer Wartezeit von ca. 30 Minuten oder mehr zwar signalisiert, aber der Anrufer bekommt auch nach dem Annehmen weiterhin das Freizeichen (ein iPhone im Vodafone-Netz zeigte bei mir nach einige Sekunden nach dem Annehmen dann “Anruf fehlgeschlagen” an) und der Angerufene bekommt keinen Ton. Ich hatte ursprünglich nur register => SIPID:SIPPWD@sipgate.de (entspricht callbackextension=s), was auch ging — nur andere Zahlen, z.B. die eigene Telefonnummer, verursachen das Problem.
  • trustrpid: Bei Sipgate-internen Anrufen steht bei eingehenden Anrufen im From-Feld des SIP-Headers nicht immer die Nummer des Anrufers, sondern z.B. dessen Kundennummer. In dem Fall wird die korrekte Nummer im Feld P-Asserted-Identity mitgesendet und mit dieser Option wird sie später ins From-Feld kopiert.
  • sendrpid: Falls man im Dialplan die CONNECTEDLINE-Funktion benutzt, um bei ausgehenden Anrufen Text im Display des Telefons anzuzeigen (und dafür in [global] den Wert sendrpid=pai gesetzt hat), sollte man es für Sipgate hier deaktivieren.

Mit der obigen Konfiguration landen eingehende Sipgate-Anrufe im Dialplan unter SIPID@sipgate-in. Ausgehende Anrufe bekommt man im Dialplan mit

[outgoing]
exten => _0049X.,1,Goto(0${EXTEN:4},1)
exten => _+49X.,1,Goto(0${EXTEN:3},1)
exten => _+XXX.,1,Goto(00${EXTEN:1},1)
exten => _XXX.,1,Set(CALLERID(number)=SIPID)
same => n,Set(CALLERID(name)=49123456789)
same => n,Dial(SIP/${EXTEN}@sipgate-SIPID,,rWT)

wobei 49123456789 die gewünschte Absenderrufnummer ist, wenn im Sipgate-Account bei Absenderrufnummer “setzt das Endgerät” ausgewählt ist. Für die Standardnummer kann man diese Zeile auch weglassen.

Eingehende Anrufe gehen so (angenommen, man hat ein internes SIP-Endgerät mit der Nummer 20 angelegt):

[sipgate-in]
exten => SIPID,1,Dial(SIP/20)

Asterisk: Change number in To header

A long time ago, I wrote about changing the callee ID as seen by the caller using CONNECTEDLINE.
Changing the caller ID as seen by the callee is also pretty obvious using CALLERID.
That leaves two more constellations: changing the caller ID as seen by the caller (which doesn’t make sense because a phone typically doesn’t display its own number on outgoing calls)., and changing the callee ID as seen by the callee, which I’ll talk about here now.

The reason you might want to do this is because you have multiple PSTN phone numbers that ring the same SIP phone. The obvious way to solve this would be to use

exten => _X.,n,SipAddHeader(To: "123456" <sip:123456@server>)
exten => _X.,n,Dial(SIP/${EXTEN})

, but that doesn’t work because SipAddHeader doesn’t overwrite existing headers, it only adds new ones. The Snom forum mentions a hack using the Diversion header, assuming your phone does indeed display that. A much nicer way is the following:

exten => _X.,n,Dial(SIP/${EXTEN}!123456)

. The number after the exclamation mark is simply what Asterisk uses as the local part when it composes the To URI. This features is not well-documented, but from the code I guess it was introduced in Asterisk 1.6. Asterisk 1.8’s (and higher) chan_sip.c gives a short explanation:

 *  SIP Dial string syntax:
 *       SIP/devicename
 *  or   SIP/username@domain (SIP uri)
 * or   SIP/username[:password[:md5secret[:authname[:transport]]]]@host[:port]
 * or   SIP/devicename/extension
 *  or   SIP/devicename/extension/IPorHost
 * or   SIP/username@domain//IPorHost
 * and there is an optional [!dnid] argument you can append to alter the
 *  To: header.

Asterisk: Change Callee-ID using CONNECTEDLINE

It’s easy to change your Caller ID (assuming your phone provider doesn’t filter it) in Asterisk using something like Set(CALLERID(name)=blah). This is often used to choose which number to use for an outgoing call if you have multiple on a single SIP or ISDN trunk.

But did you know it’s just as easy to change the Callee ID on an outgoing call, i.e. change what your phone displays during the call? This can be very useful to display on the phone which one of several possible outgoing lines (multiple SIP providers, ISDN, …) was used or at which point in an IVR menu you are at the moment. To do this, use Set(CONNECTEDLINE(name)=blah). Before getting started, set sendrpid = pai in your sip.conf.

To make things easier, I created two macros in my dialplan:

[macro-connectedline-name-number]
exten => s,1,Set(CONNECTEDLINE(name,i)=${ARG1})
exten => s,n,Set(CONNECTEDLINE(number,i)=${ARG2})
exten => s,n,Set(CONNECTEDLINE(pres)=allowed)

[macro-connectedline-name]
exten => s,1,Macro(connectedline-name-number,${ARG1}, ${MACRO_EXTEN})

Now I can do things like

[internal-test]
exten => 101,1,Answer()
exten => 101,n,Macro(connectedline-name,Hello World)
exten => 101,n,Playback(hello-world)
exten => 101,n,Hangup()

in my dialplan (IVR example).

Or how about

[outgoing]
exten => 100,1,Macro(connectedline-name,Mailbox)
exten => 100,n,VoiceMailMain(${CALLERID(num)},s)
exten => _XXX.,n,Macro(connectedline-name,VoIP 1)
exten => _XXX.,n,Dial(SIP/${EXTEN}@voipprovider)

(outgoing line example).

The Asterisk Wiki also has an entire page on Manipulating Party ID Information.