CluPilotCloud/app/Services/Wireguard/LocalWireguardHub.php

55 lines
1.6 KiB
PHP

<?php
namespace App\Services\Wireguard;
use App\Models\Host;
use Illuminate\Support\Facades\Process;
use Illuminate\Support\Str;
use RuntimeException;
/**
* Real hub on the CluPilot VM. Allocates the next free address in the configured
* subnet and manages peers with `wg`. Watch-item: the app runs in a container, so
* the wg interface must be reachable from here (host network / mounted config);
* verified on the real VM, not in the mocked test-suite.
*/
class LocalWireguardHub implements WireguardHub
{
public function allocateIp(): string
{
$used = Host::query()->whereNotNull('wg_ip')->pluck('wg_ip')->all();
$prefix = Str::beforeLast(config('provisioning.wireguard.subnet', '10.66.0.0/24'), '.');
for ($octet = 2; $octet <= 254; $octet++) {
$ip = "{$prefix}.{$octet}";
if (! in_array($ip, $used, true)) {
return $ip;
}
}
throw new RuntimeException('WireGuard management subnet exhausted.');
}
public function addPeer(string $publicKey, string $ip): void
{
Process::run(['wg', 'set', 'wg0', 'peer', $publicKey, 'allowed-ips', $ip.'/32'])->throw();
Process::run('wg-quick save wg0');
}
public function removePeer(string $publicKey): void
{
Process::run(['wg', 'set', 'wg0', 'peer', $publicKey, 'remove'])->throw();
Process::run('wg-quick save wg0');
}
public function endpoint(): string
{
return (string) config('provisioning.wireguard.endpoint');
}
public function publicKey(): string
{
return (string) config('provisioning.wireguard.hub_public_key');
}
}