Signatur
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
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;
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;
}
// Wichtig · Fallstricke
Sicherheitshinweise:
- Stellen Sie sicher, dass der SSH-Server (auf Serverseite) das Direct-TCP/IP-Forwarding erlaubt (
AllowTcpForwarding yesin dersshd_config). Andernfalls schlägtssh2_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
$hostwird 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-Erweiterungssh2und 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.