Https Request mit SSL empfangen

Ich habe mir um von außen per Http mit SSL-Verschlüsselung Sachen an meinem Miniserver schalten zu können (z.B. über Tasker oder IFTTT) einen kleinen Serverdienst in Python programmiert, welcher aus solchen POST's ein UDP Paket an meinen Miniserver schickt. Das ganze läuft bei mir auf einem Raspberry Pi, müsste natürlich aber auch auf anderen System laufen:

Ihr müsst ein System haben auf welchem Python 3.x installiert ist.

Zunächst installiert ihr bottle für Python, bottle ist ein simpler http Server Dienst:

sudo apt-get install python-bottle 

 

Wenn ihr das fertig habt müsst ihr euch ein SSL-Zertifikat erstellen mit:

openssl req -new -x509 -keyout key.pem -out cert.pem -days 3650 -nodes

Wichtig ist dass ihr bei "common name" den korrekten Namen, sprich den DNS Eintrag unter dem euer RPi zu erreichen seid eintragt!

Das SSL Zertifikat hat eine gültigkeit von 3650 Tagen, wird allerdings in Browsern als nicht sicher angezeigt, da es von euch selbst zertifiziert ist! Für eine HTTP Post von Tasker oder IFTTT spielt das aber keine Rolle!

Dann erstellt ihr das Python Programm mittels

nano https2UDP.py

und fügt dann folgenden Code dort ein:

#!/usr/bin/python
# -*- config: utf-8 -*-

from __future__ import absolute_import, division, print_function
import bottle
from bottle import request, route, get, run, ServerAdapter, post

import sys
import socket

# !!!! BEGIN CHANGE ME !!!!

Miniserver_IP = ''
Miniserver_PORT = 8885
Http_Port = 21607
Http_Route = 'dhjkfgsd8345igsdf78534gdgbfg786345i6'
Zertifikat = '/home/pi/cert.pem'
Schluessel = '/home/pi/key.pem'

# !!!! END CHANGE ME !!!!

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# copied from bottle. Only changes are to import ssl and wrap the socket
class SSLWSGIRefServer(ServerAdapter):
    def run(self, handler):
        from wsgiref.simple_server import make_server, WSGIRequestHandler
        import ssl
        if self.quiet:
            class QuietHandler(WSGIRequestHandler):
                def log_request(*args, **kw): pass
            self.options['handler_class'] = QuietHandler
        srv = make_server(self.host, self.port, handler, **self.options)
        srv.socket = ssl.wrap_socket (
         srv.socket,
         certfile=Zertifikat,
         keyfile=Schluessel,  # path to certificates
         server_side=True)
        srv.serve_forever()

@post('/'+Http_Route+'/<Befehl>')
def UDP_Befehl(Befehl):
    print('Http Befehl: ')
    print (Befehl+"\n")
    sock.sendto(bytes(Befehl, 'utf-8') , (Miniserver_IP, Miniserver_PORT))
#    return 'Thank you for your post'


def main():
#    bottle.run(host='', port=Http_Port)
    srv = SSLWSGIRefServer(host='', port=Http_Port)
    run(server=srv)

if __name__ == '__main__':
    main()

Hier müsst ihr dann noch folgende Dinge eintragen:

Miniserver_IP = 'x.x.x.x'
Miniserver_PORT = 8885
Http_Port = 21607
Http_Route = 'Hallo'
Zertifikat = '/home/pi/cert.pem'
Schluessel = '/home/pi/key.pem'

 

Miniserver_IP und entsprechenden UDP Empfangs-Port

Http_Port: hier muss dann auch eine Port-Weiterleitung von aussen eingerichtet werden (Fritzbox, oder anderen Router)

Http_Route: Diese wird benötigt um anzugeben wie der Aufruf aussehen soll. Tragt ihr dort zum Beispiel "Hallo" ein muss der Aufruf wie folgt aussehen: my.DynDNS.eintrag:21607/Hallo/Eurer_Befehle. Hierbei wird dann alles nach dem /Hallo/ als UPD Nachricht an den Miniserver geschickt. Das my.DynDNS.eintrag und der Port müssen natürlich von euch entsprechend angepasst werden. Ich habe meine Http_Route einfach aus Groß-, Kleinbuchstaben und Zahlen zusammengesetzt. Das macht es noch schwerer um von aussen zufällig etwas an den MS zu schicken.

Zertifikat und Schluessel: Hier müssen das Zertifikat und der Client-Schlüssel welche ihr oben erzeugt habt mit kompletten Pfad angegeben werden.

Wichtig noch: das ganze funktioniert nur mit Http POST Anfragen, alle andere habe ich gesperrt! Gebt ihr die Adresse daher in einen Browser ein kommt folgende Meldung:

Error: 405 Method Not Allowed

Bekommt ihr diese Meldung wisst ihr aber das alles richtig installiert ist. Bzw. vorher müsste noch die Meldung kommen das das Zertifikat nicht sicher ist, da ihr es ja selbst erstellt habt.

 

So das war es auch schon.

Nun könnt ihr das ganze testen:

python3 https2UDP.py

Um das Programm beim Starten zu starten geht ihr wie folgt vor:

sudo crontab -e

hier trag ihr dann folgendes ein:

@reboot python3 /home/pi/httpsUDP.py > /dev/null 2>&1

So und schon sollte es laufen.

 

Falls fragen sind bitte einfach melden.

 

Gruß Iksi