fsockopen zu server hinter proxy
jogi
- php
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
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
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
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