Start · Sprachen · PHP · Referenz · ssh2_tunnel

ssh2_tunnel

Funktion

Öffnet einen TCP-Tunnel über eine bestehende SSH-Verbindung zu einem entfernten Zielhost.

seit PHP 0.9.0 Kategorie: http

Signatur

ssh2_tunnel(resource $session, string $host, int $port): resource|false

Beschreibung

ssh2_tunnel() nutzt eine bestehende SSH-Sitzung, um einen direkten TCP-Kanal (Direct TCP/IP Channel) zu einem Zielhost und -port aufzubauen, der vom SSH-Server aus erreichbar ist. Dieser Mechanismus wird auch als SSH-Portweiterleitung oder -Tunneling bezeichnet.

Die Funktion ist besonders nützlich, wenn auf Dienste zugegriffen werden soll, die sich hinter einer Firewall befinden oder nur vom SSH-Server aus erreichbar sind – beispielsweise interne Datenbanken, HTTP-Dienste in privaten Netzwerken oder andere TCP-basierte Dienste. Der gesamte Datenverkehr wird dabei verschlüsselt über die SSH-Verbindung übertragen.

Der zurückgegebene Stream kann wie ein normaler PHP-Netzwerk-Stream verwendet werden – also mit Funktionen wie fread(), fwrite() und fclose(). Das eignet sich beispielsweise dafür, einen rohen HTTP-Request über den Tunnel zu senden oder einen anderen TCP-Dienst anzusprechen.

Voraussetzung ist, dass die PECL-Erweiterung ssh2 installiert ist und eine aktive SSH-Sitzung (via ssh2_connect() und anschließender Authentifizierung) vorliegt.

Parameter

Name Typ Default Beschreibung
$session Pflicht resource Eine aktive SSH-Sitzungsressource, die zuvor mit ssh2_connect() erstellt und authentifiziert wurde.
$host Pflicht string Der Hostname oder die IP-Adresse des Zielrechners, zu dem der Tunnel geöffnet werden soll. Dieser Host wird vom SSH-Server aus aufgelöst und verbunden.
$port Pflicht int Der TCP-Port auf dem Zielhost, zu dem der Tunnel aufgebaut werden soll – z. B. 80 für HTTP oder 3306 für MySQL.

Rückgabewert

Typ
resource|false
Beschreibung
Gibt eine Stream-Ressource zurück, über die bidirektional Daten gesendet und empfangen werden können. Im Fehlerfall (z. B. wenn der SSH-Server die Verbindung ablehnt) wird false zurückgegeben.

Beispiele

HTTP-Anfrage über SSH-Tunnel senden

<?php
// SSH-Verbindung aufbauen
$session = ssh2_connect('ssh.example.com', 22);
if (!$session) {
    die('SSH-Verbindung fehlgeschlagen.');
}

// Authentifizierung mit Benutzername und Passwort
if (!ssh2_auth_password($session, 'username', 'geheimesPasswort')) {
    die('SSH-Authentifizierung fehlgeschlagen.');
}

// Tunnel zum internen HTTP-Dienst öffnen (nur vom SSH-Server erreichbar)
$tunnel = ssh2_tunnel($session, 'intern.example.local', 80);
if (!$tunnel) {
    die('Tunnel konnte nicht geöffnet werden.');
}

// Rohen HTTP-Request über den Tunnel senden
$request = "GET / HTTP/1.1\r\nHost: intern.example.local\r\nConnection: close\r\n\r\n";
fwrite($tunnel, $request);

// Antwort lesen
$response = '';
while (!feof($tunnel)) {
    $response .= fread($tunnel, 4096);
}

fclose($tunnel);
echo $response;
HTTP/1.1 200 OK Content-Type: text/html; charset=UTF-8 ...(Antwort des internen Servers)

Tunnel zu einem internen MySQL-Port prüfen

<?php
$session = ssh2_connect('jumphost.example.com', 22);
if (!$session || !ssh2_auth_pubkey_file($session, 'admin', '/home/admin/.ssh/id_rsa.pub', '/home/admin/.ssh/id_rsa')) {
    die('SSH-Verbindung oder Authentifizierung fehlgeschlagen.');
}

// Tunnel zur internen Datenbank (nur vom Jumphost aus erreichbar)
$tunnel = ssh2_tunnel($session, 'db.intern.example.com', 3306);
if ($tunnel) {
    echo "Tunnel zu MySQL erfolgreich geöffnet." . PHP_EOL;
    // Ersten Bytes des MySQL-Handshakes lesen
    $banner = fread($tunnel, 64);
    echo "Empfangene Daten: " . bin2hex($banner) . PHP_EOL;
    fclose($tunnel);
} else {
    echo "Tunnel konnte nicht geöffnet werden." . PHP_EOL;
}
Tunnel zu MySQL erfolgreich geöffnet. Empfangene Daten: 3a00000a382e302e32382...

// Wichtig · Fallstricke

Sicherheitshinweise:

  • Stellen Sie sicher, dass der SSH-Server (auf Serverseite) das Direct-TCP/IP-Forwarding erlaubt (AllowTcpForwarding yes in der sshd_config). Andernfalls schlägt ssh2_tunnel() fehl.
  • Vermeiden Sie es, Zugangsdaten (Passwörter, private Schlüssel) im Klartext im Code zu hinterlegen. Nutzen Sie Umgebungsvariablen oder sichere Secrets-Manager.
  • Der SSH-Server agiert als Relay: Der Zielhost $host wird vom SSH-Server aus aufgelöst, nicht vom lokalen PHP-System. Dies kann zur Umgehung lokaler DNS-Sperren oder Firewalls verwendet werden – stellen Sie sicher, dass dies erwünscht ist.
  • ssh2_tunnel() gehört zur PECL-Erweiterung ssh2 und ist nicht in der PHP-Standardinstallation enthalten. Sie muss explizit installiert werden (pecl install ssh2).
  • Der Stream ist im Blocking-Modus. Für nicht-blockierende Kommunikation kann stream_set_blocking($tunnel, false) verwendet werden.