39 lines
1.1 KiB
PHP
39 lines
1.1 KiB
PHP
<?php
|
|
|
|
namespace App\Support\Ssh;
|
|
|
|
use App\Models\Server;
|
|
use phpseclib3\Net\SSH2;
|
|
use RuntimeException;
|
|
|
|
/**
|
|
* TOFU (trust-on-first-use) host-key pinning. phpseclib verifies the key-exchange
|
|
* signature but does NOT pin the server's host key, so a MITM presenting its own
|
|
* valid key would be accepted. We record the host key on first connect and refuse
|
|
* the connection on any later mismatch.
|
|
*/
|
|
trait VerifiesHostKey
|
|
{
|
|
private function verifyHostKey(SSH2 $conn, Server $server): void
|
|
{
|
|
$hostKey = $conn->getServerPublicHostKey();
|
|
|
|
if ($hostKey === false) {
|
|
throw new RuntimeException("Host-Key von {$server->name} ({$server->ip}) nicht lesbar — Verbindung abgebrochen.");
|
|
}
|
|
|
|
$known = (string) ($server->ssh_host_key ?? '');
|
|
|
|
if ($known !== '') {
|
|
if (! hash_equals($known, $hostKey)) {
|
|
throw new RuntimeException("Host-Key-Mismatch fuer {$server->name} ({$server->ip}) — moegliches MITM. Verbindung abgebrochen.");
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
// trust on first use
|
|
$server->forceFill(['ssh_host_key' => $hostKey])->save();
|
|
}
|
|
}
|