Dieter: PHP-Script als "Gateway" zu einer externen MySQL-DB ?

Hallo,
mein Problem ist folgendes:

Ich muss auf eine externe, d.h. diese Datenbank liegt nicht auf dem gleichem Server wie mein Script, zugreifen. Leider ist aber die Nutzung/Anmeldung von einem externen Host nicht vorgesehen und der zuständige "Admin" offensichtlich nicht in der Lage, diese Freischaltung kurzerhand in der mysql-user einzustellen - dieses ist aber ein anderes Thema.

Da der Einsatz meines Scriptes auf dem gleichem Server wo auch die zu benutzende Datenbank liegt ausgeschlossen ist, bin ich auf die Idee gekommen, eine Art "Gateway" per Script zu nutzen - in der Art:
Mein Script (liegt auf Server I):
-> greift auf PHP-Script (liegt auf Server II) per POST zu
-> PHP-Script führt die MySQL-Anweisungen localhost aus
-> PHP-Script liefert die Ergebnisse wieder an Server I (mein Script)

Soweit, so gut - aber jetzt stehe ich da und weiß überhaupt nicht, ob:
a) diese Lösung überhaupt sinn macht und realisierbar ist
b) wie ich das ganze technisch/programmiertechnisch lösen kann.

Ich bitte daher hier um ein bisschen Mithilfe und Denkanstösse...
Gibt es vielleicht derartiges bereits fertig (man muß ja nicht das Rad neu erfinden) ?

VG
Dieter

  1. Soweit, so gut - aber jetzt stehe ich da und weiß überhaupt nicht, ob:
    a) diese Lösung überhaupt Sinn macht und realisierbar ist
    b) wie ich das ganze technisch/programmiertechnisch lösen kann.

    Also im Prinzip geht das.

    === Aber ===

    Ich befürchte sehr ernsthaft, dass Du Dir ein erhebliches Sicherheitsproblem baust. Denn wenn Du nichts weißt, wie Du das technisch lösen kannst dann weißt Du auch nicht wo die Haken sind. Das ist nämlich nicht trivial.

    Im folgenden sind
    "Webserver"   - Der Server, der keinen Zugang zur Datenbank hat.
    "Datenserver" - Der Server mit dem Zugang

    === Im Prinzip geht es universell ===

    Auf dem entfernten Server ein Skript erstellen, welches Deine Abfrage entgegen nimmt und das Ergebnis z.B. als JSON zurück gibt.

    Problematisch hierbei: Eine Authentifizierung ist absolut notwendig - die Daten gehen aber im Klartext über das Netz. Es wäre zwar über ein servergeneriertes Token für jeden Zugriff und die Beschränkung auf die IP des Clients (der eigentliche Webserver) durchaus möglich dies zu beheben, aber darunter leidet die Performance:

    Webserver stellt Anfrage nach Token

    Datenserver prüft die IP und liefert ein Token (zufälligen String) oder eine Fehlermeldung (dann exit).Der Datenserver speichert einen Schlüssel (Hash aus dem Token und einem beiden Seiten bekanntem "Geheimnis") sowie einen Timestamp in einer Datentabelle.

    Webserver hasht das Token und das auch ihm bekannte "Geheimnis" und schickt das Ergebnis als Schlüssel zur Authentifizierung mit der Abfrage an den Datenserver.

    Datenserver löscht alle überalterten Schlüssel aus der Tabelle und prüft danach, ob die IP stimmt und ob der Schlüssel in der Tabelle ist.
    * Falls eines davon nicht: Fehlermeldung, exit.
    * Falls ja wird der Schlüssel gelöscht, die mitgelieferte Abfrage ausgeführt und das Ergebnis (aus meiner Sicht am besten) nach JSON umgewandelt, dieses wird (womöglich komprimiert) gesendet.

    1. Webserver wertet die empfangenen Daten aus.

    Der Datentransport sollte zusätzlich verschlüsselt erfolgen (HTTPS). Die Sicherheitssituation verschlechtert sich dennoch, denn das "Geheimnis" muss auf beiden Rechnern im Klartext gespeichert werden. Wer also Zugriff auf nur einen Hosts hat, der kann beide Webseiten und die Datenbank angreifen!

    === Schneller wäre spezielle Skripte für jede Abfrage ===

    Voraussetzung: Die NUR LESENDEN Abfragen sind, bis auf die Parameter (where foo="bar" - dann wäre "bar" ein Parameter) bekannt und die abrufbaren Daten sind ohnehin SÄMTLICH für die Öffentlichkeit bestimmt, es entsteht also kein Problem, wenn jemand diese Daten unberechtigt abruft.

    Auf dem Datenserver liegen Skripte für jede Abfrage, welche aus den übergebenen Parametern die Abfrage genau so zusammenbauen, wie Du es machen würdest, wenn Du direkt auf die Datenbank zugreifen könntest. Die Abfrage würde ausgeführt, das Ergebnis nach JSON, CSV, eine HTML-Tabelle, what ever umgewandelt und dann gesendet.

    Wenn die Daten nicht für die Öffentlichkeit bestimmt sind oder schreibende Zugriffe möglich sein müssen, dann musst Du das mit einer Authentifizierung (wie oben beschrieben) versehen und der Datentransport sollte ebenfalls verschlüsselt erfolgen (HTTPS).

    === Falls Dir das zu aufwendig ist ===

    Wechsle den Hoster. Variomedia bietet eine Datenbank, auf die man auch von entfernten Hosts zugreifen kann.

    Jörg Reinholz

    1. Hallo,

      zuerst einmal vielen Dank für deine ausführliche Antwort.

      Ich befürchte sehr ernsthaft, dass Du Dir ein erhebliches Sicherheitsproblem baust. Denn wenn Du nichts weißt, wie Du das technisch lösen kannst dann weißt Du auch nicht wo die Haken sind. Das ist nämlich nicht trivial.

      Ich glaube ich habe mich in meiner Fragestellung ein wenig zu lapidar ausgedrückt. Wie ich das i.d.S. technisch lösen kann ist mir schon bewusst, allerdings hoffte und hoffe ich auf eventuelle Erfahrungsberichte / ggf. fertige Klassen oder auch Hinweisen auf Aspekte die ich bis jetzt nicht beachtet habe.

      Das Problem ist generell das die Daten non-public sind und es aufgrund der (Un-)Fähigkeiten des DB-Serveradmins leider dieser Weg die einzig zu realisierende Lösung zu sein scheint.

      Generell würde ich selber bei so einem Lösungsvorschlag mein Veto einlegen, einfach aufgrund der ausführlich von dir umschriebenen Sicherheitsproblematik. Leider sehe ich aber bei den zugrundeliegenden Gegebenheiten keine anderen zufriedenstellenden (wenn man hierbei überhaupt von zufriedenstellend reden kann) Möglichkeiten.

      VG
      Dieter

      1. hi,

        Ich glaube ich habe mich in meiner Fragestellung ein wenig zu lapidar ausgedrückt. Wie ich das i.d.S. technisch lösen kann ist mir schon bewusst, allerdings hoffte und hoffe ich auf eventuelle Erfahrungsberichte / ggf. fertige Klassen oder auch Hinweisen auf Aspekte die ich bis jetzt nicht beachtet habe.

        Es gibt die PHP-Funktionen serialize() und unserialize(). Damit kannst Du einen Stream erzeugen aus beliebigen Datenstrukturen und die Strukturen aus dem Stream zurückgewinnen. Der Transport wäre dann über HTTP.

        Es wird wohl beim Eigenbau bleiben, das ist jedoch nicht weiter schwierig, eigentlich nur Tipparbeit, ansonsten eine schöne Aufgabe, ich habe schon Einiges in dieser Hinsicht entwickelt fürs Remote-DB-Management mit Perl.

        --Hotti

  2. hi,

    Ich muss auf eine externe, d.h. diese Datenbank liegt nicht auf dem gleichem Server wie mein Script, zugreifen. Leider ist aber die Nutzung/Anmeldung von einem externen Host nicht vorgesehen und der zuständige "Admin" offensichtlich nicht in der Lage, diese Freischaltung kurzerhand in der mysql-user einzustellen - dieses ist aber ein anderes Thema.

    Eine gänzlich andere Frage, aber nicht unbedeutend: Wenn nicht über Port 3306, wie kämest Du ansonsten auf den Server?

    Horst

    1. Hallo Horst,

      Eine gänzlich andere Frage, aber nicht unbedeutend: Wenn nicht über Port 3306, wie kämest Du ansonsten auf den Server?

      Horst

      das Problem ist das man nur als lokaler Nutzer (localhost) auf die Maschine bzw. MySQL kommt und ein externer Host / User kein Zugriff erhält.
      Diese Beschränkungen kann man z.B. über die user in der MySQL einstellen (wenn man es dann kann :-), sprich also einen MySQL-User anlegen, der nicht nur intern, sondern auch von ausserhalb zugreifen darf.

      Die Portkonfiguration ist dabei absolut nebensächlich, da der Port ja sozusagen lediglich die "Tür" zu der Maschine ist.

      Gruss
      Dieter

      1. hi,

        das Problem ist das man nur als lokaler Nutzer (localhost) auf die Maschine bzw. MySQL kommt und ein externer Host / User kein Zugriff erhält.

        Jaja, schon klar ;)

        Also noch einmal meine Frage, die für Dich von Interesse ist:
        Wie käme Benutzer auf die Maschine? Zur Aswähl stehen evntl. HTTP, Telnet, SSH, FTP und die üblichen Verdächtigen der IP-Stack-Family.

        Wenn Dir das bekannt ist, könnten wir über einen Gateway nachdenken.

        Hotti

        1. Hallo nochmal,

          Telnet, SSH sowie FTP scheiden aus, das einzige was nutzbar wäre ist leider P80, also HTTP (ja, leider noch nicht mal https). Zu allem Überfluss ist der Server-Admin des DB-Servers leider derart eingestellt, das dieser (kurioserweise) kein Problem damit hätte ein (!) PHP-Script auf der Maschine zuzulassen das ich dann über 80 ansprechen darf, aber sonst nix.

          Wenn ich Telnet/SSH zur Verfügung hätte, würde die Lösung nicht nur bereits feststehen sondern sicher schon laufen. Es ist mir unklar wie dieser Mann diese Position erhalten hat, auch ist mir unklar warum dieser ausgerechnet die unsicherste Lösung will, aber so ist es halt.

          Man(n) kennt das ja: Der KD ist König - auch wenn es noch so unsinnig ist.

          Mir wird auch ganz flau im Magen wenn ich daran denke das ich lustig und fröhlich relativ sensible Daten quer durchs Web schicken soll, aber mir fällt einfach nichts anderes ein.

          Es handelt sich im übrigen alles um reine Leseabfragen, allerdings sind diese dynamisch, d.h. eine feste Integration der querys innerhalb des Scriptes auf dem DB-Server sind nicht möglich.

          Gruss
          Dieter

          1. hi,

            Telnet, SSH sowie FTP scheiden aus, das einzige was nutzbar wäre ist leider P80, also HTTP (ja, leider noch nicht mal https). Zu allem Überfluss ist der Server-Admin des DB-Servers leider derart eingestellt, das dieser (kurioserweise) kein Problem damit hätte ein (!) PHP-Script auf der Maschine zuzulassen das ich dann über 80 ansprechen darf, aber sonst nix.

            Hmm, kein Telnet, SSh, FTP... Wie käme denn ein PHP-Script auf die Maschine?

            Horst

            1. hi,

              Telnet, SSH sowie FTP scheiden aus, das einzige was nutzbar wäre ist leider P80, also HTTP (ja, leider noch nicht mal https). Zu allem Überfluss ist der Server-Admin des DB-Servers leider derart eingestellt, das dieser (kurioserweise) kein Problem damit hätte ein (!) PHP-Script auf der Maschine zuzulassen das ich dann über 80 ansprechen darf, aber sonst nix.

              Hmm, kein Telnet, SSh, FTP... Wie käme denn ein PHP-Script auf die Maschine?

              Horst

              So, jetzt alle lachen:
              Ich soll dem Admin des DB-Servers das Script geben; er will es dann "überprüfen" (wie auch immer dieses aussehen soll) und dieser wird es dann auf dem DB-Server "bereitstellen".
              Bevor ich jetzt geprügelt werde: DAS ist der Originalwortlaut des Admins.

              Ich werde bei diesem Projekt wohl neben meinen normalen RE-Positionen wohl noch die Positionen "Beruhigungsmittel" sowie "Schmerztabletten aufgrund nachhaltiger Beseitigung der aufgrund andauernder Lachattacken aufgetreten Magenkrämpfe" hinzufügen müssen...

              Ich habe den Admin ja schon darum gebeten einen Tunnel aufzumachen, irgendwie und warum und ob dieser mich überhaupt verstanden hat was ich will, kann, möchte und werde ich an dieser Stelle nicht bewerten.

              Fakt ist das ich um die "wir schicken Daten frei durchs Web mit einer "Scriptgateway-Lösung" wohl nicht herumkommen werde.

              Gruss
              Dieter

              1. hi,

                Ich soll dem Admin des DB-Servers das Script geben; er will es dann "überprüfen" (wie auch immer dieses aussehen soll) und dieser wird es dann auf dem DB-Server "bereitstellen".
                Bevor ich jetzt geprügelt werde: DAS ist der Originalwortlaut des Admins.

                Ok, lass den machen, er ist für die Policy zuständig und die kann den Zugriff über Port 80 genauso regeln wie über Port 3306.

                Fakt ist das ich um die "wir schicken Daten frei durchs Web mit einer "Scriptgateway-Lösung" wohl nicht herumkommen werde.

                Machen ;)

                POST, Daten in Richtung Server: Ein Perl-Script, was den POST entgegennimmt, kann einen serialisierten Stream direkt aus STDIN lesen (was in PHP nicht machbar ist). Auch was den Serializer betrifft, hier würde ich eine Perl-Lösung bevorzugen, der Perl-Serializer Storable::freeze() arbeitet auf Byte-Ebene, ist damit unabhängig von irgendwelchen Zeichenkodierungen und außerdem sehr performant. Mit Storable::thaw() wird eine Datenstruktur aus dem Stream zurückgewonnen.

                GET, Daten vom Server holen: Inwieweit der PHP-Serializer mit NULL-Werten umgehen kann, weiß ich (noch) nicht, Perl's Storable::freeze() kann das. Auch hier würde ich mit reinen Binaries arbeiten, also eher mit Perl.

                Ansonsten: Baue serverseitig eine Kontrollstruktur für die Parameter und hinterlege dazu klar definierte SQL-Statements, welche die Responses ausliefern. Also keine SQL-Statements als text/plain per HTTP senden ;)

                Viel Erfolg!

                Btw., ich habe für die nächsten Tage auch sowas ähnliches zu machen, aus einer lokkal vorliegenden Datei sind Daten zu parsen, in Records aufzuarbeiten und per HTTP zu übertragen. Ca. 20.000 Records, geschätzte 2..3MB. Das wird ein POST...

                Hotti

                1. Tach!

                  POST, Daten in Richtung Server: Ein Perl-Script, was den POST entgegennimmt, kann einen serialisierten Stream direkt aus STDIN lesen (was in PHP nicht machbar ist).

                  Diese Aussage ist nicht richtig. Aber warum sollte man das wollen? Alles was benötigt wird, kann im Request übertragen werden, also in $_GET oder $_POST gefunden werden.

                  Auch was den Serializer betrifft, hier würde ich eine Perl-Lösung bevorzugen, der Perl-Serializer Storable::freeze() arbeitet auf Byte-Ebene, ist damit unabhängig von irgendwelchen Zeichenkodierungen und außerdem sehr performant. Mit Storable::thaw() wird eine Datenstruktur aus dem Stream zurückgewonnen.

                  Auch hier ist PHP nicht im Nachteil. Der Serializer geht generell von ISO-8859-1 aus, also lässt sich damit auch problemlos UTF-8 übertragen.

                  GET, Daten vom Server holen: Inwieweit der PHP-Serializer mit NULL-Werten umgehen kann, weiß ich (noch) nicht, Perl's Storable::freeze() kann das. Auch hier würde ich mit reinen Binaries arbeiten, also eher mit Perl.

                  PHP hat mit NULL kein Problem, auch nicht mit binären Daten.

                  Ansonsten: Baue serverseitig eine Kontrollstruktur für die Parameter und hinterlege dazu klar definierte SQL-Statements, welche die Responses ausliefern. Also keine SQL-Statements als text/plain per HTTP senden ;)

                  Du solltest seine Anforderungen genauer lesen. Die Statements seien nicht vorhersagbar. Die letzte Empfehlung gilt aber auch so. Ohne SSL-Verbindung würde ich hier nicht arbeiten wollen. Auch eine Absicherung gegen unberechtigten Script-Aufruf ist Pflicht.

                  dedlfix.

              2. hi,

                Fakt ist das ich um die "wir schicken Daten frei durchs Web mit einer "Scriptgateway-Lösung" wohl nicht herumkommen werde.

                Du hast eingangs nach fertigen Scripts oder Libs gefragt. Da ich sowas schon öfter gemacht habe, schreibe ich Dir mal auf, wie sowas gemacht werden kann:

                Stream Up

                Die Artikel Teil 1 und Teil 2 sind noch in Arbeit ;)

                Schönen Sonntag,
                Horst