FrickelfabrikAnmelden
Server & Netzwerk7 min Lesezeit

Kein Ton beim Telefonieren – einseitige Sprache bei SIP finden und beheben

Der Anruf kommt zustande, aber einer hört nichts. Fast immer steckt NAT dahinter. Wie man in drei Schritten herausfindet, wohin die Sprache wirklich geht, und welche Einstellung in Asterisk das Problem löst – mit echten Ausgaben aus einem Testlabor.

Es klingelt, man nimmt ab, die Anzeige läuft – und man hört nichts. Oder nur der eine hört den anderen. Wer mit VoIP zu tun hat, kennt das. Es ist der Klassiker unter den Telefonie-Störungen, und die gute Nachricht ist: Die Ursache ist fast immer dieselbe.

In diesem Tutorial stelle ich das Problem in einem kleinen Labor nach: eine Asterisk-Telefonanlage „im Internet“ und ein Telefon dahinter, hinter einem ganz normalen Router mit NAT, wie zu Hause. Ich zeige, wie man den Fehler mit Bordmitteln von Asterisk findet, und welche Einstellung ihn behebt. Alle Ausgaben in diesem Beitrag sind echt.

Warum der Anruf klappt, die Sprache aber nicht

Ein VoIP-Telefonat besteht aus zwei getrennten Dingen:

  • SIP baut den Anruf auf und ab: Wer ruft wen an, wer nimmt ab, wer legt auf.
  • RTP transportiert die Sprache, in kleinen Paketen, 50 pro Sekunde und Richtung.

Die beiden nehmen unterschiedliche Wege. Beim Anrufaufbau schreibt jede Seite in den SIP-Nachrichten auf, wohin die andere Seite die Sprache schicken soll. Das steht im sogenannten SDP-Teil, in der Zeile c= (die Adresse) und m=audio (der Port).

Und hier liegt das Problem. Ein Telefon hinter einem Router kennt nur seine eigene, private Adresse, etwa 192.168.178.20. Genau die schreibt es in den SDP-Teil. Für die Gegenseite im Internet ist diese Adresse wertlos: 192.168.178.20 gibt es in Millionen Haushalten, und keine davon ist von außen erreichbar.

Die Folge: SIP kommt durch, weil die Antworten einfach an die Adresse zurückgehen, von der die Anfrage kam. Die Sprache aber schickt die Gegenseite brav an 192.168.178.20 – und dort kommt sie nie an.

Das Labor

Damit man sieht, was passiert, habe ich das nachgebaut:

Telefon (baresip)          Router mit NAT              Asterisk 20
192.168.178.20   ──────►   192.168.178.1 │ 172.31.0.2  ──────►  172.31.0.10
   Heimnetz                         „Internet“

Das Telefon ruft die Nebenstelle 600 an. Dort läuft ein Echo: Asterisk schickt alles zurück, was es hört. Hört das Telefon sein Echo, funktioniert die Sprache in beide Richtungen.

Die Nebenstelle ist ganz schlicht eingerichtet, die NAT-Einstellungen sind zunächst alle aus:

[1001]
type=endpoint
context=lab
disallow=all
allow=alaw
auth=1001
aors=1001
direct_media=no
rtp_symmetric=no
rewrite_contact=no
force_rport=no

Schritt 1: Den SIP-Verkehr ansehen

Auf der Asterisk-Konsole (asterisk -rvvv) schaltet man die Protokollierung der SIP-Nachrichten ein:

pjsip set logger on

Dann den Testanruf machen. Im Protokoll steht die Einladung des Telefons, das INVITE. Das Wichtigste daran, gekürzt:

<--- Received SIP request (796 bytes) from UDP:172.31.0.2:5060 --->
INVITE sip:600@172.31.0.10 SIP/2.0
Via: SIP/2.0/UDP 192.168.178.20:5060;branch=z9hG4bKa6ae11110d7ed7d8;rport
Contact: <sip:1001-0x55afe93e7c80@192.168.178.20:5060>
...
c=IN IP4 192.168.178.20
m=audio 20028 RTP/AVP 8 101

Hier sieht man das Problem schon, wenn man weiß, wonach man sucht:

  • Die erste Zeile sagt: Das Paket kam von 172.31.0.2. Das ist die Adresse des Routers.
  • Im SDP steht aber c=IN IP4 192.168.178.20. Das ist die private Adresse des Telefons.

Zwei verschiedene Adressen für dasselbe Telefon: Das ist das Erkennungszeichen für NAT.

Merksatz: Steht in c= eine private Adresse (10.x, 172.16.x bis 172.31.x, 192.168.x), die Nachricht kam aber von einer anderen Adresse, dann sitzt das Gerät hinter NAT. Ob das zum Problem wird, hängt von der Einstellung der Gegenseite ab.

Schritt 2: Der Sprache folgen

Jetzt wird es konkret. Asterisk kann jedes einzelne Sprachpaket protokollieren:

rtp set debug on

Bei vielen gleichzeitigen Gesprächen lieber nur für eine Adresse: rtp set debug ip 172.31.0.2.

Beim Testanruf erscheinen dann pro Sekunde 100 solcher Zeilen:

Got  RTP packet from    172.31.0.2:20000 (type 08, seq 009738, ts 061896, len 000160)
Sent RTP packet to      192.168.178.20:20000 (type 08, seq 008921, ts 061896, len -000013)

Diese beiden Zeilen erzählen die ganze Geschichte:

  • Got … from 172.31.0.2: Die Sprache des Telefons kommt bei Asterisk an, über den Router. Diese Richtung funktioniert.
  • Sent … to 192.168.178.20: Asterisk schickt seine Sprache an die private Adresse aus dem SDP. Die gibt es im Internet nicht.

Aus dem Labor: Bei mir steht bei den gesendeten Paketen sogar eine negative Länge (len -000013), weil es im Labor überhaupt keinen Weg zu dieser Adresse gibt und schon das Senden scheitert. Im echten Internet sieht die Zeile ganz normal aus. Die Pakete verschwinden erst unterwegs. Darauf also nicht verlassen.

Schritt 3: Gegenprobe beim Telefon

Zur Sicherheit habe ich am Router mitgezählt, was beim Telefon ankommt. Ein Mitschnitt mit tcpdump über die zehn Sekunden des Anrufs:

Pakete
vom Telefon gesendet454
beim Telefon angekommen0

Das Telefon spricht, hört aber nichts. Einseitige Sprache, wie im Lehrbuch.

Die Lösung: rtp_symmetric

Die Idee dahinter heißt symmetrisches RTP: Statt der Adresse aus dem SDP zu glauben, schickt Asterisk die Sprache dorthin zurück, woher die Sprache des Telefons kommt. Der Router hat für genau diese Verbindung eine Tür offen, also kommt die Antwort durch.

In Asterisk ist das eine Zeile in der Nebenstelle:

rtp_symmetric=yes

Danach sieht dasselbe Protokoll so aus:

Got  RTP packet from    172.31.0.2:20012 (type 08, seq 008077, ts 062036, len 000160)
Sent RTP packet to      172.31.0.2:20012 (type 08, seq 055541, ts 062032, len 000160)

Asterisk sendet jetzt an den Router, und zwar an genau den Port, von dem die Sprache kam. Beim Telefon kommen 447 Pakete an. Das Echo ist zu hören.

Und die anderen NAT-Einstellungen?

Ich habe im Labor jede Einstellung einzeln ausprobiert. Für die Sprache reicht rtp_symmetric=yes allein. Die anderen beiden braucht man trotzdem, aber für etwas anderes:

  • rewrite_contact=yes: Meldet sich das Telefon an, speichert Asterisk sonst die private Adresse aus der Contact-Zeile. Eingehende Anrufe gehen dann an 192.168.178.20 und kommen nie an. Im Labor sah das so aus:

    rewrite_contact=no:   Contact: sip:1001-…@192.168.178.20:5060
    rewrite_contact=yes:  Contact: sip:1001-…@172.31.0.2:5060
    

    Ohne die Einstellung klingelte das Telefon bei einem Anruf von Asterisk nicht. Mit ihr wurde der Anruf angenommen.

  • force_rport=yes: Asterisk antwortet auf SIP-Nachrichten an Adresse und Port, von denen sie kamen, statt an die Angaben in der Via-Zeile.

  • direct_media=no: Sonst versucht Asterisk, zwei Telefone die Sprache direkt austauschen zu lassen, an sich selbst vorbei. Hinter verschiedenen Routern kann das nicht klappen.

Für Telefone, die von außen über das Internet angebunden sind, also Homeoffice, Handy-App, Telefon beim Kunden, gehören alle vier in die Nebenstelle:

direct_media=no
rtp_symmetric=yes
rewrite_contact=yes
force_rport=yes

Der umgekehrte Fall: Asterisk steht selbst hinter NAT

Bisher saß das Telefon hinter dem Router. Genauso oft steht die Telefonanlage hinter einem Router, etwa auf einem Raspberry Pi zu Hause, und spricht mit einem SIP-Anbieter im Internet. Dann schreibt Asterisk seine eigene private Adresse in den SDP-Teil, und der Anbieter schickt die Sprache ins Leere.

Das Erkennungszeichen ist dasselbe, nur gespiegelt: Im INVITE, das Asterisk verschickt, steht in c= die private Adresse der Anlage.

Die Lösung sitzt hier nicht in der Nebenstelle, sondern im Transport. Asterisk muss wissen, unter welcher Adresse es von außen erreichbar ist und welche Netze „innen“ sind:

[transport-udp]
type=transport
protocol=udp
bind=0.0.0.0:5060
external_media_address=203.0.113.10
external_signaling_address=203.0.113.10
local_net=192.168.178.0/24

203.0.113.10 steht hier für die öffentliche IP des Anschlusses. Dazu gehört eine Portweiterleitung im Router: der SIP-Port und der ganze RTP-Bereich aus rtp.conf (Standard: 10000 bis 20000) an die Anlage.

Der heimliche Störenfried: SIP-ALG

Manche Router versuchen zu helfen. Eine Funktion namens SIP-ALG (Application Layer Gateway) schreibt SIP-Nachrichten unterwegs um und ersetzt private Adressen durch die öffentliche. Klingt gut, macht aber oft mehr kaputt als heil: Sie schreibt halbe Nachrichten um, verträgt sich nicht mit den Einstellungen oben oder bricht bei verschlüsseltem SIP ganz.

Ein typisches Zeichen: Die Adressen im Mitschnitt vor dem Router und nach dem Router passen nicht zueinander, obwohl niemand etwas eingestellt hat. Wenn die Fehlersuche keinen Sinn ergibt, im Router nach „SIP-ALG“, „SIP Helper“ oder „SIP Passthrough“ suchen und es testweise abschalten.

Kurz und knapp

SymptomWahrscheinliche UrsacheWo nachsehen
Ich höre den anderen nichtAsterisk sendet an eine private Adressertp set debug on: Wohin geht „Sent“?
Der andere hört mich nichtMeine Sprache kommt nicht anrtp set debug on: Gibt es „Got“-Zeilen?
Gespräch bricht nach etwa 32 Sekunden abdie Bestätigung (ACK) auf das 200 OK kommt nicht an, oft auch NATpjsip set logger on: Kommt das ACK?
Telefon klingelt bei eingehenden Anrufen nichtprivate Contact-Adresse gespeichertpjsip show contacts
Alles wirkt chaotisch, Adressen passen nichtSIP-ALG im RouterRouter-Einstellungen

Und die vier Zeilen für Telefone hinter NAT, zum Mitnehmen:

direct_media=no
rtp_symmetric=yes
rewrite_contact=yes
force_rport=yes

Weiterlesen

#Telefonie#SIP#Asterisk#Fehlersuche#Tutorial

Du bekommst eine Mail zum Bestätigen. Abmelden geht jederzeit. Datenschutz

Kommentare

Kommentar schreiben

Kommentieren geht mit einem kostenlosen Konto. Du meldest dich mit einem Link per E-Mail an, ganz ohne Passwort.

Zum Kommentieren anmelden

Mehr zum Thema