VpnManager.php 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. <?php
  2. namespace App\Services;
  3. use Illuminate\Support\Facades\Storage;
  4. use Illuminate\Support\Facades\Crypt;
  5. use Illuminate\Support\Facades\Log;
  6. use Illuminate\Support\Facades\Schema;
  7. class VpnManager
  8. {
  9. private $configPath = 'scripts/vpn-config.conf';
  10. private $scriptPath = 'scripts/vpn-connect.sh';
  11. public function updateCredentials($username, $password, $server)
  12. {
  13. try {
  14. $configContent = "# Configurazione VPN - storage/scripts/vpn-config.conf\n";
  15. $configContent .= "# ATTENZIONE: Questo file deve avere permessi 600\n\n";
  16. $configContent .= "VPN_USERNAME=\"{$username}\"\n";
  17. $configContent .= "VPN_PASSWORD=\"{$password}\"\n";
  18. $configContent .= "VPN_SERVER=\"{$server}\"\n";
  19. Storage::put($this->configPath, $configContent);
  20. $fullPath = storage_path( $this->configPath);
  21. chmod($fullPath, 0600);
  22. Log::info('Credenziali VPN aggiornate con successo');
  23. return true;
  24. } catch (\Exception $e) {
  25. Log::error('Errore nell\'aggiornamento delle credenziali VPN: ' . $e->getMessage());
  26. return false;
  27. }
  28. }
  29. public function getVpnStatus($forceRefresh = false)
  30. {
  31. try {
  32. if ($forceRefresh) {
  33. return $this->syncStatusWithSystem();
  34. }
  35. if (!Schema::hasTable('vpn_status')) {
  36. Log::warning('Tabella vpn_status non esiste');
  37. return 'disconnected';
  38. }
  39. $status = \DB::table('vpn_status')->first();
  40. if (!$status) {
  41. return $this->syncStatusWithSystem();
  42. }
  43. return $status->status;
  44. } catch (\Exception $e) {
  45. Log::error('Errore nel recupero dello stato VPN: ' . $e->getMessage());
  46. return 'disconnected';
  47. }
  48. }
  49. public function getLastUpdate()
  50. {
  51. try {
  52. if (!Schema::hasTable('vpn_status')) {
  53. return now();
  54. }
  55. $status = \DB::table('vpn_status')->first();
  56. return $status ? $status->last_update : now();
  57. } catch (\Exception $e) {
  58. Log::error('Errore nel recupero dell\'ultimo aggiornamento VPN: ' . $e->getMessage());
  59. return now();
  60. }
  61. }
  62. public function checkRealVpnStatus()
  63. {
  64. try {
  65. // Esegui il comando per verificare lo stato reale
  66. $output = [];
  67. $returnVar = 0;
  68. exec('/opt/cisco/anyconnect/bin/vpn state 2>&1', $output, $returnVar);
  69. $statusText = implode(' ', $output);
  70. Log::info('VPN real status check', [
  71. 'output' => $output,
  72. 'return_var' => $returnVar,
  73. 'status_text' => $statusText
  74. ]);
  75. // Determina lo stato basandosi sull'output
  76. if (
  77. strpos($statusText, 'state: Connected') !== false ||
  78. strpos($statusText, 'Connected') !== false
  79. ) {
  80. return 'connected';
  81. } elseif (
  82. strpos($statusText, 'Disconnected') !== false ||
  83. strpos($statusText, 'state: Disconnected') !== false
  84. ) {
  85. return 'disconnected';
  86. } else {
  87. return 'unknown';
  88. }
  89. } catch (\Exception $e) {
  90. Log::error('Error checking real VPN status: ' . $e->getMessage());
  91. return 'error';
  92. }
  93. }
  94. public function syncStatusWithSystem()
  95. {
  96. try {
  97. $realStatus = $this->checkRealVpnStatus();
  98. \DB::table('vpn_status')->updateOrInsert(
  99. ['id' => 1],
  100. [
  101. 'status' => $realStatus,
  102. 'last_update' => now(),
  103. 'updated_at' => now(),
  104. ]
  105. );
  106. Log::info('VPN status synced with system', [
  107. 'real_status' => $realStatus
  108. ]);
  109. return $realStatus;
  110. } catch (\Exception $e) {
  111. Log::error('Error syncing VPN status: ' . $e->getMessage());
  112. return 'error';
  113. }
  114. }
  115. public function connectVpn()
  116. {
  117. try {
  118. $currentStatus = $this->checkRealVpnStatus();
  119. if ($currentStatus === 'connected') {
  120. Log::info('VPN already connected, no action needed');
  121. return true;
  122. }
  123. $scriptPath = storage_path($this->scriptPath);
  124. $configPath = storage_path($this->configPath);
  125. // Check if both script and config exist
  126. if (!file_exists($scriptPath)) {
  127. Log::error('Script VPN non trovato: ' . $scriptPath);
  128. return false;
  129. }
  130. if (!file_exists($configPath)) {
  131. Log::error('Config VPN non trovato: ' . $configPath);
  132. return false;
  133. }
  134. // Make sure script is executable
  135. $this->makeScriptExecutable();
  136. // Execute the script and capture output
  137. $command = "timeout 60 bash {$scriptPath} 2>&1";
  138. exec($command, $output, $returnVar);
  139. Log::info('Comando VPN connect eseguito', [
  140. 'command' => $command,
  141. 'output' => $output,
  142. 'return_var' => $returnVar
  143. ]);
  144. // Wait a moment and check status
  145. sleep(5);
  146. $attempts = 0;
  147. $maxAttempts = 12; // 1 minute total (5 seconds * 12)
  148. while ($attempts < $maxAttempts) {
  149. $newStatus = $this->checkRealVpnStatus();
  150. if ($newStatus === 'connected') {
  151. $this->syncStatusWithSystem();
  152. Log::info('VPN connection successful after ' . ($attempts + 1) . ' attempts');
  153. return true;
  154. }
  155. sleep(5);
  156. $attempts++;
  157. }
  158. Log::warning('VPN connection timeout or failed', [
  159. 'final_status' => $this->checkRealVpnStatus(),
  160. 'attempts' => $attempts
  161. ]);
  162. return false;
  163. } catch (\Exception $e) {
  164. Log::error('Errore nell\'esecuzione del comando VPN connect: ' . $e->getMessage());
  165. return false;
  166. }
  167. }
  168. public function disconnectVpn()
  169. {
  170. try {
  171. $command = "/opt/cisco/anyconnect/bin/vpn disconnect > /dev/null 2>&1 &";
  172. exec($command, $output, $returnVar);
  173. \DB::table('vpn_status')->updateOrInsert(
  174. ['id' => 1],
  175. [
  176. 'status' => 'disconnected',
  177. 'last_update' => now(),
  178. 'updated_at' => now(),
  179. ]
  180. );
  181. Log::info('Comando VPN disconnect eseguito', [
  182. 'command' => $command,
  183. 'return_var' => $returnVar
  184. ]);
  185. return true;
  186. } catch (\Exception $e) {
  187. Log::error('Errore nell\'esecuzione del comando VPN disconnect: ' . $e->getMessage());
  188. return false;
  189. }
  190. }
  191. public function makeScriptExecutable()
  192. {
  193. try {
  194. $fullPath = storage_path($this->scriptPath);
  195. chmod($fullPath, 0755);
  196. return true;
  197. } catch (\Exception $e) {
  198. Log::error('Errore nell\'impostazione dei permessi script: ' . $e->getMessage());
  199. return false;
  200. }
  201. }
  202. }