Umgehungsstraße

Permalink

Eine von mehreren Möglichkeit die SOP zu umgehen ist alle Netzwerkzugriffe über einen Proxy umzulenken. Das ist zwar keine schöne Lösung, trotzdem habe ich aber eine sehr primitiven Umsetzung in Python zusammengestrickt.

Aufgabestellung war es beliebige URLs zu Dateien und RSS-Feeds verfügbar zu machen ohne das der Podcatcher bzw. der Browser die fremde Herkunft solcher Ressourcen bemerkt und die SOP eingreift. Zusätzlich soll der Zugriff auf mich eingeschränkt sein. Das ist leider nötig da ich keine Lust habe jedermann Traffic zu bezahlen und, viel wichtiger, nicht jedem erlauben möchte allerlei Schund über meinen Server zu tunneln.

Wie schon gesagt erfolgt die Programmierung in Python. Zu beginn prüft das Script ob ein HTTP-GET-Request vorliegt. Alle anderen Methoden werden nicht unterstützt.

if os.environ['REQUEST_METHOD'] == 'GET':
   DoGet()
else:
   print("Status:405 Method Not Allowed")
   print
   print("405 Method Not Allowed")

In der zweiten Prüfung wird ein Password geprüft. Dieses muss vom Klient über einen URL-Parameter secret übergeben werden. Theoretisch kennen nur das Script und Ich dieses Password. Damit wäre die gewünschte Autorisierung gewährleistet.

httpGetParameter = cgi.FieldStorage()
if not ("secret" in httpGetParameter and httpGetParameter["secret"].value.decode('utf-8') == "mysecret"):
   print("Status:401 Unauthorized")
   print
   print("401 Unauthorized")
   return

Um den eigentlichen Zweck des Proxies zu realisieren wird dann versucht aus einem weiteren URL-Parameter, naheliegenderweise mit Namen url, die aufzurufende Adresse in Erfahrung zu bringen.

if "url" in httpGetParameter:
   url = httpGetParameter["url"].value.decode('utf-8')
else:
   url = None

Diese wird dann durch das Script aufgerufen und die zurückgelieferten Daten werden eins zu eins an den Podcatcher weitergereicht. Damit der Proxy nicht wartet bis die ganze Datei heruntergeladen wurde bevor er sie an den Browser weiterreicht stückele ich das ganze in Teile a 16 kB. Ohne diese Maßnahme muss der Client recht lange warten bevor er die ersten Daten sieht. Dies wiederum führt zu Timeouts und Verbindungsabbrüchen.

filehandle = urllib.urlopen(url)
...
CHUNK = 16 * 1024
while True:
   chunk = filehandle.read(CHUNK)
   if not chunk: break
   sys.stdout.write(chunk)

Serverseitig ist damit alles Fertig. Damit mein Podcatcher den Proxy auch noch benutzt habe ich eine Eingabemöglichkeit für die Proxy-URL geschaffen. Hierbei dient %URL% als Platzhalter für die eigentliche Adresse der gewünschten Ressource. Beim Laden von Daten aus dem Internet versucht mein Podcatcher immer zuerst die Datei direkt herunterzuladen. Klappt das nicht, wird ein zweiter Versuch mit dem Proxy unternommen.

Das ist schon das ganze Geheimnis. Ja, ich weiß das das sehr rudimentär ist und, insbesondere im Bereich der Sicherheit, bestimmt vieles unbedacht lässt. Allerdings ging es mir hier auch nur um eine schnelle Lösung für mein SOP-Problem. Falls also jemand eine bessere Idee hat die mir wenig Arbeit bereitet – immer her damit.

Im übrigen setzte ich zusätzlich auch einen HTTP-Header gemäß der CORS-Spezifikation. Damit sollte der Proxy auch mit meinem Podcatcher zusammen Funktionieren wenn du ihn mit einem eigenen Password auf deinem eigenen Webspace betreibst.

Den gesamten Code gibt es auf GitHub zu begutachten.