paginate(15); return view('vpns.index', compact('vpns')); } // Handle Add Form Submission public function store(Request $request) { $validated = $request->validate([ 'partner_name' => 'required|string|max:255', 'status' => 'required|in:Active,Inactive', 'local_ip' => 'required|ip', 'peer_ip' => 'required|ip', 'encryption_domain_local' => 'nullable|string|max:255', 'encryption_domain_remote' => 'nullable|string|max:255', 'preshared_key' => 'required|string', 'local_device' => 'nullable|string|max:255', 'peer_device' => 'nullable|string|max:255', 'ike_version' => 'required|integer', 'phase1_encryption' => 'required|string|max:50', 'phase1_hash' => 'required|string|max:50', 'phase1_dh_group' => 'required|string|max:50', 'phase1_lifetime' => 'required|integer', 'phase2_encryption' => 'required|string|max:50', 'phase2_hash' => 'required|string|max:50', 'phase2_dh_group' => 'nullable|string|max:50', 'phase2_lifetime' => 'required|integer', 'pfs_enabled' => 'boolean', ]); VpnConfig::create($validated); return response()->json(['success' => true, 'message' => 'VPN configuration added successfully.']); } // Fetch data for the Edit Modal public function show($id) { $vpn = VpnConfig::findOrFail($id); // Hide the pre-shared key from being sent back in the JSON response for security $vpn->makeHidden('preshared_key'); return response()->json($vpn); } // Handle Edit Form Submission public function update(Request $request, $id) { $vpn = VpnConfig::findOrFail($id); $validated = $request->validate([ 'partner_name' => 'required|string|max:255', 'status' => 'required|in:Active,Inactive', 'local_ip' => 'required|ip', 'peer_ip' => 'required|ip', 'encryption_domain_local' => 'nullable|string|max:255', 'encryption_domain_remote' => 'nullable|string|max:255', 'preshared_key' => 'nullable|string', 'local_device' => 'nullable|string|max:255', 'peer_device' => 'nullable|string|max:255', 'ike_version' => 'required|integer', 'phase1_encryption' => 'required|string|max:50', 'phase1_hash' => 'required|string|max:50', 'phase1_dh_group' => 'required|string|max:50', 'phase1_lifetime' => 'required|integer', 'phase2_encryption' => 'required|string|max:50', 'phase2_hash' => 'required|string|max:50', 'phase2_dh_group' => 'nullable|string|max:50', 'phase2_lifetime' => 'required|integer', 'pfs_enabled' => 'boolean', ]); // If the PSK field is empty, remove it so we don't overwrite the existing key if (empty($validated['preshared_key'])) { unset($validated['preshared_key']); } $vpn->update($validated); return response()->json(['success' => true, 'message' => 'VPN configuration updated successfully.']); } // Export the company's global standard VPN parameters public function downloadStandardTemplate() { $template = "=================================================\n"; $template .= " Click Mobile VPN Configuration Parameters\n"; $template .= "=================================================\n\n"; $template .= "! Phase 1 (IKE / ISAKMP)\n"; $template .= " Encryption Algorithm: AES-256\n"; $template .= " Hash Algorithm: SHA-256\n"; $template .= " Authentication Method: Pre-Shared Key (PSK)\n"; $template .= " Diffie-Hellman Group: Group 14\n"; $template .= " Lifetime: 86400 seconds\n\n"; $template .= "! Phase 2 (IPsec)\n"; $template .= " Protocol: ESP\n"; $template .= " Encryption Algorithm: AES-256\n"; $template .= " Hash Algorithm: SHA-256\n"; $template .= " Perfect Forward Secrecy (PFS): Group 14\n"; $template .= " Lifetime: 3600 seconds\n\n"; $template .= "! Gateway Details\n"; $template .= " Our Public Gateway IP: [216.55.137.19]\n"; $template .= " Our Encryption Domain: [10.199.0.0/24]\n"; return response($template) ->header('Content-Type', 'text/plain') ->header('Content-Disposition', 'attachment; filename="standard_vpn_parameters.txt"'); } // Fetch data to populate the Partner Export Modal public function generateTemplate($id) { $vpn = VpnConfig::findOrFail($id); $template = "=================================================\n"; $template .= " VPN Configuration for Partner: {$vpn->partner_name}\n"; $template .= "=================================================\n\n"; $template .= "! Phase 1 (IKE)\n"; $template .= "crypto isakmp policy 10\n"; $template .= " encr aes 256\n"; $template .= " hash sha256\n"; $template .= " authentication pre-share\n"; $template .= " group 14\n"; $template .= "crypto isakmp key {$vpn->preshared_key} address {$vpn->local_ip}\n\n"; $template .= "! Phase 2 (IPsec)\n"; $template .= "crypto ipsec transform-set TS-AES256-SHA256 esp-aes 256 esp-sha256-hmac\n"; $template .= "crypto map VPNMAP 10 ipsec-isakmp\n"; $template .= " set peer {$vpn->local_ip}\n"; $template .= " set transform-set TS-AES256-SHA256\n"; $template .= " match address 100\n\n"; $template .= "! Access Control List (Encryption Domains)\n"; $template .= "access-list 100 permit ip {$vpn->encryption_domain_remote} {$vpn->encryption_domain_local}\n"; return response()->json(['template' => $template, 'partner_name' => $vpn->partner_name]); } // Process the edited text and force a file download public function download(Request $request) { $request->validate([ 'config_content' => 'required|string', 'partner_name' => 'required|string', ]); $filename = str_replace(' ', '_', strtolower($request->partner_name)) . '_vpn_config.txt'; return response($request->config_content) ->header('Content-Type', 'text/plain') ->header('Content-Disposition', "attachment; filename=\"{$filename}\""); } }