Asterisk auf Raspberry - beim klingeln lokales GPIO schalten

DiddisVilla

Neuer User
Mitglied seit
23 Jul 2022
Beiträge
7
Punkte für Reaktionen
1
Punkte
3
Hallo,
habe Asterisk auf einem Raspi laufen - tut auch. Allerdings würde ich gerne direkt an den Raspi ein Relais hängen (an irgendendeinen) GPIO, das gezogen wird, wenn es klingelt.
Was ich nicht schaffe ist, dass auf dem lokalen Asterisk-Server ein SIP-Client-Event ausgelöst werden soll. Wie werte ich also sowas lokal aus?
Nach einem Tag suchen und versuchen bin ich für jeden Hinweis dankbar.
 
GPIO-Pins lassen sich über /sys/class/gpio steuern (https://www.kernel.org/doc/Documentation/gpio/sysfs.txt), dafür baut man sich am besten passende Shell-Scripts und dann muß man nur noch an den richtigen Stellen im Dialplan (extensions.conf) mit der System-Funktion diese Shell-Skripte aufrufen.
 
Moin


Und wenn du Ausgaben des Shellscripts auch in Asterisk ausgeben/auswerten möchtest, nimm: SHELL()
 
Ausgaben des Shellscripts
Damit das Relais nicht mehrfach "angezogen" wird und damit auch mehrfach wieder abfallen muß? ;)

Aber ohne Spaß ... mir fehlt zugegebenermaßen etwas die Phantasie, was bei der "Bedienung" eines GPIO-Pins (mit direction=out konfiguriert) an Ausgaben anfallen sollte und was man da auswerten wollen würde.

Außer ggf. ein "trigger script", was bei jedem Aufruf das Relais einfach nur umschaltet (also statt on bzw. off) und parallel noch den letzten bzw. neuen Status ausgeben soll. Das halte ich aber angesichts der Bedingung "wenn es klingelt" aus #1 für unwahrscheinlich bzw. eine schlechte Implementierung.
 
schon mal danke für die Tipps - bin weiter - aber...
Habe jetzt ein "18high.sh" geschrieben und das Pin wechselt auch auf 3,3Volt in der bash.
In der cli funktioiert das hier:
!sudo -utim /home/tim/18high.sh
In der extensions.conf:
exten => alle,n,System(! /usr/bin/sudo -utim /home/tim/18high.sh)
geht nicht.:
-- Executing [alle@tfe-zuhause:2] System("Local/alle@tfe-zuhause-00000028;2", "! /usr/bin/sudo -utim /home/tim/18high.sh") in new stack
Aber nix passiert.

@PeterPawn: ich habe ein funktionierende Außenklingel, die schon an einem Relais hängt. Brauche also nur noch ein logischen Hight, damit es klingelt. So jedenfalls der Plan ;-)
 
exten => alle,n,System(! /usr/bin/sudo -utim /home/tim/18high.sh)

Ich riskier jetzt mal ne blöde Frage, weil ich es so zugegeben noch nie gesehen habe:
Warum das Ausrufezeichen hier?

Weiters:
Da du ein sudo auf tim machst, hast Du sichergestellt dass der User unter dem asterisk läuft, dass gemäß der sudo Richtlinien auch (ohne Passswortabfrage) darf?
Ist vielleicht für den ersten Test einfacher, das Script für den asterisk user ausführbar zu machen und ohne sudo aufzurufen. Wenn das dann klappt, kannst Du ja immer noch ein sudo Konzept drüber stülpen.
 
Habe mit und ohne "!" probiert... macht eh keinen Unterschied. War ein tipp im www.

Das mit dem user ist ein guter Hinweis. Ich dachte ich hätte das erledigt, wenn das unter der cli> direkt läuft - was es tut.
 
Letztendlich kommt es darauf an, unter welchem User Dein asterisk läuft (siehe runuser, rungroup in der asterisk.conf) und was dieser User darf und ob (da Du sudo verwendest) gegebenenfalls nötige sudo Regeln für ihn existieren.
Ich würde mal (ausnahmsweise) dem Script chmod 777 geben und es im Dialplan ohne sudo aufrufen. Wenn das klappt, weißt Du dass Du auf dem richtigen Weg bist und kannst die Ausführungssicherheit ja immer noch verfeinern.

Das Rufzeichen braucht es aus meiner Sicht nicht.
 
Wenn die Notwendigkeit besteht, etwas mit sudo aufzurufen (es kann sein, daß der (Schreib-)Zugriff auf /sys/class/gpio Superuser-Rechte braucht), dann ist es am einfachsten, das im Skript (18high.sh) beim jeweiligen Kommando zu machen und die Berechtigungen dafür (ggf. limitiert auf das Skript) in die Datei /etc/sudoers einzutragen (da kann auch der Aufruf mit einem anderen Konto OHNE Kennwort-Eingabe konfiguriert werden), wozu man (neben der passenden Dokumentation: https://linux.die.net/man/5/sudoers) auch ein Kommando verwenden kann, was vor dem Speichern der Änderungen erst eimal eine Gültigkeitsprüfung vornimmt, damit man sich mit falschen Änderungen nicht selbst aus dem System aussperrt: https://linux.die.net/man/8/sudoedit bzw. https://wiki.ubuntuusers.de/sudo/Konfiguration/

PS: Wenn man echo-Kommandos in einem Skript unter Verwendung von sudo per Redirection in Dateien umleiten will (und auch das sysfs besteht aus (Pseudo-)Dateien), dann verwendet man das sudo am besten in der Form sudo bash -c "<command>", wobei in <command> auch die Umleitung der Ausgabe enthalten ist. Ansonsten wirkt eine Redirection nur auf die Standard-Handles des sudo-Kommandos, was eher nicht der Intention entspricht, weil die i.d.R. nicht mit den resultierenden Rechten aus dem sudo-Aufruf geöffnet wurden.
 
Damit das Relais nicht mehrfach "angezogen" wird und damit auch mehrfach wieder abfallen muß? ;)
Damit hat man wenigstens ein Feedback aus dem Script.
( ala: echo "Versuche zu schalten" )
Mit System() kriegt er noch nicht mal eine Fehlerausgabe wenn es nicht klappt.
 
Mit System() kriegt er noch nicht mal eine Fehlerausgabe wenn es nicht klappt.
Mit Shell() sieht er die per se auch erst mal nicht, solange er keine zusätzlichen Schritte in seinen Dialplan einbaut (z.B. ein Verbose()) und anstatt nach STDOUT (was die einzige Ausgabe ist, die man per Shell() kriegt) zu protokollieren, kann/sollte man - wenn tatsächlich Bedarf besteht, was im "Regelbetrieb" sicherlich nicht zwangsläufig der Fall ist - auch in eine Datei schreiben, was man dann nicht beim Aufruf angeben/auswerten muß.

Die Info "erfolgreich" oder "misslungen" kriegt man (wenn das Shell-Skript ordentlich entworfen wurde und seinerseits einen entsprechenden Exit-Code liefert) auch bei Verwendung von System() -die Variable ${SYSTEMSTATUS} sollte einen passenden Wert enthalten, nachdem der Aufruf beendet wurde.
 
Sorry, aber es tut nicht. Inzwischen weiß ich, was das "!" bedeutet:
! – Execute a shell command
Und genau das funktioniert unter "*CLI>:
! /home/tim/18high.sh
Ein anderes Beispiel wäre hier: !whoami - gibt auch ein sauberes Ergebnis.
 
Das stand ja nun schon in #8 - der Aufruf aus dem Dialplan heraus ist eben NICHT identisch mit dem aus dem CLI. Dort steht das Ausrufezeichen eben für den Teil, der im Dialplan bereits durch die Angabe von System(<command>) repräsentiert wird - es macht keinen Sinn, da auch noch das Ausrufezeichen in <command> anzugeben, weil das eben KEIN Shell-Kommando ist, was man ohne weiteres ausführen kann (das kommt nur im Rahmen der Jobsteuerung einer (interaktiven) Shell vor).

Sieh einfach zu, daß der Benutzer, unter dem Dein Asterisk läuft (das kriegst Du mittels Prozessliste heraus), auch Zugriff auf das Skript hat oder kopiere es einfach an einen Ort, wo dieser Zugriff (bekanntermaßen) möglich ist. Dann noch ein paar "Statusmeldungen" in das Skript 18high.sh eingebaut, die in (fest benannte) Dateien schreiben (mit "append" natürlich, also >> für die Redirection verwenden), damit man bei Fehlern INNERHALB des Skripts (das KANN auch das Fehlen entsprechender Schreibrechte im sysfs sein, wenn man das nicht korrekt mit sudo aufruft - für das gesamte Skript würde ICH das zumindest vermeiden) auch noch erkennen kann, woran es liegt.

Wenn Du jetzt bis hierher schon gekommen bist, kann es kaum noch am simplen Aufruf aus dem Dialplan heraus scheitern ... wobei ich mir gar nicht sicher bin, daß ein Aufruf aus dem CLI mittels ! ebenfalls über das Module app_system läuft - wenn das nicht der Fall sein sollte, wäre es ja zumindest noch denkbar, daß Du das Module gar nicht erst geladen hast und daher die Funktion im Dialplan auch nicht zur Verfügung steht.
 
Wenn ich mich nicht irre, hat das Pseudo Dateisystem Standardmäßig die Rechte 0660 root:gpio. Mann muss also entweder dort breitere Rechte vergeben, oder asterisk zumindest in die Gruppe gpio aufnehmen. Sonst nützen die ganzen Ausführ Rechte für das Bash Skript nichts.

sudo -u asterisk echo 1 > /sys/class/gpio/gpio18/value
gibt testweise Aufschluss darüber.

Das Pseudo Filesystem ist übrigens als veraltet zu betrachten, da gibt es bessere Klassen dafür.

Ich würde das direkt mit Python machen, ist auch nicht wirklich schwer.

pigpiod frisst Ressourcen, wenn man die Poll Rate nicht runter setzt. Das ist für den Zweck nicht zu empfehlen.
 
Zuletzt bearbeitet:
sudo -u asterisk echo 1 > /sys/class/gpio/gpio18/value
gibt testweise Aufschluss darüber.
DAS wird so eben nicht funktionieren, weil die Umleitung am Ende NICHT für den Aufruf von echo gilt, sondern für das sudo-Kommando.

Verwendet man hingegen sudo -u asterisk -c "echo 1 > /sys/class/gpio/gpio18/value", gehört die Redirection zum auszuführenden Kommando.

EDIT:
Wobei natürlich ein sudo -u root -c "echo 1 >/sys/class/gpio/gpio18/value" (und zwar im Shell-Skript 18high.sh) die sicherste Lösung ist, bei der man (sofern man die /etc/sudoers passend editiert) auch nur Änderungen in geringem Umfang (bzw. an den dafür vorgesehenen Stellen) vornehmen muß. Den Benutzer für den Betrieb von Asterisk würde ich schon deshalb NICHT in eine Gruppe mit erweiterten Rechten (also auch nicht in die Gruppe gpio) aufnehmen, weil dann beim "Ausbruch" mit dessen Kontext und dem Zugriff auf Dateien zuviele Optionen für einen Angreifer eröffnet werden.
 
Zuletzt bearbeitet:
Asche auf mein Haupt, Anführungszeichen sind nicht meine Stärke ;-)

Inwiefern denkst Du könnte ein Angreifer was anstellen, wenn Asterisk in der GPIO Gruppe ist? Man sollte doch meinen, ein Dialplan ist so gebaut, dass niemand einfach irgendwelche beliebigen Shell Befehle ausführen kann. Asterisk selbst hat wohl hoffentlich keine Schreibrechte auf die Config. Außerdem sollte die Mitgliedschaft in der GPIO Gruppe zu nicht viel mehr berechtigen als die GPIO Pins zu bedienen.

Aber wäre es wenn dann nicht geschickter, System(sudo /abs/pfad/18high.sh &) zu machen und im Skript dann nur echo ...?
Weil dann könnte man den Asterisk User per sudoers zum Aufruf dieses einen Skripts berechtigen, ohne ihm anderweitig sudo Rechte geben zu müssen. Läuft das Skript als su, wird auch alles darin mit su Rechten ausgeführt.

Oder, ich weiß nicht ob ich's schon gesagt habe, auf sysfs verzichten und den GPIO Pin mit Python steuern :D

Edit:
Moment, ich habe es Interesse halber gerade ausprobiert, ein
sudo -u asterisk echo 1 > /home/pi/test
ohne jegliche Anführungszeichen schreibt eine 1 in die Datei /home/pi/test
 
Moment, ich habe es Interesse halber gerade ausprobiert, ein
Ja, aber mit den Rechten des Users, der das sudo aufgerufen hat.

Rich (BBCode):
pi@pi4:~ $ touch /home/pi/test; chmod 600 /home/pi/test; sudo chown strongswan:nogroup /home/pi/test; ls -l /home/pi/test
-rw------- 1 strongswan nogroup 0 Dec 21 18:54 /home/pi/test
pi@pi4:~ $ sudo -u strongswan echo new_line >> /home/pi/test
-bash: /home/pi/test: Permission denied
pi@pi4:~ $ sudo -u strongswan bash -c "echo new_line >> /home/pi/test"
pi@pi4:~ $ cat /home/pi/test
cat: /home/pi/test: Permission denied
pi@pi4:~ $ sudo -u strongswan cat /home/pi/test
new_line
pi@pi4:~ $
Ich habe zwar keinen Benutzer asterisk auf dem betreffenden Pi, aber der Benutzername spielt ja nicht wirklich die entscheidende Rolle.

Außerdem sollte die Mitgliedschaft in der GPIO Gruppe zu nicht viel mehr berechtigen als die GPIO Pins zu bedienen.
Schon das ist zuviel. In einem Dialplan kann man auch leicht Fehler machen (z.B. die Übernahme von ungeprüften Eingaben bei der Ausführung von Shell-Funktionen - und viele der Channel-Variablen sind durch einen Anrufer zu beeinflussen, u.a. die Caller-ID) und nach dem Prinzip, daß "elevated privileges" so spät wie möglich erlangt und so früh wie möglich wieder entzogen werden sollten, ist es falsch, das gesamte Skript in einem sudo-Kontext aufzurufen, wenn es auch ausreichen würde, die Ausführung EINZELNER Kommandos in einem "elevated state" zu veranlassen.

Nimmt man den Benutzer asterisk in die Gruppe gpio auf, hat er VOLLEN Zugriff auf ALLE GPIO-Pins und kann deren Mappings ins Userland verändern (neue hinzufügen oder bestehende entfernen) - angesichts denkbarer(!) Schwächen in der Implementierung eines Dialplans irgendwie nichts, was ICH (andere mögen da anderer Ansicht sein) so gerne hätte.

System(sudo /abs/pfad/18high.sh &)
Was die parallele Ausführung des Shell-Skripts 18high.sh (das ist ja der Name, den der TO irgendwo vorher mal "vergeben" hat) jetzt besser machen sollte (das wäre ja das abschließende & in dem Aufruf), verstehe ich nicht und wenn in 18high.sh die einzelnen Kommandos (je nachdem, wie kompliziert man das macht, ist es ja nur ein einziges echo-Kommando - wenn das Gegenstück 18low.sh heißen sollte) mittels sudo aufgerufen werden, braucht man nicht für das gesamte Skript die erhöhten Rechte (es KÖNNTE ja auch mehr als eine Zeile in diesem Skript stehen).

Daß die Skript-Datei irgendwo "sicher" zu speichern ist (z.B. in /usr/local/bin, was hoffentlich auch in einer Zeile Defaults secure_path= in der /etc/sudoers eingeschlossen wird in den Suchpfad) und niemand außer dem Superuser dort Schreibrechte haben sollte und die Gruppe bzw. ggf. noch "others" nur Lese- und Ausführrechte erhält, versteht sich sicherlich von selbst.

Oder, ich weiß nicht ob ich's schon gesagt habe, auf sysfs verzichten und den GPIO Pin mit Python steuern
Inwiefern macht das dann das gesamte Konstrukt irgendwie sicherer? Soweit ich weiß, arbeiten diese Python-Klassen mit Memory-Mapped-I/O für die GPIO-Pins und da auch dieses Mapping erst einmal über /dev/mem einzurichten wäre, sind dann für den Python-Aufruf ebenso wieder Superuser-Rechte erforderlich.

Angesichts der Tatsache, daß hier weder die Abfrage von Pins noch irgendein Trigger beim Ändern eines Signals verwendet werden, wäre Python (m.E.) totaler Overkill, zumal ich mich frage, woher die Aussage:
Das Pseudo Filesystem ist übrigens als veraltet zu betrachten
wohl kommen mag - zumal das ohne den Zusatz "für den GPIO-Zugriff" viel zu pauschal ist und an der Realität vorbei geht. Es werden - ganz im Gegenteil - sogar immer mehr Einstellungen über Pseudo-Dateisysteme zugänglich gemacht ... man braucht ja nur mal ein mount einzugeben (meinetwegen im Raspbian) und zu zählen, wieviele Mountpoints mit derartigen Pseudo-Dateisystemen belegt sind.

Ich bin sogar der Ansicht, daß man in der /etc/sudoers das Ausführen einer bash-Shell (ohne Kennworteingabe) und darin eines echo-Kommandos auf exakt den Pfad /sys/class/gpio/gpio18/value festlegen kann (probiere ich aber erst später selbst aus), denn da steht im man-File das Folgende:
sudo allows shell-style wildcards (aka meta or glob characters) to be used in host names, path names and command line arguments in the sudoers file.
und das sollte sich - mit passender "Formulierung" - dann auf das Schreiben der Werte 0 bzw. 1 in die Datei /sys/class/gpio/gpio18/value beschränken lassen. Das Mapping des GPIO-Pins 18 ins Userland ist ohnehin Aufgabe der System- oder Asterisk-Initialisierung - das wird man ja eher nicht bei JEDEM Aufruf des "Klingel-Skripts" machen wollen.

Und by the way ... daß der Aufruf des Skripts am besten mittels NOPASSWD in der /etc/sudoers erlaubt werden sollte:
Weil dann könnte man den Asterisk User per sudoers zum Aufruf dieses einen Skripts berechtigen, ohne ihm anderweitig sudo Rechte geben zu müssen. Läuft das Skript als su, wird auch alles darin mit su Rechten ausgeführt.
, stand (meinerseits) schon in #9.
 
Zuletzt bearbeitet:
  • Like
Reaktionen: Mrs. Moose
Danke für euren Input - ja, am Ende war es dann tatsächlich eine Rechtegeschichte - So geht's jedenfalls!:
Zum Testen musste auch bei dieser Zeile in der extension.conf das Pin auf HIGH gehen:
exten => alle,n,System(echo "1" > /sys/class/gpio/gpio18/value)
Das tat es nicht - bis ich:
chmod 666 /sys/class/gpio/gpio18/value
und
sudo usermod -a -G gpio <Username> (bei mir asterisk und tim als user hinzufügen)
Ab dann ging auch:
exten => alle,n,System(etc/asterisk/18high.sh) (dorthin hab ich die 18high.sh kopiert und berechtigt)
 
Dann drücken wir mal die Daumen, daß Deine Konfiguration wasserdicht ist oder KEINE Daten verarbeitet, deren Inhalt nicht vollkommen unter Deiner Kontrolle steht.

Klar reicht es auch aus, einfach das Rechtekonzept von Linux zu untergraben und dahingehend aufzuweichen, daß man Rechte weit über das erforderliche Maß erweitert.

Das sollte man aber keinesfalls mit "best practices" verwechseln oder zur Nachahmung empfehlen, solange nicht klar ist, daß beim Nachahmen ebenfalls die Rahmenbedingungen stimmen und man sich damit keine Lücken in seiner Asterisk-Installation aufreißt. Entsprechende Vorfälle gibt es jedenfalls (leider) immer wieder und wenn die beiden Benutzer jetzt Mitglied der Gruppe gpio sind, können sie auch auf die "Steuerung" der gesamten GPIO-Implementierung zugreifen.

Wobei hier auch irgendetwas noch nicht so ganz stimmen kann - warum muß man denn auch noch JEDEM Benutzer Schreib- und Leserechte auf eine Datei einräumen (genau DAS ist ja der Unterschied zwischen dem Standardwert 0660 und dem lt. Beitrag geänderten 0666), wenn man den Benutzer bereits in die entsprechende Gruppe aufgenommen hat und damit für ihn schon die zweite 6 Schreib- und Lesezugriff gestatten würde?

Mit viel Phantasie könnte man sich noch ein Problem beim Traversieren der Verzeichnisstruktur bis zur entsprechenden value-Datei vorstellen … wenn das aber nicht der Fall sein sollte, dann kann jetzt JEDER Benutzer auf dem RasPi den Zustand des Pins auslesen und neu setzen. Einfach mal ausprobieren … beim Ändern von sicherheitsrelevanten Einstellungen (auch wenn's hier nur die Türklingel sein mag, die da dran hängt - beim nächsten Mal ist es dann vielleicht die gesamte (De-)Aktivierung einer Alarmanlage) sollte man die Konsequenzen bestenfalls auch immer verstehen und nicht nur auf gut Glück irgendwelchen Tipps im Internet folgen.

Just my 2 cents …
 
Holen Sie sich 3CX - völlig kostenlos!
Verbinden Sie Ihr Team und Ihre Kunden Telefonie Livechat Videokonferenzen

Gehostet oder selbst-verwaltet. Für bis zu 10 Nutzer dauerhaft kostenlos. Keine Kreditkartendetails erforderlich. Ohne Risiko testen.

3CX
Für diese E-Mail-Adresse besteht bereits ein 3CX-Konto. Sie werden zum Kundenportal weitergeleitet, wo Sie sich anmelden oder Ihr Passwort zurücksetzen können, falls Sie dieses vergessen haben.