433 MHz-Codes empfangen und den Raspi über Funk fernbedienen

Wie man mit dem Raspberry Pi 433-Mhz-Geräte wie Funksteckdosen fernsteuert habe ich ja bereits in einem vohergehenden Projekt beschrieben.

Heute soll die Gegenseite zum Zug kommen: wir wollen mit dem Raspi 433 MHz-Signale empfangen und so den Raspi mit einer Fernbedienung fernsteuern.

Zuerst wollen wir das mit einem fertigen Kit bewerkstelligen und dann noch mehr aus dem Kit kitzeln, indem wir es dazu gebrauchen, beliebige 433-Mhz-Code zu empfangen, z. B. auch von bereits vorhandenen Funksteckdosenfernbedienungen, und auszuwerten.

Für dieses Projekt verwenden ich ein 2272-Kit mit braunem Sender mit ausziehbarer Antenne wie rechts zu sehen. Es gibt diese Kits für 315 und 433 MHz, ich habe mich für die 433 MHz-Version entschieden, weil ich für diese Frequenz schon andere Fernbedienungen besitze.

Der Sender


Den Sender muss man aufschrauben und eine dieser kleinen, zylindrischen 12 Volt Batterien A23S einsetzen. Im Inneren des Senders befindet sich in PT2264-Chip, der für die Kodierung und Aussendung der Signale zuständig ist.

A0 ... A7 Zur Einstellung einer von 531441* (312) Kombinationen zur Individualisierung A8/D3 ... A11/D0 wie oben, allerdings nur Zustände high und low, wenn D0 ... D3 gebraucht werden sollen /TE Tranmission enable. Wenn LOW, wird die kodierte Waveform an DOUT ausgegeben. OSC1 Output-Oszillator OSC2 Input-Oszillator DOUT Data Out. Hier wird die kodierte Waveform ausgegeben. VCC Spannungsversorgung +5V VSS GND
Drehen wir die Platine im Sender um, fällt uns auf, dass die untere Reihe der Pins der PT2264 nicht verlötet ist. Das ist Absicht. Denn hier liegen die Pins A7 ... A0 (von links nach rechts, neben dem bereits verlöteten VSS-Pin 9).

Diese können so bleiben (Zustand FLOAT) oder auf HIGH (H-Lötpads) oder LOW (L-Lötpads) gezogen werden. So kann man seine geheime, individuelle Kodierung mit über 500'000* Kombinationen einstellen.

Ich habe keine Ahnung, ob der China-Mann am Lötkolben die Lötstellen täglich oder sonstwie variiert, aber man muss die Möglichkeit einschließen, dass alle ausgelieferten Platinen gleich kodiert sind. Wer hier also einen individuellen und geheimen Code will, weil es um etwas wichtiges wie z. B. den Öffner für sein Garagentor geht, sollte den Lötkolben ansetzen.

Was macht der Sender? Kurz gesagt: Drücke ich einen der 4 Knöpfe, dann kodiert er diese je nach eingestellter Kodierung anders auf eine Waveform (Wellenform) und sendet diese auf 433.92 MHz in den Äther.

Der Empfänger

Auf der anderen, der Empfängerseite werkelt ein SC2272. A0 ... A7 Zur Einstellung einer von 531441* (312) Kombinationen zur Individualisierung A8/D3 ... A11/D0 wie oben, allerdings nur Zustände high und low, wenn D0 ... D3 gebraucht werden sollen DIN Input der kodierten Waveform OSCO Output-Oszillator OSCI Input-Oszillator VT wird HIGH, wenn das Signal gültig ist VCC Spannungsversorgung +5V / +3.3V VSS GND
Beim Empfängermodul ist natürlich zuerst darauf zu achten, das A0 ... A11 gleich konfiguriert sind. Dies ist sozusagen der Schlüssel für die Kodierung / Dekodierung und nur so werden die Ausgänge D0 ... D3 richtig geschaltet. Die Lötungen müssen denen des Empfängers entsprechen.

Was macht der Empfänger? Nun, die Schaltung um den SC2272 empfängt die Signale auf 433.92 MHz und stellt sie dann an DIN am SC2272 bereit (das wird später noch einmal interessant). Der SC2272 dekodiert diese Wellenformen und schaut, ob eine zu den durch A0 ... A11 konfigurierten passt. Ist dies 2x hintereinander (zur Sicherheit gegen zufällige Störstrahlung) der Fall, dann setzt er VT auf HIGH und ebenfalls D0 bis D3 für die Knöpfe A bis D. Hier können nun Relais angeschlossen werden, die z. B. ein Garagentor öffnen oder schließen.

Die Schaltung



Die Schaltung ist denkbar einfach: Das 2272-Empfangsmodul wird ins Breadboard gesteckt und 5V mit 5 Volt und GND mit GND auf dem Breadboard verbunden. Dann kommt an D0 bis D3 jeweils der Pluspol einer LED. Da es bei mir ein wenig zu eng dafür war, war die LEDs zu groß, habe ich nur die beiden äußeren D-Leitungen direkt verbunden und die beiden anderen links daneben gesetzt und mit Dupont-Kabeln verbunden.

Jeweils ein 220 Ohm-Vorwiderstand führt von den LEDs zu GND des Boards. Fertig ist die Schaltung. Das Breadboard und der Raspi ist hierbei nur Stromspender. Die Schaltung läuft ohne Programm.


Drückt man nun die Taste A auf dem Sender, so funkt dieser den Code für die gedrückte Taste in den Äther, der Empfänger empfängt ihn, dekodiert den Code, erkennt die Taste A und schaltet den Ausgang D0 auf High, was die LED zum Leuchten bringt.

Seltsam war allerdings, dass ich den Sender ganz nah, ca. 20 cm neben den Empfänger halten musste. Ich war schon ganz enttäuscht und wollte das Fluchen ob des Billig-Mists anfangen, da kam mir die Idee, es doch einmal mit 3.3V als Stromversorgung für den Empfänger zu versuchen. Und komischerweise funktionierte es damit erheblich besser. Nun funktionierte es quer durch den Raum und auch ein paar Meter darüber hinaus, also so ca. 10 Meter. Obwohl 5 Volt als Versorgungsspannung angegeben sind, funktioniert es mit 3.3V besser? Sonderbar. Die Freude war trotzdem groß.

Die Ausgänge des 2272 kann man jetzt mit maximal 3.3V auch bedenkenlos an beliebige Raspberry-Ports anschließen (als Input Pulldown definieren) und auswerten. So könnte man vier Funktionen in Python schalten, die ausgeführt werden sollen, wenn man den entsprechenden Knopf an der Funkfernbedienung drückt. Diese Fernbedienung ist auf jeden Fall komfortabler als die Fernsteuerung mittels Infrarot-Fernbedienung, bei der man doch ein bisschen komisch zielen musste und die viel Konfigurationsaufwand hatte. Dafür hat man aber auch nur 4 Funktionen.

Mit dem 2272-Kit beliebige Codes empfangen


Jetzt nutzen wir aus, dass das 433-MHz-Signal in digitaler Form in den SC2272 geschickt werden muss, damit der die Wellenformen erkennen kann.

Dieses Signal liegt an DIN des 2272 an - das ist der 5., also mittlere Pin oben, wenn die IC-Kerbe links ist. Dort greifen wir es mit einem Messfühler ab und schicken es in den Raspi-Port B27. Bitte beachten: den SC2272 nur auf 3.3V betreiben (was bei mir ja besser ging als mit 5V), sonst könnten hier mehr als 3.3V (nämlich bis zu 5V) anliegen und den Raspi beschädigen. Wenn es doch nicht anders geht als mit 5 Volt: Eingangsspannung messen und ggf. durch Teilwiderstände heruntersetzen!

Wer keinen Messfühler hat, kann auch ein kleines Kabel an die Rückseite des SC2272 löten. Aber bitte nicht zu lange auf der Stelle rumbraten. ICs sind hitzeempfindlch und eine Überhitzung könnte deren Tod bedeuten.

Das an Pin BCM 27 anliegende 433-MHz-Signal lassen wir dann nicht mehr durch den SC2272 auswerten, sondern durch den Raspi. Der kann uns dann alle empfangenen Code ausgeben, auch die, die nicht von der ursprünglichen Fernbedienung kommen, sondern auch von anderen.

Dafür benutzen wir die 433Utils. Falls die 433Utils noch nicht wegen des anderen Projektes installiert sind, müssen wir dies jetzt nachholen:

433 Utils installieren

Installiert wird das Paket, indem wir es von GitHub herunterladen und kompilieren git clone --recursive git://github.com/ninjablocks/433Utils.git cd 433Utils/RPi_utils/ make Hängt die Datenleitung nicht an BCM 17, sondern an einem anderen Pin, muss in codesend.cpp die Zeile int PIN = 0; vor dem Kompilieren (make) angepasst werden. Es ist hier die WPI-Nr. anzugeben, die man hier nachschlagen kann. Außerdem muss das WiringPi-Paket installiert sein. Danach finden sich ein paar Tools im Verzeichnis ~/433Utils/RPi_utils pi@raspberrypi:~/433Utils/RPi_utils $ ll insgesamt 104K drwxr-xr-x 2 pi pi 4,0K Sep 12 18:35 . drwxr-xr-x 7 pi pi 4,0K Sep 12 18:33 .. -rwxr-xr-x 1 pi pi 20K Sep 12 18:35 codesend -rw-r--r-- 1 pi pi 2,0K Sep 12 18:33 codesend.cpp -rw-r--r-- 1 pi pi 2,3K Sep 12 18:35 codesend.o -rw-r--r-- 1 pi pi 535 Sep 12 18:33 Makefile -rw-r--r-- 1 pi pi 925 Sep 12 18:33 README.md -rwxr-xr-x 1 pi pi 21K Sep 12 18:35 RFSniffer -rw-r--r-- 1 pi pi 1,3K Sep 12 18:33 RFSniffer.cpp -rw-r--r-- 1 pi pi 2,7K Sep 12 18:35 RFSniffer.o -rwxr-xr-x 1 pi pi 20K Sep 12 18:35 send -rw-r--r-- 1 pi pi 1,9K Sep 12 18:33 send.cpp -rw-r--r-- 1 pi pi 3,0K Sep 12 18:35 send.o Uns interessiert heute das Programm RFSniffer. Dies übernimmt die ganze Erkennung der 433-MHz-Signale und wandelt sie mittels der dahinter stehenden RCSwitch-Library in einen eindeutigen Code um, den sie ausgibt.

pi@raspberrypi:~/433Utils/RPi_utils $ ./RFSniffer Received 7689664 Received 7689664 Received 7689664 Received 7689664 Diesen Code können wir mit dem Sendemodul aus dem anderen Projekt wieder senden. Dazu benutzen wir das Tool codesend. So können wir uns die Codes von ganz unterschiedlichen Funkfernbedienungen aufschreiben und wieder senden und tun dann mit dem Raspi genau dasselbe und können damit z. B. Funksteckdosen schalten, Garagentore öffnen, Alarmanlagen an- und ausschalten und wozu 433-MHz-Geräte sonst noch gebraucht werden.

Sicherheitsüberlegungen

Bruteforce Attack

Auch wenn sich 531441* Kombinationen erstmal viel anhören, soviel wie fünf 5-stellige Zahlenschlösser, so gibt es nur eine begrenzte Zahl von unterschiedlichen Code. Für Standard-Funksteckdosen sind dies z. B. 32*5 = 160 fürs Einschalten und noch einmal 160 fürs Ausschalten. Bei dem vorliegenden 2272-Kit muss man davon ausgehen, dass diese immer gleich kodiert aus der Fabrik kommen.

*Das ist eine Milchmädchen-Rechnung. Denn eigentlich sind es nur 38 * 24 = 6561 * 16 = 104'976 sind und wenn man bedenkt, dass die Lötaufwand für A9 ... A11 höher ist und ihn wohl kaum jemand durchführen wird, sogar nur 38 = 6561 Kombinationen

Nun kann man mit einem 433 MHz-Sender, z. B. am Raspi alle Kombinationen durchprobieren. Normalerweise reagiert ein Gerät auf einen Impuls von ca. einer Zehntel Sekunde. Das heißt, alle Codes für einen bekannten Funksteckdosenhersteller sind in 16 Sekunden durchprobiert.

Für das vorliegende Kit, bei dem man A0-A7 frei zwischen 3 Zuständen ändern kann, ergeben sich dann 38 = 6561 Kombinationen. Denn auf der Empfänger-Platine existieren keine Löt-Pads für A9 und höher, also wird diese wohl niemand benutzen. Wenn man heraus hat, die der PT2264 kodiert (durch beobachten und auswerten), dann sind dies 6561 bekannte Codes, die in knapp 11 Minuten alle durchprobiert sind.

Record und Replay

Aber was hält mich davon ab, einen kleinen Arduino mit Empfänger in eine Tarnung wie einen hohlen Pflasterstein einzubauen und neben der Garage zu positionieren und diesen alle Codes, die im Umfeld gesendet werden aufzunehmen? Am nächsten Tag hole ich meine Schaltung dann wieder ab und schaue mir das Protokoll an und weiß den Code, den ich dann wieder vor Ort senden kann und so Zutritt erhalte, wann immer ich will...

Machen wir uns nichts vor: alles was per Funk gesendet wird, kann auch von Unberechtigten aufgefangen und ausgewertet werden. Man sollte diese Technologie also nicht einsetzen, wenn es um sicherheitsrelevante Themen geht. Wenn ich von Alarmanlagen höre, die mit einem Sender auf 433 MHz (oder anderen Frequenzen) mit einem Tastendruck deaktiviert werden können, werde ich hellhörig. Wenn Sender und Empfänger nicht einen sich ständig ändernden Code verwenden, der auf sicher kryptografischem Weg mittels individuellem Schlüssel synchron gehalten wird, dann ist so etwas einfach nur unsicher. Ich glaube ja nicht, dass dieser Aufwand betrieben wird. Und selbst wenn, ist er nur Makulatur, wenn sich der Code nicht in der Zeitperiode ändert, die für eine Bruteforce Attacke nötig wäre.

Das Eingeben eines Codes auf einem Keypad mittels Tastendrucken erscheint mir da doch sehr viel sicherer. Ist aber natürlich nicht so bequem, wenn man dazu z. B. aus dem Auto steigen muss. Wobei wir wieder beim alten Grundsatz wären, dass sich Sicherheit meist umgekehrt proportional zur Bequemlichkeit verhält.