jogi: fsockopen zu server hinter proxy

Hallo zusammen,

ich versuche eine Verbindung zu einem Server aufzubauen, wobei der Server hinter einem Proxy hängt.
An diesen Server möchte ich dann per POST eine Datei senden:

Das ist mein code ohne Proxy
[PHP]
$fp = fsockopen("ssl://zielserver.com",443,$errstr,$errno);
if(!$fp)
{
    die();
}
else
{
    fputs($fp, "POST zielpfad/servlet HTTP/1.1\r\n");
    fputs($fp, "Host: zielserver.com\r\n");
    fputs($fp, "Authorization: Basic ".$kennung." \r\n");
    fputs($fp, "Content-length: ". strlen($data) ."\r\n");
    fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");
 fputs($fp, "Accept: text/xml\r\n");
 fputs($fp, "SOAPAction: "run"\r\n");
 fputs($fp, "Cache-Control: no-cache\r\n");
 fputs($fp, "Pragma: no-cache\r\n");
    fputs($fp, "Connection: close\r\n\r\n");
    fputs($fp, $data);
}
while(!feof($fp))
{
    $fget = fgets($fp, 128);
    $data .= $fget;
}
fclose($fp);
[/PHP]
Nun befindet sich der zielserver hinter einem proxy-server proxyserver.com

kann mir jemand sagen, wie ich mein script umschreiben muss, damit ich über den proxy zu meinem zielserver komme.

gruß jogi

  1. Hi,

    Nun befindet sich der zielserver hinter einem proxy-server proxyserver.com

    kann mir jemand sagen, wie ich mein script umschreiben muss, damit ich über den proxy zu meinem zielserver komme.

    Tipp: Fuehre eine "normale" Anfrage mit dem FireFox durch, und schau dir bspw. mit FireBug an, welche HTTP-Header genau im Request auftauchen - und vergleiche dann mit deinen bisherigen.

    MfG ChrisB

    --
    "The Internet: Technological marvel of marvels - but if you don't know *what* you're lookin' for on the Internet, it is nothing but a time-sucking vortex from hell."
    1. Hallo!

      Nun befindet sich der zielserver hinter einem proxy-server proxyserver.com

      kann mir jemand sagen, wie ich mein script umschreiben muss, damit ich über den proxy zu meinem zielserver komme.

      Tipp: Fuehre eine "normale" Anfrage mit dem FireFox durch, und schau dir bspw. mit FireBug an, welche HTTP-Header genau im Request auftauchen - und vergleiche dann mit deinen bisherigen.

      Das hilft hier leider nicht, weil die Verbindung mit dem eigentlichen Server TLS-verschlüsselt ablaufen soll (siehe bestehenden Code) und man deswegen am Firebug nicht viel erkennen kann.

      Viele Grüße,
      Christian

  2. Hallo!

    $fp = fsockopen("ssl://zielserver.com",443,$errstr,$errno);

    Du willst offensichtlich Dich mit SSL mit dem Server verbinden. Das Problem: Wenn Du einen HTTP-Proxy dazwischen hast, dann musst Du vorher mit dem Proxy im Klartext reden, um einen HTTP-CONNECT-Aufruf abzusetzen. DANACH musst Du dann die TLS-Verschlüsselung aktivieren. Das heißt aber auch, dass Du das nicht mehr bequem per fsockopen() machen kannst (dort musst Du erst einmal eine normale TCP-Verbindung aufbauen), sondern Du musst den TLS-Handshake erst im Laufe der Verbindung (sobald CONNECT durchgegangen ist) anstoßen. Dafür bietet PHP eine Funktion an, nämlich stream_socket_enable_crypto, die aber erst ab PHP 5.1 funktioniert (unter PHP 5.2.6 würde ich aber aus Sicherheitsgründen sowieso kein PHP einsetzen wollen).

    Hier mal ein Beispiel, wie man das machen kann:

    $proxy_host = 'proxyhost.lan';  
    $proxy_port = 3128;  
      
    $remote_host = 'zielhost.test';  
    $remote_port = 443;  
      
    $fp = fsockopen ("tcp://$proxy_host:$proxy_port", 0, $errstr, $errno);  
    if (!is_resource ($fp)) {  
      // verbindung zum proxy geht nicht  
      throw new Exception ("Could not open connection to proxy server");  
    }  
      
    // CONNECT-request senden  
    fputs ($fp, "CONNECT $remote_host:$remote_port HTTP/1.1\r\n\r\n");  
      
    // antwort einlesen  
    $line = fgets ($fp, 8192);  
    $line = trim ($line);  
    if (substr ($line, 0, 7) != 'HTTP/1.') {  
      fclose ($fp);  
      // ungültige antwort  
      throw new Exception ("Invalid response: $line");  
    }  
    if (substr ($line, 9, 3) != '200') {  
      fclose ($fp);  
      // keinr 200er-Antwort, also fehlgeschlagen  
      throw new Exception ("CONNECT failed: $line");  
    }  
    // solange man keine leerzeile eingelesen hat, einfach neue zeilen  
    // einlesen, Leerzeile markiert Ende des HTTP-Headers und danach  
    // kann's mit TLS losgehen  
    while (trim ($line) != "") {  
      $line = fgets ($fp, 8192);  
    }  
    $res = stream_socket_enable_crypto ($fp, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);  
    if (!$res) {  
      // konnte keinen TLS-Handshake durchführen  
      throw new Exception ("TLS Handshake failed");  
    }  
      
    // Und JETZT über die Verbindung ganz normal den HTTP-Request absetzen  
    // und die Antwort auslesen, so wie vorher  
      
    fputs ($fp, "GET / HTTP/1.1\r\n");  
    // etc.
    

    -------- schnipp ---------------

    Im Falle von einer Klartextverbindung (d.h. **KEIN** SSL/TLS über den Proxy) hättest Du das ganze VIEL einfacher:

    Im Klartextfall musst Du Dich nämlich lediglich mit dem Proxy verbinden statt mit dem richtigen Server und den Namen des richtigen Servers in dem Request verarbeiten, d.h.

    Vereinfachter voriger Code (Klartext-Fall!):

    $fp = fsockopen ('tcp://zielserver.test:80', 0, ...);  
    fputs ($fp, "POST /bla HTTP/1.1\r\n");
    

    Vereinfachter neuer Code (Klartext-Fall!):

    $fp = fsockopen ('tcp://proxyserver.lan:3128', 0, ...);  
    fputs ($fp, "POST http://zielserver.test/bla HTTP/1.1\r\n");
    

    Viele Grüße,
    Christian