Hallo Freunde,
vor ein paar Tagen wollte ich mein Cisco 8961 endlich nach langer Zeit mit meiner Fritzbox verbinden. Zwar hat die grundlegende Funktion (Registrierung und Telefonate an der Fritzbox) funktioniert, jedoch bin ich ziemlich schnell ich auf das Problem mit der Uhrzeit bei Firmware >= 9.1 gestoßen (vergleiche https://tools.cisco.com/bugsearch/bug/CSCul33490). Also habe ich erstmal die 9.0 versucht, jedoch konnte sich das Telefon hierbei nicht an der Fritzbox registrieren (die Uhrzeit war jedoch tatsächlich korrekt). Das Problem ist, dass NTP von >= 9.1 einfach nicht mehr unterstützt wird und stattdessen die Uhrzeit im Header der SIP-Antworten der Fritzbox erwartet wird. Dies ist auch in diversen anderen Threads hier im Forum beschrieben.
Da ich mich ohnehin nicht wirklich mit der alten Firmware-Version abfinden wollte, habe ich mir eine Lösung überlegt, um das Problem zu beheben. Da ich weder die Fritzbox Firmware, noch die Cisco Firmware verändern kann, musste eine Alternative her. Wie bereits geschrieben erwartet das Telefon die Uhrzeit im SIP-Header. Also ist eine naheliegende Lösung diesen dementsprechend zu manipulieren.
Da ich viele hilfreiche Informationen aus diesem Forum bezogen habe, möchte ich mein Vorgehen gerne mit euch teilen. Jedoch wird das Ganze sehr technisch. Wer keine Erfahrung mit Linux und Routing hat, sollte an dieser Stelle vielleicht aufhören zu lesen - auf der anderen Seite, wer ein Cisco Telefon an einer Fritzbox betreibt, wird sicherlich auch das hier hinbekommen
Zuerst benötigen wir einen Linux-Rechner, der für uns die Pakete manipuliert. Ich verwende dazu einen Raspberry Pi mit Raspbian, prinzipiell sollte aber auch jede andere Hardware/Distribution taugen.
Als erstes müssen wir die Routing-Funktionalität des Kernels aktivieren. Dazu muss in /etc/sysctl.conf folgende Zeile ergänzt werden:
Danach noch
ausführen, um die Änderungen zu aktivieren.
Bevor es auf dem Linux Rechner weitergeht, müssen wir das Routing für das Telefon verändert. Für das Telefon funktioniert das je nach DHCP Server z.B. so:
dnsmasq:
dhcpd:
Falls ihr die Fritzbox als DHCP Server verwendet bleibt euch nur den Router manuel im Telefon zu konfigurieren, aber das habt ihr wahrscheinlich ohnehin schon, da ihr auch den TFTP Server manuel einrichten musstet.
Nun müsst ihr noch in eurem Router eine spezifische Route für euer Telefon über den Linux Rechner einrichten, also z.B. so:
192.168.x.z via 192.168.x.y
Ich selbst verwende die Fritzbox nicht als Router, daher kann ich nicht mit Gewissheit sagen, ob das funktioniert. Die Konfiguration dafür findet ihr aber unter Heimnetz -> Heimnetzübersicht -> Netzwerkeinstellungen -> IPv4 Routen.
Wenn ihr das alles geschafft habt sollte sich das Telefon weiterhin registrieren. Um das zu überprüfen oder auch um einen Fehler zu finden, können wir nun auf dem Linux Rechner
ausführen. Wichtig ist, dass wir Pakete in beide Richtungen sehen (wobei wir nur die eine Richtung manipulieren müssen, aber asymmetrisches Routing ist Mist und verursacht nur Probleme...). Das Ganze sollte in etwa so aussehen:
Die Pakete sehr ihr möglicherweise doppelt. Das liegt daran, dass die Pakete einmal reinkommen und einmal rausgesendet werden.
So, nun haben wir also erfolgreich den Traffic über unseren Linux-Rechner umgeleitet. Jetzt geht es ans Manipulieren. Zuerst müssen wir ein paar Pakete nachinstallieren:
Als nächstes legt ihr euch eine Datei sip-date.pl an. Ich habe das unter /opt/scripts gemacht, aber da könnt ihr natürlich variieren. Inhalt:
Außerdem brauchen wir noch eine Datei sip-date.sh mit folgendem Inhalt:
Die zweite Datei kann man verwenden, um das Script als Service zu starten. Wie das geht findet man leicht über Google heraus.
Die beiden Scripte jetzt noch per
ausführbar machen und dann kann es losgehen.
An dieser Stelle sei noch gesagt, dass es natürlich hilfreich ist, wenn der Linux Rechner auch die richtige Uhrzeit hat, also am Besten vorher noch NTP konfigurieren ;-)
In einem Terminal startet ihr jetzt
und in einem anderen führt ihr diesen Befehl aus:
wobei x.f die Fritzbox und x.z das Telefon.
Über
könnt ihr sehen, ob die Regel aktiv ist und ob Pakete von der Regel erfasst werden. Denkt daran, dass iptables Regeln nach einem Neustart weg sind. Ich verwende iptables-persistent (Google), um die Regeln nach einem Neustart automatisch wiederherzustellen.
Wenn alles richtig eingerichtet ist, solltet ihr nun im Perl-Script Pakete ankommen sehen. Außerdem kann man mit obigen tcpdump Befehl ebenfalls die manipulierten Pakete sehen, die sehen jetzt z.B. so aus:
Wie ihr seht, wird jetzt die Uhrzeit in das Paket eingefügt. Ggf. noch das Telefon einmal durchbooten, dann sollte die Uhrzeit auch dort aktuel sein.
So, das war's. Ich hoffe ich konnte dem einen oder anderen helfen.
Viele Grüße
vor ein paar Tagen wollte ich mein Cisco 8961 endlich nach langer Zeit mit meiner Fritzbox verbinden. Zwar hat die grundlegende Funktion (Registrierung und Telefonate an der Fritzbox) funktioniert, jedoch bin ich ziemlich schnell ich auf das Problem mit der Uhrzeit bei Firmware >= 9.1 gestoßen (vergleiche https://tools.cisco.com/bugsearch/bug/CSCul33490). Also habe ich erstmal die 9.0 versucht, jedoch konnte sich das Telefon hierbei nicht an der Fritzbox registrieren (die Uhrzeit war jedoch tatsächlich korrekt). Das Problem ist, dass NTP von >= 9.1 einfach nicht mehr unterstützt wird und stattdessen die Uhrzeit im Header der SIP-Antworten der Fritzbox erwartet wird. Dies ist auch in diversen anderen Threads hier im Forum beschrieben.
Da ich mich ohnehin nicht wirklich mit der alten Firmware-Version abfinden wollte, habe ich mir eine Lösung überlegt, um das Problem zu beheben. Da ich weder die Fritzbox Firmware, noch die Cisco Firmware verändern kann, musste eine Alternative her. Wie bereits geschrieben erwartet das Telefon die Uhrzeit im SIP-Header. Also ist eine naheliegende Lösung diesen dementsprechend zu manipulieren.
Da ich viele hilfreiche Informationen aus diesem Forum bezogen habe, möchte ich mein Vorgehen gerne mit euch teilen. Jedoch wird das Ganze sehr technisch. Wer keine Erfahrung mit Linux und Routing hat, sollte an dieser Stelle vielleicht aufhören zu lesen - auf der anderen Seite, wer ein Cisco Telefon an einer Fritzbox betreibt, wird sicherlich auch das hier hinbekommen
Zuerst benötigen wir einen Linux-Rechner, der für uns die Pakete manipuliert. Ich verwende dazu einen Raspberry Pi mit Raspbian, prinzipiell sollte aber auch jede andere Hardware/Distribution taugen.
Als erstes müssen wir die Routing-Funktionalität des Kernels aktivieren. Dazu muss in /etc/sysctl.conf folgende Zeile ergänzt werden:
Code:
net.ipv4.ip_forward=1
Danach noch
Code:
sysctl -p
Bevor es auf dem Linux Rechner weitergeht, müssen wir das Routing für das Telefon verändert. Für das Telefon funktioniert das je nach DHCP Server z.B. so:
dnsmasq:
Code:
[...]
dhcp-option=pirouter,option:router,192.168.x.y # IP des Linux Rechners
dhcp-option=vendor:Cisco,150,192.168.x.t # IP eures TFTPs
dhcp-host=00:11:22:33:44:55,192.168.x.z,set:pirouter # MAC und IP des Telefons
[...]
dhcpd:
Code:
[...]
option cisco-tftp code 150 = array of ip-address;
shared-network LAN1 {
[...]
subnet 192.168.x.0 netmask 255.255.255.0 { # euer Subnetz
[...]
option cisco-tftp 192.168.x.t; # IP eures TFTPs
option routers 192.168.x.1; # Euer default Router
host phone.tld { # FQDN des Telefons
fixed-address 192.168.x.z; # IP des Telefons
hardware ethernet 00:11:22:33:44:55; # MAC des Telefons
option routers 192.168.x.y; # IP des Linux Rechners
}
[...]
}
}
Falls ihr die Fritzbox als DHCP Server verwendet bleibt euch nur den Router manuel im Telefon zu konfigurieren, aber das habt ihr wahrscheinlich ohnehin schon, da ihr auch den TFTP Server manuel einrichten musstet.
Nun müsst ihr noch in eurem Router eine spezifische Route für euer Telefon über den Linux Rechner einrichten, also z.B. so:
192.168.x.z via 192.168.x.y
Ich selbst verwende die Fritzbox nicht als Router, daher kann ich nicht mit Gewissheit sagen, ob das funktioniert. Die Konfiguration dafür findet ihr aber unter Heimnetz -> Heimnetzübersicht -> Netzwerkeinstellungen -> IPv4 Routen.
Wenn ihr das alles geschafft habt sollte sich das Telefon weiterhin registrieren. Um das zu überprüfen oder auch um einen Fehler zu finden, können wir nun auf dem Linux Rechner
Code:
tcpdump -v udp port 5060
Code:
phone.tld.sip > fritzbox.tld.sip: SIP, length: 997
REGISTER sip:192.168.x.f SIP/2.0 # IP der Fritzbox
[...]
fritzbox.tld.sip > phone.tld.sip: SIP, length: 813
SIP/2.0 200 OK
[...]
Die Pakete sehr ihr möglicherweise doppelt. Das liegt daran, dass die Pakete einmal reinkommen und einmal rausgesendet werden.
So, nun haben wir also erfolgreich den Traffic über unseren Linux-Rechner umgeleitet. Jetzt geht es ans Manipulieren. Zuerst müssen wir ein paar Pakete nachinstallieren:
Code:
apt-get install nfqueue-bindings-perl libnetpacket-perl
Als nächstes legt ihr euch eine Datei sip-date.pl an. Ich habe das unter /opt/scripts gemacht, aber da könnt ihr natürlich variieren. Inhalt:
Code:
#!/usr/bin/perl
#
# see http://search.cpan.org/~atrak/NetPacket-0.04/
#use strict;
BEGIN {
push @INC,"perl";
push @INC,"build/perl";
push @INC,"NetPacket-0.04";
};
use nfqueue;
use NetPacket::IP qw(IP_PROTO_UDP);
use NetPacket::UDP;
use Socket qw(AF_INET AF_INET6);
use POSIX qw(strftime);
my $q;
sub cleanup()
{
print "unbind\n";
$q->unbind(AF_INET);
print "close\n";
$q->close();
}
sub cb()
{
my ($dummy,$payload) = @_;
print "Perl callback called!\n";
print "dummy is $dummy\n" if $dummy;
if ($payload) {
print "len: " . $payload->get_length() . "\n";
my $ip_obj = NetPacket::IP->decode($payload->get_data());
print $ip_obj, "\n";
print("$ip_obj->{src_ip} => $ip_obj->{dest_ip} $ip_obj->{proto}\n");
print "Id: " . $payload->swig_id_get() . "\n";
if($ip_obj->{proto} == IP_PROTO_UDP) {
# decode the UDP header
my $udp_obj = NetPacket::UDP->decode($ip_obj->{data});
print "UDP src_port: $udp_obj->{src_port}\n";
print "UDP dst_port: $udp_obj->{dest_port}\n";
print "UDP flags : $udp_obj->{flags}\n";
print "UDP data : $udp_obj->{data}\n";
#if ($udp_obj->{flags} & NetPacket::UDP::PSH &&
# length($udp_obj->{data})) {
# print "data is defined\n";
# #$udp_obj->{data} = 'gruik';
# $udp_obj->{data} =~ s/love/hate/m;
# print "**********\n";
# print $udp_obj->{data};
# print "**********\n";
#}
$datestring = strftime "%a, %d %b %Y %H:%M:%S GMT", gmtime;
$udp_obj->{data} =~ s!SIP/2.0 200 OK!SIP/2.0 200 OK\r\nDate: $datestring!g;
print "UDP data new: $udp_obj->{data}\n";
# try modifying the packet
#$ip_obj->{src_ip} = "1.2.3.4";
#$udp_obj->{src_port} = 42;
#$ip_obj->{dest_ip} = "213.186.33.19";
$udp_obj->{cksum} = 0;
$ip_obj->{cksum} = 0;
$ip_obj->{data} = $udp_obj->encode($ip_obj);
my $modified_payload = $ip_obj->encode();
my $ip2 = NetPacket::IP->decode($modified_payload);
print("$ip2->{src_ip} => $ip2->{dest_ip} $ip2->{proto}\n");
my $udp2 = NetPacket::UDP->decode($ip2->{data});
print "UDP src_port: $udp2->{src_port}\n";
print "UDP dst_port: $udp2->{dest_port}\n";
print "data length: ", length($modified_payload), "\n";
my $ret = $payload->set_verdict_modified($nfqueue::NF_ACCEPT,$modified_payload,length($modified_payload));
print "ret: $ret\n";
return;
}
$payload->set_verdict($nfqueue::NF_ACCEPT);
return;
}
$payload->set_verdict($nfqueue::NF_ACCEPT);
}
$q = new nfqueue::queue();
print "open\n";
$q->open();
print "bind\n";
$q->bind(AF_INET);
$SIG{INT} = "cleanup";
#print "set callback, wrong argument type (should fail)\n";
#$q->set_callback("blah");
print "setting callback\n";
$q->set_callback(\&cb);
print "creating queue\n";
$q->create_queue(0);
print "trying to run\n";
$q->try_run();
Außerdem brauchen wir noch eine Datei sip-date.sh mit folgendem Inhalt:
Code:
#!/bin/bash
PIDFILE="/var/run/sip-date.pid";
/usr/bin/perl /opt/scripts/sip-date.pl 2>&1 > /dev/null &
echo $! > $PIDFILE;
exit 0;
Die zweite Datei kann man verwenden, um das Script als Service zu starten. Wie das geht findet man leicht über Google heraus.
Die beiden Scripte jetzt noch per
Code:
chmod +x sip-date.*
An dieser Stelle sei noch gesagt, dass es natürlich hilfreich ist, wenn der Linux Rechner auch die richtige Uhrzeit hat, also am Besten vorher noch NTP konfigurieren ;-)
In einem Terminal startet ihr jetzt
Code:
./sip-date.pl
Code:
iptables -A FORWARD -s 192.168.x.f/32 -d 192.168.x.z/32 -p udp -m udp --sport 5060 --dport 5060 -j NFQUEUE --queue-num 0
Über
Code:
iptables -vnxL
Wenn alles richtig eingerichtet ist, solltet ihr nun im Perl-Script Pakete ankommen sehen. Außerdem kann man mit obigen tcpdump Befehl ebenfalls die manipulierten Pakete sehen, die sehen jetzt z.B. so aus:
Code:
fritzbox.tld.sip > phone.tld.sip: SIP, length: 850
SIP/2.0 200 OK
Date: Sat, 10 Dec 2016 11:38:38 GMT
[...]
Wie ihr seht, wird jetzt die Uhrzeit in das Paket eingefügt. Ggf. noch das Telefon einmal durchbooten, dann sollte die Uhrzeit auch dort aktuel sein.
So, das war's. Ich hoffe ich konnte dem einen oder anderen helfen.
Viele Grüße
Zuletzt bearbeitet: