debug = false; // Connect ke MikroTik if ($mikrotik->connect2('manjapro.net', 'apiapkmanjapro', 'apiapkmanjapro123321', '2887')) { // Ambil semua remote-address yang sudah dipakai $secrets = $mikrotik->comm('/ppp/secret/print', [ "?local-address" => "172.18.1.100" ]); $maxIp = 0; foreach ($secrets as $secret) { if (isset($secret['remote-address']) && filter_var($secret['remote-address'], FILTER_VALIDATE_IP)) { $ipParts = explode('.', $secret['remote-address']); if (count($ipParts) == 4 && $ipParts[0] == '172' && $ipParts[1] == '18' && $ipParts[2] == '1') { $lastOctet = (int)$ipParts[3]; if ($lastOctet > $maxIp) { $maxIp = $lastOctet; } } } } // Hitung remote-address baru $nextIp = $maxIp + 1; $remoteAddress = "172.18.1." . $nextIp; // Local address (bisa fix atau ambil dari pool) $localAddress = "172.18.1.100"; // ============================== // Ambil semua dst-port yang sudah digunakan // ============================== $natRules = $mikrotik->comm('/ip/firewall/nat/print'); $usedPorts = []; foreach ($natRules as $rule) { if (isset($rule['dst-port'])) { $ports = explode(',', $rule['dst-port']); foreach ($ports as $p) { $usedPorts[] = (int)$p; } } } // Cari 2 port yang bebas mulai dari 2000 $startPort = 200; $freePorts = []; while (count($freePorts) < 2) { if (!in_array($startPort, $usedPorts)) { $freePorts[] = $startPort; } $startPort++; if ($startPort > 9999) { // Batas port TCP break; // Hindari infinite loop } } if (count($freePorts) < 2) { return [ 'status' => false, 'message' => 'Tidak ada 2 port bebas yang tersedia' ]; } $port1 = $freePorts[0]; $port2 = $freePorts[1]; // ============================== // Generate user/pass // ============================== // $secretUser = strtolower(preg_replace('/[^a-z0-9]/i', '', substr($Secret, 0, 12))) . "@manjapro.net"; $prefix = strtolower(preg_replace('/[^a-z0-9]/i', '', substr($Secret, 0, 10))); $secretUser = $prefix . rand(1000, 9999) . "@manjapro.net"; $secretPass = strtolower(substr(md5($secretUser), 0, 12)); $nasSecret = substr(md5($secretUser), 0, 20); // Tambahkan PPP secret $add = $mikrotik->comm('/ppp/secret/add', [ "name" => $secretUser, "password" => $secretPass, "profile" => "default-encryption", "local-address" => $localAddress, "remote-address" => $remoteAddress, "service" => "any", "comment" => $Secret ]); // Tambahkan 2 firewall NAT rules $nat1 = $mikrotik->comm('/ip/firewall/nat/add', [ "chain" => "dstnat", "dst-address-list" => "IP-Public", "dst-port" => $port1, "protocol" => "tcp", "action" => "dst-nat", "to-addresses" => $remoteAddress, "to-ports" => $port1, "comment" => $Secret ]); $nat2 = $mikrotik->comm('/ip/firewall/nat/add', [ "chain" => "dstnat", "dst-address-list" => "IP-Public", "dst-port" => $port2, "protocol" => "tcp", "action" => "dst-nat", "to-addresses" => $remoteAddress, "to-ports" => $port2, "comment" => $Secret ]); $mikrotik->disconnect(); // Siapkan data response $data = [ "name" => $secretUser, "password" => $secretPass, "profile" => "default-encryption", "local-address" => $localAddress, "remote-address" => $remoteAddress, "service" => "any", "nas_secret" => $nasSecret, "nasgroupname" => $nasGroup, "port-api" => $port1, "port-remote" => $port2 ]; return json_encode( [ 'status' => true, 'message' => 'PPP secret dan NAT berhasil dibuat', 'data' => $data ] ); } else { return json_encode ([ 'status' => false, 'message' => 'Gagal terhubung ke MikroTik' ]); } } public function deleteTunnel($Data) { $data = json_decode($Data); // Validasi data yang diterima if (!isset($data->data->{'name'}) || !isset($data->data->{'port-api'}) || !isset($data->data->{'port-remote'})) { http_response_code(400); echo json_encode([ 'success' => false, 'message' => "Data tidak lengkap untuk menghapus tunnel" ]); return; } $name = $data->data->{'name'}; $portApi = $data->data->{'port-api'}; $portRemote = $data->data->{'port-remote'}; $mikrotik = new RouterosAPI(); $mikrotik->debug = false; // Connect ke MikroTik if ($mikrotik->connect2('manjapro.net', 'apiapkmanjapro', 'apiapkmanjapro123321', 2887)) { try { // Hapus PPP Secret $pppSecrets = $mikrotik->comm('/ppp/secret/print', [ "?name" => $name ]); if (!empty($pppSecrets)) { foreach ($pppSecrets as $secret) { if (isset($secret['.id'])) { $mikrotik->comm('/ppp/secret/remove', [ ".id" => $secret['.id'] ]); } } } // Hapus NAT untuk port-api $natApi = $mikrotik->comm('/ip/firewall/nat/print', [ "?dst-port" => $portApi ]); if (!empty($natApi)) { foreach ($natApi as $rule) { if (isset($rule['.id'])) { $mikrotik->comm('/ip/firewall/nat/remove', [ ".id" => $rule['.id'] ]); } } } // Hapus NAT untuk port-remote $natRemote = $mikrotik->comm('/ip/firewall/nat/print', [ "?dst-port" => $portRemote ]); if (!empty($natRemote)) { foreach ($natRemote as $rule) { if (isset($rule['.id'])) { $mikrotik->comm('/ip/firewall/nat/remove', [ ".id" => $rule['.id'] ]); } } } $mikrotik->disconnect(); // Kirim respon sukses http_response_code(200); echo json_encode([ 'success' => true, 'message' => "Tunnel '$name' berhasil dihapus" ]); } catch (Exception $e) { $mikrotik->disconnect(); http_response_code(500); echo json_encode([ 'success' => false, 'message' => "Gagal menghapus tunnel: " . $e->getMessage() ]); } } else { http_response_code(500); echo json_encode([ 'success' => false, 'message' => "Gagal koneksi ke MikroTik" ]); } } } // <===== CONTOH =====> // $tunnel = new CreateTunnel(); // $result = $tunnel->addSecret('user123', 'pass123'); // if ($result['status']) { // echo "✅ Berhasil: " . $result['remote-address']; // } else { // echo "❌ Gagal: " . $result['message']; // }