/
DATKAI
/
ITCUP
Обзор
Документация
Войти
/
DATKAI
/
ITCUP
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
main
app/Models/VpnClient.php
118 строк
3 KB
ITCUP Admin
feat(vpn): этап 3 — маршрутизация site-to-site + этап 4 — мониторинг
22 апр 2026, 08:13
22 апр 2026, 08:13
96a4d88
Код
Авторство
О чём код?
<?php namespace App\Models; use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; class VpnClient extends Model { protected $fillable = [ 'vpn_service_id', 'name', 'user_id', 'asset_id', 'assigned_ip', 'credentials', 'custom_config', 'is_active', 'last_connected_at', 'notes', // routing 'lan_subnets', 'peer_access_ids', // monitoring 'last_handshake_at', 'rx_bytes', 'tx_bytes', 'last_endpoint', ]; protected $casts = [ 'credentials' => 'encrypted:array', 'custom_config' => 'encrypted', 'is_active' => 'boolean', 'last_connected_at' => 'datetime', 'last_handshake_at' => 'datetime', 'lan_subnets' => 'array', 'peer_access_ids' => 'array', 'rx_bytes' => 'integer', 'tx_bytes' => 'integer', ]; public function service(): BelongsTo { return $this->belongsTo(VpnService::class, 'vpn_service_id'); } public function user(): BelongsTo { return $this->belongsTo(User::class); } public function asset(): BelongsTo { return $this->belongsTo(Asset::class); } /** * Вернуть список подсетей, доступ к которым имеет этот клиент: * туннельный адрес + свой lan + чужие lan (из peer_access_ids). * * Используется в клиентском .conf (AllowedIPs) чтобы клиент знал куда * слать трафик через туннель. * * @return string[] */ public function allowedSubnets(): array { $subnets = []; // Туннельная подсеть целиком — чтобы видеть других peer-ов через hub if (!empty($this->service?->subnet)) { $subnets[] = $this->service->subnet; } // LAN других peer-ов к которым разрешён доступ $accessIds = $this->peer_access_ids ?? []; if (!empty($accessIds)) { $peers = VpnClient::whereIn('id', $accessIds)->get(); foreach ($peers as $p) { foreach ((array) ($p->lan_subnets ?? []) as $net) { $subnets[] = $net; } } } return array_values(array_unique(array_filter($subnets))); } /** * AllowedIPs которые hub должен прописать для этого peer-а в своём [Peer] блоке. * Это туннельный IP peer-а + его LAN — чтобы hub знал куда слать ответный трафик. * * @return string[] */ public function hubRoutableSubnets(): array { $subnets = []; if ($this->assigned_ip) { $subnets[] = str_contains($this->assigned_ip, '/') ? $this->assigned_ip : $this->assigned_ip . '/32'; } foreach ((array) ($this->lan_subnets ?? []) as $net) { $subnets[] = $net; } return array_values(array_unique(array_filter($subnets))); } public function isHandshakeRecent(int $seconds = 180): bool { return $this->last_handshake_at && $this->last_handshake_at->diffInSeconds(now()) <= $seconds; } }