"use client" import { useMemo, useState } from "react" import { PageHeader } from "@/components/page-header" import { servers } from "@/lib/data" import type { WireGuardInterface, WireGuardPeer } from "@/lib/data" import { Flag } from "@/components/flag" import { Card, CardContent } from "@/components/ui/card" import { Button } from "@/components/ui/button" import { cn } from "@/lib/utils" import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetDescription, SheetFooter, SheetClose, } from "@/components/ui/sheet" import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, } from "@/components/ui/dropdown-menu" import { ShieldCheckIcon, PlusIcon, SearchIcon, KeyRoundIcon, ChevronDownIcon, ChevronRightIcon, MoreHorizontalIcon, PencilIcon, Trash2Icon, PowerIcon, CopyIcon, CheckIcon, CodeXmlIcon, UsersIcon, ActivityIcon, ArrowDownIcon, ArrowUpIcon, } from "lucide-react" // ─── collect all WireGuard interfaces from all servers ──────────────────────── interface WgIfaceWithServer extends WireGuardInterface { serverId: string serverName: string serverCountry: string } function collectInterfaces(): WgIfaceWithServer[] { const result: WgIfaceWithServer[] = [] for (const srv of servers) { for (const wg of srv.wireGuardIfaces ?? []) { result.push({ ...wg, serverId: srv.id, serverName: srv.name, serverCountry: srv.country, }) } } return result } // ─── helpers ────────────────────────────────────────────────────────────────── function fmtBytes(n: number | undefined): string { if (!n) return "—" if (n >= 1_000_000_000) return `${(n / 1_000_000_000).toFixed(1)} ГБ` if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)} МБ` if (n >= 1_000) return `${(n / 1_000).toFixed(0)} КБ` return `${n} Б` } function truncKey(key: string): string { if (key.length <= 20) return key return `${key.slice(0, 8)}…${key.slice(-8)}` } // ─── RSC generator ──────────────────────────────────────────────────────────── function generateWgRsc(iface: WgIfaceWithServer): string { const lines: string[] = [] lines.push(`# WireGuard — ${iface.name} · ${iface.serverName}`) lines.push(`# RouterOS 7.x`) lines.push(``) lines.push(`/interface wireguard add \\`) lines.push(` name=${iface.name} \\`) lines.push(` listen-port=${iface.listenPort} \\`) lines.push(` mtu=${iface.mtu} \\`) if (iface.comment) lines.push(` comment="${iface.comment}" \\`) if (!iface.enabled) lines.push(` disabled=yes \\`) lines.push(``) for (const p of iface.peers) { lines.push(`/interface wireguard peers add \\`) lines.push(` interface=${iface.name} \\`) lines.push(` public-key="${p.publicKey}" \\`) lines.push(` allowed-address=${p.allowedIps.join(",")} \\`) if (p.endpoint) lines.push(` endpoint-address=${p.endpoint.split(":")[0]} \\`) if (p.endpoint) lines.push(` endpoint-port=${p.endpoint.split(":")[1] ?? "13231"} \\`) if (p.persistent) lines.push(` persistent-keepalive=25 \\`) if (p.comment) lines.push(` comment="${p.comment}" \\`) lines.push(``) } return lines.join("\n") } // ─── Peer row ───────────────────────────────────────────────────────────────── function PeerRow({ peer }: { peer: WireGuardPeer }) { return (
Порт
{iface.listenPort}
MTU
{iface.mtu}
Пиров
{onlinePeers} /{iface.peers.length}
{code.split("\n").map((line, i) => {
const isComment = line.startsWith("#")
const isCmd = line.trimStart().startsWith("/interface")
const isParam = /^\s+[a-z]/.test(line)
return (
{line}{"\n"}
)
})}
{s.label}
{s.value}
WireGuard — рекомендуемый туннельный протокол в RouterOS 7.x
Доступен с RouterOS 7.1+. Более высокая производительность и безопасность по сравнению с GRE+IPsec.
Ключи генерируются командой /interface/wireguard/print.
Нет WireGuard интерфейсов
Добавьте первый интерфейс или проверьте поиск
RouterOS 7 · /interface wireguard — быстрые команды
{b.title}
{b.lines.join("\n")}