Docker images / prepare-release (push) Successful in 8s
Docker images / backend-image (push) Successful in 1m39s
Docker images / frontend-image (push) Successful in 2m56s
Docker images / notify-webhook (push) Skipped
Docker images / updater-image (push) Successful in 53s
Docker images / publish-release (push) Successful in 10s
Added comprehensive support for managing WireGuard interfaces, including CRUD operations and peer management. Updated permissions to include access control for WireGuard routes. Enhanced the UI components to display and interact with WireGuard configurations, improving user experience and functionality. Introduced new tests for WireGuard-related functionalities to ensure reliability.
826 lines
41 KiB
TypeScript
826 lines
41 KiB
TypeScript
export type ServerStatus = "online" | "offline" | "degraded"
|
||
export type ServerType = "jump-host" | "exit-node" | "home-router"
|
||
|
||
export interface WanUplink {
|
||
id: string
|
||
name: string // "WAN1-RT"
|
||
isp: string // "Rostelecom"
|
||
iface: string // "ether1"
|
||
ip: string // external IP
|
||
maxDl: number // Mbps
|
||
maxUl: number // Mbps
|
||
}
|
||
|
||
// ─── WireGuard ───────────────────────────────────────────────────────────────
|
||
|
||
export interface WireGuardPeer {
|
||
id?: string
|
||
rosId?: string
|
||
publicKey: string
|
||
allowedIps: string[]
|
||
endpoint?: string // "1.2.3.4:13231"
|
||
latestHandshake?: string // "2 минуты назад"
|
||
transferRx?: number // bytes
|
||
transferTx?: number // bytes
|
||
persistentKeepalive?: number
|
||
persistent?: boolean
|
||
comment?: string
|
||
disabled?: boolean
|
||
name?: string
|
||
clientAddress?: string
|
||
clientDns?: string
|
||
clientEndpoint?: string
|
||
}
|
||
|
||
export interface WireGuardInterface {
|
||
id: string
|
||
rosId?: string
|
||
name: string // e.g. "wg-msk-spb"
|
||
listenPort: number // default 13231
|
||
mtu: number // 1420 default in ROS 7.x
|
||
publicKey?: string
|
||
privateKey?: string
|
||
address?: string
|
||
peers: WireGuardPeer[]
|
||
comment: string
|
||
enabled: boolean
|
||
status: "up" | "down"
|
||
}
|
||
|
||
export interface Server {
|
||
id: string
|
||
name: string
|
||
host: string // management IP / API address
|
||
model: string
|
||
os: string
|
||
site: string
|
||
country: string // ISO 3166-1 alpha-2, e.g. "RU", "DE"
|
||
asn: string
|
||
type: ServerType
|
||
enabled: boolean
|
||
status: ServerStatus
|
||
latency: number | null
|
||
sessions: number
|
||
comment?: string
|
||
// RouterOS 7.x extras
|
||
ipv6Address?: string // global or link-local
|
||
wireGuardIfaces?: WireGuardInterface[]
|
||
vrfNames?: string[] // VRF instances on this router
|
||
rpkiEnabled?: boolean
|
||
// home-router specific
|
||
wanUplinks?: WanUplink[]
|
||
lanSubnet?: string // e.g. "192.168.10.0/24"
|
||
// snapshot / poll data (как GET /api/servers — последний poll MikroTik)
|
||
uptime?: string
|
||
cpuLoad?: number
|
||
/** байты, поля RouterOS resource */
|
||
freeMemory?: number
|
||
totalMemory?: number
|
||
polledAt?: string
|
||
}
|
||
|
||
export interface FlowspecRule {
|
||
id: string
|
||
dstPrefix?: string
|
||
srcPrefix?: string
|
||
ipProto?: string
|
||
dstPort?: string
|
||
action: "rate-limit" | "discard" | "redirect"
|
||
rate?: number // Mbps, for rate-limit
|
||
comment?: string
|
||
}
|
||
|
||
export interface Filter {
|
||
id: string
|
||
name: string
|
||
domains: number
|
||
ips: number
|
||
asns: number
|
||
servers: string[]
|
||
enabled: boolean
|
||
updated: string
|
||
communities: string[]
|
||
gateway: string
|
||
// RouterOS 7.x extras
|
||
largeCommunities?: string[] // RFC 8092 format "AS:VALUE1:VALUE2"
|
||
rpkiValid?: boolean // filter only RPKI-valid routes
|
||
flowspecRules?: FlowspecRule[]
|
||
}
|
||
|
||
export interface Domain {
|
||
id: string
|
||
domain: string
|
||
resolvedIp: string
|
||
asn: string
|
||
purpose: string
|
||
filter: string
|
||
updated: string
|
||
enabled: boolean
|
||
}
|
||
|
||
export interface IpRange {
|
||
id: string
|
||
cidr: string
|
||
asn: string
|
||
country: string
|
||
purpose: string
|
||
filter: string
|
||
updated: string
|
||
enabled: boolean
|
||
}
|
||
|
||
export interface Asn {
|
||
id: string
|
||
asn: string
|
||
org: string
|
||
country: string
|
||
prefixes: number
|
||
filter: string
|
||
updated: string
|
||
enabled: boolean
|
||
}
|
||
|
||
export type FirewallAction =
|
||
| "accept" | "drop" | "reject" | "mark-routing" | "mark-conn"
|
||
| "masquerade" | "src-nat" | "dst-nat"
|
||
| "fasttrack-connection" | "nfqueue" | "passthrough" | "return"
|
||
| "add-src-to-address-list" | "add-dst-to-address-list"
|
||
|
||
export interface FirewallRule {
|
||
id: string
|
||
chain: string
|
||
action: FirewallAction | string
|
||
proto: string
|
||
src: string
|
||
dst: string
|
||
port: string
|
||
iface: string
|
||
comment: string
|
||
enabled: boolean
|
||
hits: number
|
||
// RouterOS 7.x extras
|
||
family?: "ip" | "ip6" | "any"
|
||
tlsHost?: string // tls-host matcher (SNI)
|
||
connRateLimit?: string // connection-rate e.g. "100/s"
|
||
layer7Proto?: string // /ip firewall layer7-protocol
|
||
nfqueueId?: number
|
||
log?: boolean
|
||
logPrefix?: string
|
||
}
|
||
|
||
export interface Backup {
|
||
id: string
|
||
server: string
|
||
filename: string
|
||
size: string
|
||
created: string
|
||
kind: "auto" | "manual"
|
||
notes: string
|
||
}
|
||
|
||
// ─── VXLAN ───────────────────────────────────────────────────────────────────
|
||
|
||
export interface VxlanTunnel {
|
||
id: string
|
||
name: string // "vxlan-overlay-1"
|
||
vni: number // 0–16777215
|
||
port: number // source port (default 0 = auto)
|
||
dstPort: number // destination port (default 8472)
|
||
serverId: string
|
||
vtepIp: string // VTEP address on the server
|
||
remoteVteps: string[] // remote VTEP IPs (unicast-flood)
|
||
l2mtu: number
|
||
arpProxy: boolean
|
||
macLearning: boolean
|
||
comment: string
|
||
enabled: boolean
|
||
status: "up" | "down"
|
||
}
|
||
|
||
// ─── VRF ─────────────────────────────────────────────────────────────────────
|
||
|
||
export interface VrfInstance {
|
||
id: string
|
||
name: string // VRF name
|
||
serverId: string
|
||
interfaces: string[] // list of interfaces in this VRF
|
||
routingTable: string // associated routing table
|
||
comment: string
|
||
}
|
||
|
||
// ─── Container (RouterOS 7.4+) ───────────────────────────────────────────────
|
||
|
||
export interface RouterContainer {
|
||
id: string
|
||
name: string
|
||
serverId: string
|
||
image: string // e.g. "nginx:alpine"
|
||
tag: string
|
||
status: "running" | "stopped" | "error"
|
||
envs: { key: string; value: string }[]
|
||
mounts: { dst: string; src?: string }[]
|
||
interfaces: string[] // veth interface names
|
||
cmd?: string
|
||
startOnBoot: boolean
|
||
comment: string
|
||
uptime?: string
|
||
cpu?: number // CPU % 0-100
|
||
memMb?: number // MB
|
||
}
|
||
|
||
// ─── Certificate ─────────────────────────────────────────────────────────────
|
||
|
||
export type CertUsage = "server" | "client" | "ca" | "crl-sign"
|
||
export type CertStatus = "valid" | "expired" | "revoked"
|
||
|
||
export interface RouterCertificate {
|
||
id: string
|
||
name: string
|
||
serverId: string
|
||
commonName: string
|
||
sans: string[]
|
||
issuedBy: string
|
||
validFrom: string
|
||
validUntil: string
|
||
daysLeft: number
|
||
keySize: number
|
||
usage: CertUsage[]
|
||
trusted: boolean
|
||
status: CertStatus
|
||
}
|
||
|
||
export interface PingProbe {
|
||
id: string
|
||
srcServerId: string // which server sends the ping
|
||
srcInterface?: string // optional interface name on source router
|
||
name: string
|
||
target: string
|
||
filter: string
|
||
rtt: number | null
|
||
loss: number
|
||
status: "up" | "warn" | "down"
|
||
series: number[]
|
||
enabled: boolean
|
||
/** Показывать в блоке «Активные пробы» на дашборде (звезда в мониторинге) */
|
||
showOnDashboard?: boolean
|
||
}
|
||
|
||
export interface SystemEvent {
|
||
id: string
|
||
sev: "destructive" | "warning" | "info"
|
||
title: string
|
||
message: string
|
||
when: string
|
||
}
|
||
|
||
function spark(n: number, base: number, range: number): number[] {
|
||
let s = base * 1000 + range
|
||
return Array.from({ length: n }, () => {
|
||
s = (s * 9301 + 49297) % 233280
|
||
const r = s / 233280
|
||
return Math.max(1, Math.round(base + (r - 0.5) * range * 2))
|
||
})
|
||
}
|
||
|
||
export const servers: Server[] = [
|
||
{
|
||
id: "srv1", name: "mt-msk-core-01", host: "10.0.0.1", model: "CCR2004-1G-12S+2XS", os: "7.20.1",
|
||
site: "MSK", country: "RU", asn: "AS65001", type: "jump-host", enabled: true, status: "online", latency: 12, sessions: 4,
|
||
ipv6Address: "2a01:4f8:1c1c:a1b2::1",
|
||
rpkiEnabled: true,
|
||
vrfNames: ["mgmt", "bypass"],
|
||
wireGuardIfaces: [
|
||
{
|
||
id: "wg1", name: "wg-msk-spb", listenPort: 13231, mtu: 1420, comment: "MSK → SPB overlay", enabled: true, status: "up",
|
||
peers: [
|
||
{ publicKey: "SPBPublicKeyBase64AAAAAAAAAAAAAAAAAAAAAA=", allowedIps: ["10.210.0.2/32","192.168.20.0/24"], endpoint: "10.0.1.1:13231", latestHandshake: "2 мин назад", transferRx: 182_400_000, transferTx: 64_800_000, persistent: true },
|
||
],
|
||
},
|
||
{
|
||
id: "wg2", name: "wg-msk-fra", listenPort: 13232, mtu: 1420, comment: "MSK → FRA overlay", enabled: true, status: "up",
|
||
peers: [
|
||
{ publicKey: "FRAPublicKeyBase64AAAAAAAAAAAAAAAAAAAAAA=", allowedIps: ["10.210.0.6/32"], endpoint: "10.0.2.1:13231", latestHandshake: "1 мин назад", transferRx: 421_000_000, transferTx: 210_000_000, persistent: true },
|
||
],
|
||
},
|
||
],
|
||
},
|
||
{
|
||
id: "srv2", name: "mt-spb-edge-01", host: "10.0.1.1", model: "CCR2116-12G-4S+", os: "7.20.1",
|
||
site: "SPB", country: "RU", asn: "AS65002", type: "exit-node", enabled: true, status: "online", latency: 28, sessions: 6,
|
||
ipv6Address: "2a01:4f8:1c2c:b2c3::1",
|
||
rpkiEnabled: true,
|
||
wireGuardIfaces: [
|
||
{
|
||
id: "wg3", name: "wg-spb-msk", listenPort: 13231, mtu: 1420, comment: "SPB → MSK overlay", enabled: true, status: "up",
|
||
peers: [
|
||
{ publicKey: "MSKPublicKeyBase64AAAAAAAAAAAAAAAAAAAAAA=", allowedIps: ["10.210.0.1/32"], endpoint: "10.0.0.1:13231", latestHandshake: "2 мин назад", transferRx: 64_800_000, transferTx: 182_400_000, persistent: true },
|
||
],
|
||
},
|
||
],
|
||
},
|
||
{
|
||
id: "srv3", name: "mt-fra-edge-01", host: "10.0.2.1", model: "CCR2004-16G-2S+", os: "7.20.1",
|
||
site: "FRA", country: "DE", asn: "AS65003", type: "exit-node", enabled: true, status: "online", latency: 41, sessions: 3,
|
||
ipv6Address: "2a01:4f8:1c3c:c3d4::1",
|
||
rpkiEnabled: true,
|
||
wireGuardIfaces: [
|
||
{
|
||
id: "wg4", name: "wg-fra-msk", listenPort: 13231, mtu: 1420, comment: "FRA → MSK overlay", enabled: true, status: "up",
|
||
peers: [
|
||
{ publicKey: "MSKPublicKeyBase64AAAAAAAAAAAAAAAAAAAAAA=", allowedIps: ["10.210.0.1/32"], endpoint: "10.0.0.1:13232", latestHandshake: "1 мин назад", transferRx: 210_000_000, transferTx: 421_000_000, persistent: true },
|
||
],
|
||
},
|
||
],
|
||
},
|
||
{
|
||
id: "srv4", name: "mt-ams-edge-01", host: "10.0.3.1", model: "RB5009UG+S+IN", os: "7.19.3",
|
||
site: "AMS", country: "NL", asn: "AS65004", type: "exit-node", enabled: true, status: "degraded", latency: 88, sessions: 2,
|
||
},
|
||
{
|
||
id: "srv5", name: "mt-sgp-edge-01", host: "10.0.4.1", model: "CCR2004-1G-12S+2XS", os: "7.14.2",
|
||
site: "SGP", country: "SG", asn: "AS65005", type: "exit-node", enabled: false, status: "offline", latency: null, sessions: 0,
|
||
},
|
||
{
|
||
id: "srv6", name: "mt-ams-test-01", host: "10.0.3.2", model: "hEX S", os: "7.20.1",
|
||
site: "AMS", country: "NL", asn: "AS65006", type: "jump-host", enabled: true, status: "online", latency: 92, sessions: 1,
|
||
},
|
||
{
|
||
id: "srv7", name: "mt-msk-lab-01", host: "10.0.0.7", model: "RB5009UG+S+IN", os: "7.20.1",
|
||
site: "MSK", country: "RU", asn: "AS65007", type: "jump-host", enabled: true, status: "online", latency: 14, sessions: 2,
|
||
vrfNames: ["lab"],
|
||
},
|
||
{
|
||
id: "home1", name: "home-msk-01", host: "192.168.10.1", model: "hEX S (RB760iGS)", os: "7.20.1",
|
||
site: "MSK", country: "RU", asn: "", type: "home-router", enabled: true, status: "online", latency: 3, sessions: 0,
|
||
comment: "MSK офис — основной роутер",
|
||
lanSubnet: "192.168.10.0/24",
|
||
wanUplinks: [
|
||
{ id: "w1a", name: "WAN1-RT", isp: "Rostelecom", iface: "ether1", ip: "94.25.168.1", maxDl: 500, maxUl: 500 },
|
||
{ id: "w1b", name: "WAN2-BL", isp: "Beeline", iface: "ether2", ip: "85.174.12.1", maxDl: 100, maxUl: 100 },
|
||
],
|
||
},
|
||
{
|
||
id: "home2", name: "home-spb-01", host: "192.168.20.1", model: "RB5009UG+S+IN", os: "7.20.1",
|
||
site: "SPB", country: "RU", asn: "", type: "home-router", enabled: true, status: "online", latency: 5, sessions: 0,
|
||
comment: "SPB офис — основной роутер",
|
||
lanSubnet: "192.168.20.0/24",
|
||
wanUplinks: [
|
||
{ id: "w2a", name: "WAN1-MTS", isp: "МТС", iface: "ether1", ip: "178.214.4.1", maxDl: 300, maxUl: 300 },
|
||
{ id: "w2b", name: "WAN2-ERT", isp: "ЭР-Телеком", iface: "ether2", ip: "95.31.14.1", maxDl: 200, maxUl: 150 },
|
||
],
|
||
},
|
||
]
|
||
|
||
export const filters: Filter[] = [
|
||
{
|
||
id: "f1", name: "youtube-bypass", domains: 1842, ips: 4218, asns: 12,
|
||
servers: ["srv1","srv2","srv3","srv4"], enabled: true, updated: "12 мин назад",
|
||
communities: ["65001:100","65001:200"], gateway: "10.0.0.1",
|
||
largeCommunities: ["65001:100:1","65001:100:2"],
|
||
rpkiValid: true,
|
||
},
|
||
{
|
||
id: "f2", name: "streaming-eu", domains: 612, ips: 2104, asns: 8,
|
||
servers: ["srv2","srv3","srv4"], enabled: true, updated: "2 ч назад",
|
||
communities: ["65001:200"], gateway: "10.0.1.1",
|
||
largeCommunities: ["65001:200:1"],
|
||
rpkiValid: true,
|
||
},
|
||
{
|
||
id: "f3", name: "cdn-bypass", domains: 4218, ips: 18211, asns: 22,
|
||
servers: ["srv1","srv2","srv3","srv4","srv6"], enabled: true, updated: "1 ч назад",
|
||
communities: ["65001:300","65002:100"], gateway: "10.0.0.1",
|
||
flowspecRules: [
|
||
{ id: "fs1", dstPrefix: "104.16.0.0/12", ipProto: "tcp", dstPort: "443", action: "rate-limit", rate: 100, comment: "CF rate-limit" },
|
||
],
|
||
},
|
||
{ id: "f4", name: "social-block-school", domains: 84, ips: 412, asns: 4, servers: ["srv1","srv7"], enabled: false, updated: "3 дн назад", communities: ["65007:999"], gateway: "" },
|
||
{ id: "f5", name: "office-direct", domains: 142, ips: 884, asns: 6, servers: ["srv1","srv2","srv3","srv4","srv6","srv7"], enabled: true, updated: "4 ч назад", communities: ["65001:400"], gateway: "10.0.0.1" },
|
||
{ id: "f6", name: "gaming-low-latency", domains: 88, ips: 1212, asns: 14, servers: ["srv1","srv2","srv3","srv7"], enabled: true, updated: "24 мин назад", communities: ["65001:500","65002:200"], gateway: "10.0.2.1" },
|
||
]
|
||
|
||
export const domains: Domain[] = [
|
||
{ id: "d1", domain: "youtube.com", purpose: "streaming", filter: "youtube-bypass", resolvedIp: "142.250.74.110", asn: "AS15169", updated: "12 мин", enabled: true },
|
||
{ id: "d2", domain: "googlevideo.com", purpose: "streaming", filter: "youtube-bypass", resolvedIp: "142.250.74.142", asn: "AS15169", updated: "12 мин", enabled: true },
|
||
{ id: "d3", domain: "ytimg.com", purpose: "streaming", filter: "youtube-bypass", resolvedIp: "172.217.16.46", asn: "AS15169", updated: "12 мин", enabled: true },
|
||
{ id: "d4", domain: "netflix.com", purpose: "streaming", filter: "streaming-eu", resolvedIp: "54.246.79.9", asn: "AS2906", updated: "2 ч", enabled: true },
|
||
{ id: "d5", domain: "nflxvideo.net", purpose: "streaming", filter: "streaming-eu", resolvedIp: "45.57.32.18", asn: "AS2906", updated: "2 ч", enabled: true },
|
||
{ id: "d6", domain: "cloudflare.com", purpose: "cdn", filter: "cdn-bypass", resolvedIp: "104.16.132.229", asn: "AS13335", updated: "1 ч", enabled: true },
|
||
{ id: "d7", domain: "akamaized.net", purpose: "cdn", filter: "cdn-bypass", resolvedIp: "23.46.18.94", asn: "AS20940", updated: "1 ч", enabled: true },
|
||
{ id: "d8", domain: "fastly.net", purpose: "cdn", filter: "cdn-bypass", resolvedIp: "151.101.1.95", asn: "AS54113", updated: "1 ч", enabled: true },
|
||
{ id: "d9", domain: "twitch.tv", purpose: "streaming", filter: "streaming-eu", resolvedIp: "52.223.241.72", asn: "AS16509", updated: "2 ч", enabled: false },
|
||
{ id: "d10", domain: "discord.com", purpose: "voip", filter: "gaming-low-latency", resolvedIp: "162.159.135.232", asn: "AS13335", updated: "24 мин", enabled: true },
|
||
{ id: "d11", domain: "steam.com", purpose: "gaming", filter: "gaming-low-latency", resolvedIp: "23.45.139.40", asn: "AS20940", updated: "24 мин", enabled: true },
|
||
{ id: "d12", domain: "epicgames.com", purpose: "gaming", filter: "gaming-low-latency", resolvedIp: "34.205.247.51", asn: "AS16509", updated: "24 мин", enabled: true },
|
||
]
|
||
|
||
export const ipRanges: IpRange[] = [
|
||
{ id: "i1", cidr: "142.250.0.0/15", purpose: "streaming", filter: "youtube-bypass", asn: "AS15169", country: "US", updated: "12 мин", enabled: true },
|
||
{ id: "i2", cidr: "172.217.0.0/16", purpose: "streaming", filter: "youtube-bypass", asn: "AS15169", country: "US", updated: "12 мин", enabled: true },
|
||
{ id: "i3", cidr: "104.16.0.0/12", purpose: "cdn", filter: "cdn-bypass", asn: "AS13335", country: "US", updated: "1 ч", enabled: true },
|
||
{ id: "i4", cidr: "23.32.0.0/11", purpose: "cdn", filter: "cdn-bypass", asn: "AS20940", country: "US", updated: "1 ч", enabled: true },
|
||
{ id: "i5", cidr: "151.101.0.0/16", purpose: "cdn", filter: "cdn-bypass", asn: "AS54113", country: "US", updated: "1 ч", enabled: true },
|
||
{ id: "i6", cidr: "54.246.0.0/16", purpose: "streaming", filter: "streaming-eu", asn: "AS2906", country: "IE", updated: "2 ч", enabled: true },
|
||
{ id: "i7", cidr: "45.57.0.0/16", purpose: "streaming", filter: "streaming-eu", asn: "AS2906", country: "NL", updated: "2 ч", enabled: true },
|
||
{ id: "i8", cidr: "162.159.128.0/19", purpose: "voip", filter: "gaming-low-latency", asn: "AS13335", country: "US", updated: "24 мин", enabled: true },
|
||
{ id: "i9", cidr: "52.223.240.0/20", purpose: "streaming", filter: "streaming-eu", asn: "AS16509", country: "IE", updated: "2 ч", enabled: false },
|
||
]
|
||
|
||
export const asns: Asn[] = [
|
||
{ id: "a1", asn: "AS15169", org: "GOOGLE", country: "US", prefixes: 842, filter: "youtube-bypass", updated: "12 мин", enabled: true },
|
||
{ id: "a2", asn: "AS13335", org: "CLOUDFLARENET", country: "US", prefixes: 1284, filter: "cdn-bypass", updated: "1 ч", enabled: true },
|
||
{ id: "a3", asn: "AS16509", org: "AMAZON-02", country: "US", prefixes: 4128, filter: "streaming-eu", updated: "2 ч", enabled: true },
|
||
{ id: "a4", asn: "AS20940", org: "AKAMAI-ASN1", country: "US", prefixes: 614, filter: "cdn-bypass", updated: "1 ч", enabled: true },
|
||
{ id: "a5", asn: "AS54113", org: "FASTLY", country: "US", prefixes: 122, filter: "cdn-bypass", updated: "1 ч", enabled: true },
|
||
{ id: "a6", asn: "AS2906", org: "AS-SSI (Netflix)", country: "US", prefixes: 88, filter: "streaming-eu", updated: "2 ч", enabled: true },
|
||
{ id: "a7", asn: "AS32934", org: "FACEBOOK", country: "US", prefixes: 412, filter: "social-block-school",updated: "3 дн", enabled: false },
|
||
{ id: "a8", asn: "AS8075", org: "MICROSOFT-CORP", country: "US", prefixes: 882, filter: "office-direct", updated: "4 ч", enabled: true },
|
||
]
|
||
|
||
export const firewallRules: FirewallRule[] = [
|
||
{ id: "fw1", chain: "forward", action: "accept", proto: "tcp", src: "youtube-bypass", dst: "0.0.0.0/0", port: "443", iface: "wan-bgp", comment: "YouTube bypass traffic", enabled: true, hits: 188421 },
|
||
{ id: "fw2", chain: "forward", action: "mark-routing", proto: "tcp", src: "10.10.0.0/24", dst: "cdn-bypass", port: "—", iface: "lan", comment: "CDN routing mark", enabled: true, hits: 4128821 },
|
||
{ id: "fw3", chain: "srcnat", action: "masquerade", proto: "all", src: "10.10.0.0/16", dst: "0.0.0.0/0", port: "—", iface: "wan-msk", comment: "Main NAT rule", enabled: true, hits: 12889241 },
|
||
{ id: "fw4", chain: "forward", action: "drop", proto: "tcp", src: "0.0.0.0/0", dst: "social-block-school", port: "—", iface: "lan-school", comment: "School social block", enabled: true, hits: 4218 },
|
||
{ id: "fw5", chain: "input", action: "accept", proto: "tcp", src: "10.10.0.0/16", dst: "—", port: "22,443,8291",iface: "—", comment: "Management access", enabled: true, hits: 18412 },
|
||
{ id: "fw6", chain: "input", action: "drop", proto: "tcp", src: "0.0.0.0/0", dst: "—", port: "22", iface: "wan-msk", comment: "Block SSH from WAN", enabled: true, hits: 882412 },
|
||
]
|
||
|
||
export const backups: Backup[] = [
|
||
{ id: "b1", server: "mt-msk-core-01", filename: "mt-msk-core-01_2026-04-26_03-00.rsc", size: "124 КБ", created: "Сегодня, 03:00", kind: "auto", notes: "снапшот перед обновлением" },
|
||
{ id: "b2", server: "mt-msk-core-01", filename: "mt-msk-core-01_2026-04-25_03-00.rsc", size: "124 КБ", created: "Вчера, 03:00", kind: "auto", notes: "" },
|
||
{ id: "b3", server: "mt-spb-edge-01", filename: "mt-spb-edge-01_2026-04-26_03-00.rsc", size: "88 КБ", created: "Сегодня, 03:00", kind: "auto", notes: "" },
|
||
{ id: "b4", server: "mt-fra-edge-01", filename: "mt-fra-edge-01_2026-04-26_manual.rsc",size: "92 КБ", created: "Сегодня, 14:18", kind: "manual", notes: "перед изменением BGP" },
|
||
{ id: "b5", server: "mt-ams-edge-01", filename: "mt-ams-edge-01_2026-04-25_03-00.rsc", size: "64 КБ", created: "Вчера, 03:00", kind: "auto", notes: "" },
|
||
]
|
||
|
||
export const pingProbes: PingProbe[] = [
|
||
// srv1 — mt-msk-core-01 (JH, MSK) → основной мониторинг
|
||
{ id: "p1", srcServerId: "srv1", name: "youtube.com", target: "142.250.74.110", filter: "youtube-bypass", rtt: 18, loss: 0, status: "up", series: spark(40, 18, 4), enabled: true },
|
||
{ id: "p2", srcServerId: "srv1", name: "cloudflare.com", target: "104.16.132.229", filter: "cdn-bypass", rtt: 4, loss: 0, status: "up", series: spark(40, 4, 1), enabled: true },
|
||
{ id: "p3", srcServerId: "srv1", name: "netflix-eu", target: "54.246.79.9", filter: "streaming-eu", rtt: 28, loss: 0, status: "up", series: spark(40, 28, 5), enabled: true },
|
||
{ id: "p4", srcServerId: "srv1", name: "fastly-edge", target: "151.101.1.95", filter: "cdn-bypass", rtt: 8, loss: 0, status: "up", series: spark(40, 8, 2), enabled: true },
|
||
// srv7 — mt-msk-lab-01 (JH, MSK) → лаборатория
|
||
{ id: "p5", srcServerId: "srv7", name: "discord-voip", target: "162.159.135.232", filter: "gaming-low-latency", rtt: 12, loss: 0, status: "up", series: spark(40, 12, 2), enabled: true },
|
||
{ id: "p6", srcServerId: "srv7", name: "steam-cdn", target: "23.45.139.40", filter: "gaming-low-latency", rtt: 38, loss: 1.2, status: "warn", series: spark(40, 38, 12), enabled: true },
|
||
{ id: "p7", srcServerId: "srv7", name: "akamai-edge", target: "23.46.18.94", filter: "cdn-bypass", rtt: 22, loss: 0, status: "up", series: spark(40, 22, 4), enabled: true },
|
||
// srv2 — mt-spb-edge-01 (EN, SPB) → исходящий трафик SPB
|
||
{ id: "p8", srcServerId: "srv2", name: "youtube.com", target: "142.250.74.110", filter: "youtube-bypass", rtt: 22, loss: 0, status: "up", series: spark(40, 22, 5), enabled: true },
|
||
{ id: "p9", srcServerId: "srv2", name: "office-365", target: "104.47.0.22", filter: "office-direct", rtt: 31, loss: 0, status: "up", series: spark(40, 31, 6), enabled: false },
|
||
// srv3 — mt-fra-edge-01 (EN, FRA) → исходящий трафик Frankfurt
|
||
{ id: "p10", srcServerId: "srv3", name: "youtube.com", target: "142.250.74.110", filter: "youtube-bypass", rtt: 12, loss: 0, status: "up", series: spark(40, 12, 3), enabled: true },
|
||
{ id: "p11", srcServerId: "srv3", name: "netflix-eu", target: "54.246.79.9", filter: "streaming-eu", rtt: 9, loss: 0, status: "up", series: spark(40, 9, 2), enabled: true },
|
||
// srv4 — mt-ams-edge-01 (EN, AMS, degraded) → деградировавший узел
|
||
{ id: "p12", srcServerId: "srv4", name: "cloudflare.com", target: "104.16.132.229", filter: "cdn-bypass", rtt: 88, loss: 3.4, status: "warn", series: spark(40, 88, 22), enabled: true },
|
||
{ id: "p13", srcServerId: "srv4", name: "sgp-probe", target: "139.180.22.4", filter: "—", rtt: null,loss: 100, status: "down", series: Array(40).fill(0), enabled: true },
|
||
]
|
||
|
||
export const systemEvents: SystemEvent[] = [
|
||
{ id: "e1", sev: "destructive", title: "BGP-сессия упала", message: "mt-sgp-edge-01 · пир 139.180.22.4 · простой 2ч", when: "2ч" },
|
||
{ id: "e2", sev: "destructive", title: "Ошибка синхронизации фильтра", message: "cdn-bypass → mt-ams-edge-01 · таймаут", when: "14м" },
|
||
{ id: "e3", sev: "warning", title: "Высокая задержка на AMS", message: "среднее 88мс · порог 60мс", when: "8м" },
|
||
{ id: "e4", sev: "warning", title: "Бэкап просрочен", message: "mt-msk-lab-01 · последний 5д назад", when: "1ч" },
|
||
{ id: "e5", sev: "info", title: "Обновление BGP завершено", message: "+412 префиксов · −188 отозвано", when: "12м" },
|
||
{ id: "e6", sev: "info", title: "Фильтр youtube-bypass обновлён", message: "+88 доменов · ↑ 24 сервера", when: "12м" },
|
||
]
|
||
|
||
export const dashLatency = {
|
||
msk: spark(60, 12, 4),
|
||
spb: spark(60, 28, 6),
|
||
fra: spark(60, 41, 9),
|
||
ams: spark(60, 88, 18),
|
||
}
|
||
|
||
export const traffic = {
|
||
rx: Array.from({ length: 60 }, (_, i) => Math.round(280 + Math.sin(i / 6) * 60 + ((i * 7919) % 31))),
|
||
tx: Array.from({ length: 60 }, (_, i) => Math.round(220 + Math.sin(i / 5) * 50 + ((i * 6271) % 21))),
|
||
}
|
||
|
||
// ─── GRE ────────────────────────────────────────────────────────────────────
|
||
|
||
export type GreStatus = "up" | "down" | "degraded"
|
||
export type IpsecEncAlg = "aes-128" | "aes-192" | "aes-256"
|
||
export type IpsecAuthAlg = "sha1" | "sha256" | "sha512"
|
||
export type IpsecDhGroup = "modp1024" | "modp2048" | "modp4096" | "ecp256" | "ecp384" | "ecp521"
|
||
export type IkeVersion = "ikev1" | "ikev2"
|
||
export type DscpMode = "inherit" | number
|
||
|
||
export interface GreIpsec {
|
||
secret: string // ipsec-secret → auto-creates peer+policy+proposal
|
||
encAlg: IpsecEncAlg // proposal enc-algorithms
|
||
authAlg: IpsecAuthAlg // proposal auth-algorithms
|
||
dhGroup: IpsecDhGroup // proposal pfs-group / peer dh-group
|
||
ikeVersion: IkeVersion // peer exchange-mode
|
||
lifetime: string // proposal lifetime (e.g. "1d 00:00:00")
|
||
pfs: boolean // perfect forward secrecy
|
||
}
|
||
|
||
export interface GreTunnel {
|
||
id: string
|
||
name: string // interface name, e.g. gre-msk-spb
|
||
serverId: string // which MikroTik runs this tunnel
|
||
localAddress: string // local GRE endpoint ("0.0.0.0" = auto)
|
||
remoteAddress: string // remote GRE endpoint (required)
|
||
localInnerIp: string // /ip address on this side, e.g. 10.200.0.1/30
|
||
remoteInnerIp: string // /ip address on remote side, e.g. 10.200.0.2/30
|
||
poolId: string // which IP pool the inner IPs come from
|
||
ipsec: GreIpsec | null // null = no IPsec (plain GRE)
|
||
mtu: number // default 1476
|
||
keepaliveInterval: number // seconds, 0 = disabled
|
||
keepaliveRetries: number
|
||
dscp: DscpMode // "inherit" or 0-63
|
||
clampTcpMss: boolean
|
||
allowFastPath: boolean
|
||
comment: string
|
||
enabled: boolean
|
||
status: GreStatus
|
||
}
|
||
|
||
export interface GrePool {
|
||
id: string
|
||
name: string
|
||
cidr: string
|
||
allocated: number
|
||
total: number
|
||
comment: string
|
||
}
|
||
|
||
const defaultIpsec = (secret: string, ikeVersion: IkeVersion = "ikev2"): GreIpsec => ({
|
||
secret,
|
||
encAlg: "aes-256",
|
||
authAlg: "sha256",
|
||
dhGroup: "modp2048",
|
||
ikeVersion,
|
||
lifetime: "1d 00:00:00",
|
||
pfs: true,
|
||
})
|
||
|
||
export const grePools: GrePool[] = [
|
||
{ id: "gp1", name: "pool-gre-core", cidr: "10.200.0.0/24", allocated: 16, total: 64, comment: "Ядровые межузловые туннели" },
|
||
{ id: "gp2", name: "pool-gre-mgmt", cidr: "10.201.0.0/24", allocated: 8, total: 64, comment: "Управляющие туннели (lab, test)" },
|
||
]
|
||
|
||
export const greTunnels: GreTunnel[] = [
|
||
{
|
||
id: "gre1", name: "gre-msk-spb", serverId: "srv1",
|
||
localAddress: "10.0.0.1", remoteAddress: "10.0.1.1",
|
||
localInnerIp: "10.200.0.1/30", remoteInnerIp: "10.200.0.2/30", poolId: "gp1",
|
||
ipsec: defaultIpsec("xK9#mQ2$vLp8nR4"),
|
||
mtu: 1476, keepaliveInterval: 10, keepaliveRetries: 10,
|
||
dscp: "inherit", clampTcpMss: true, allowFastPath: true,
|
||
comment: "MSK → SPB core interconnect", enabled: true, status: "up",
|
||
},
|
||
{
|
||
id: "gre2", name: "gre-msk-fra", serverId: "srv1",
|
||
localAddress: "10.0.0.1", remoteAddress: "10.0.2.1",
|
||
localInnerIp: "10.200.0.5/30", remoteInnerIp: "10.200.0.6/30", poolId: "gp1",
|
||
ipsec: defaultIpsec("pW3@jT7!hD5kYe1"),
|
||
mtu: 1476, keepaliveInterval: 10, keepaliveRetries: 10,
|
||
dscp: "inherit", clampTcpMss: true, allowFastPath: true,
|
||
comment: "MSK → FRA core interconnect", enabled: true, status: "up",
|
||
},
|
||
{
|
||
id: "gre3", name: "gre-msk-ams", serverId: "srv1",
|
||
localAddress: "10.0.0.1", remoteAddress: "10.0.3.1",
|
||
localInnerIp: "10.200.0.9/30", remoteInnerIp: "10.200.0.10/30", poolId: "gp1",
|
||
ipsec: defaultIpsec("rN6%bF2*cM8sZa0"),
|
||
mtu: 1476, keepaliveInterval: 10, keepaliveRetries: 10,
|
||
dscp: "inherit", clampTcpMss: true, allowFastPath: false,
|
||
comment: "MSK → AMS core interconnect", enabled: true, status: "degraded",
|
||
},
|
||
{
|
||
id: "gre4", name: "gre-msk-sgp", serverId: "srv1",
|
||
localAddress: "10.0.0.1", remoteAddress: "10.0.4.1",
|
||
localInnerIp: "10.200.0.13/30", remoteInnerIp: "10.200.0.14/30", poolId: "gp1",
|
||
ipsec: defaultIpsec("qA4^eU9#wG1oXi6"),
|
||
mtu: 1476, keepaliveInterval: 10, keepaliveRetries: 10,
|
||
dscp: "inherit", clampTcpMss: true, allowFastPath: true,
|
||
comment: "MSK → SGP core interconnect", enabled: false, status: "down",
|
||
},
|
||
{
|
||
id: "gre5", name: "gre-lab-core", serverId: "srv7",
|
||
localAddress: "10.0.0.7", remoteAddress: "10.0.0.1",
|
||
localInnerIp: "10.201.0.1/30", remoteInnerIp: "10.201.0.2/30", poolId: "gp2",
|
||
ipsec: null,
|
||
mtu: 1500, keepaliveInterval: 0, keepaliveRetries: 0,
|
||
dscp: "inherit", clampTcpMss: false, allowFastPath: true,
|
||
comment: "Lab → core (internal, no IPsec)", enabled: true, status: "up",
|
||
},
|
||
{
|
||
id: "gre6", name: "gre-ams-test", serverId: "srv6",
|
||
localAddress: "10.0.3.2", remoteAddress: "10.0.3.1",
|
||
localInnerIp: "10.201.0.5/30", remoteInnerIp: "10.201.0.6/30", poolId: "gp2",
|
||
ipsec: null,
|
||
mtu: 1476, keepaliveInterval: 5, keepaliveRetries: 5,
|
||
dscp: 0, clampTcpMss: true, allowFastPath: true,
|
||
comment: "AMS test → AMS edge", enabled: true, status: "up",
|
||
},
|
||
]
|
||
|
||
// ─── Filter Rules (Community → Gateway per server) ────────────────────────────
|
||
|
||
export interface FilterRule {
|
||
id: string
|
||
community: string // BGP community, e.g. "65001:100"
|
||
communityName?: string // optional human-readable name
|
||
action?: "route" | "blackhole" // default "route"; "blackhole" → null-route (RTBH)
|
||
gateway: string // next-hop IP for filter rule; empty for blackhole
|
||
/** GRE: id туннеля / имя интерфейса; рекурсивный маршрут: `rec:<id>` строки recursive_routes на сервере */
|
||
gatewayTunnelId: string
|
||
description: string
|
||
}
|
||
|
||
export interface ServerFilterRuleset {
|
||
serverId: string
|
||
rules: FilterRule[]
|
||
}
|
||
|
||
export const serverFilterRulesets: ServerFilterRuleset[] = [
|
||
// srv1 — mt-msk-core-01 (jump-host, MSK): gre1=SPB, gre2=FRA, gre3=AMS(deg), gre4=SGP(down)
|
||
{
|
||
serverId: "srv1",
|
||
rules: [
|
||
{ id: "r1", community: "65001:100", communityName: "youtube-bypass", gateway: "10.200.0.6", gatewayTunnelId: "gre2", description: "YouTube/Google Video → Frankfurt (IX)" },
|
||
{ id: "r2", community: "65001:200", communityName: "streaming-eu", gateway: "10.200.0.6", gatewayTunnelId: "gre2", description: "Netflix, Twitch EU → Frankfurt" },
|
||
{ id: "r3", community: "65001:300", communityName: "cdn-bypass", gateway: "10.200.0.2", gatewayTunnelId: "gre1", description: "Cloudflare / Akamai / Fastly → SPB" },
|
||
{ id: "r4", community: "65002:100", communityName: "cdn-secondary", gateway: "10.200.0.10", gatewayTunnelId: "gre3", description: "CDN резерв → Amsterdam (degraded)" },
|
||
{ id: "r5", community: "65001:400", communityName: "office-direct", gateway: "10.200.0.2", gatewayTunnelId: "gre1", description: "MS Office 365 / Teams → SPB direct" },
|
||
{ id: "r6", community: "65001:500", communityName: "gaming-ll", gateway: "10.200.0.2", gatewayTunnelId: "gre1", description: "Discord / Steam / Epic — низкая задержка → SPB" },
|
||
{ id: "r10", community: "65535:666", communityName: "BLACKHOLE (RFC 7999)", action: "blackhole", gateway: "", gatewayTunnelId: "", description: "RTBH — null-route входящих маршрутов" },
|
||
{ id: "r11", community: "65001:666", communityName: "blackhole-local", action: "blackhole", gateway: "", gatewayTunnelId: "", description: "Локальная блокировка — сброс трафика" },
|
||
],
|
||
},
|
||
// srv7 — mt-msk-lab-01 (jump-host, MSK lab): gre5=core
|
||
{
|
||
serverId: "srv7",
|
||
rules: [
|
||
{ id: "r7", community: "65001:100", communityName: "youtube-bypass", gateway: "10.201.0.2", gatewayTunnelId: "gre5", description: "Lab: YouTube → core" },
|
||
{ id: "r8", community: "65007:999", communityName: "school-block", gateway: "10.201.0.2", gatewayTunnelId: "gre5", description: "Lab: школьная блокировка" },
|
||
],
|
||
},
|
||
// srv6 — mt-ams-test-01 (jump-host, AMS test): gre6=AMS edge
|
||
{
|
||
serverId: "srv6",
|
||
rules: [
|
||
{ id: "r9", community: "65001:300", communityName: "cdn-bypass", gateway: "10.201.0.6", gatewayTunnelId: "gre6", description: "AMS test: CDN → AMS edge" },
|
||
],
|
||
},
|
||
// Exit nodes — нет правил по умолчанию
|
||
{ serverId: "srv2", rules: [] },
|
||
{ serverId: "srv3", rules: [] },
|
||
{ serverId: "srv4", rules: [] },
|
||
{ serverId: "srv5", rules: [] },
|
||
]
|
||
|
||
// ─── VXLAN mock data ─────────────────────────────────────────────────────────
|
||
|
||
export const vxlanTunnels: VxlanTunnel[] = [
|
||
{
|
||
id: "vx1", name: "vxlan-overlay-msk", vni: 10010, port: 0, dstPort: 8472,
|
||
serverId: "srv1", vtepIp: "10.0.0.1", remoteVteps: ["10.0.1.1","10.0.2.1"],
|
||
l2mtu: 1500, arpProxy: true, macLearning: true,
|
||
comment: "MSK overlay — сегмент bypass", enabled: true, status: "up",
|
||
},
|
||
{
|
||
id: "vx2", name: "vxlan-overlay-spb", vni: 10010, port: 0, dstPort: 8472,
|
||
serverId: "srv2", vtepIp: "10.0.1.1", remoteVteps: ["10.0.0.1","10.0.2.1"],
|
||
l2mtu: 1500, arpProxy: true, macLearning: true,
|
||
comment: "SPB overlay — сегмент bypass", enabled: true, status: "up",
|
||
},
|
||
{
|
||
id: "vx3", name: "vxlan-overlay-fra", vni: 10010, port: 0, dstPort: 8472,
|
||
serverId: "srv3", vtepIp: "10.0.2.1", remoteVteps: ["10.0.0.1","10.0.1.1"],
|
||
l2mtu: 1500, arpProxy: true, macLearning: false,
|
||
comment: "FRA overlay — сегмент bypass", enabled: true, status: "up",
|
||
},
|
||
{
|
||
id: "vx4", name: "vxlan-mgmt-lab", vni: 20001, port: 0, dstPort: 4789,
|
||
serverId: "srv7", vtepIp: "10.0.0.7", remoteVteps: ["10.0.0.1"],
|
||
l2mtu: 1500, arpProxy: false, macLearning: true,
|
||
comment: "Lab management VXLAN", enabled: true, status: "up",
|
||
},
|
||
{
|
||
id: "vx5", name: "vxlan-overlay-ams", vni: 10010, port: 0, dstPort: 8472,
|
||
serverId: "srv4", vtepIp: "10.0.3.1", remoteVteps: ["10.0.0.1"],
|
||
l2mtu: 1500, arpProxy: true, macLearning: true,
|
||
comment: "AMS overlay (degraded)", enabled: true, status: "down",
|
||
},
|
||
]
|
||
|
||
// ─── Container mock data ─────────────────────────────────────────────────────
|
||
|
||
export const routerContainers: RouterContainer[] = [
|
||
{
|
||
id: "c1", name: "adguard-msk", serverId: "srv1",
|
||
image: "adguard/adguardhome", tag: "latest",
|
||
status: "running",
|
||
envs: [{ key: "AGH_CONFIG", value: "/opt/adguardhome/conf/AdGuardHome.yaml" }],
|
||
mounts: [{ dst: "/opt/adguardhome/conf", src: "/disk1/adguard" }, { dst: "/opt/adguardhome/work", src: "/disk1/adguard-work" }],
|
||
interfaces: ["veth-adguard"],
|
||
startOnBoot: true, comment: "AdGuard Home — DNS фильтрация",
|
||
uptime: "12д 4ч", cpu: 3, memMb: 64,
|
||
},
|
||
{
|
||
id: "c2", name: "prometheus-msk", serverId: "srv1",
|
||
image: "prom/prometheus", tag: "v2.52.0",
|
||
status: "running",
|
||
envs: [],
|
||
mounts: [{ dst: "/prometheus", src: "/disk1/prom-data" }],
|
||
interfaces: ["veth-prom"],
|
||
cmd: "--config.file=/etc/prometheus/prometheus.yml --storage.tsdb.retention.time=30d",
|
||
startOnBoot: true, comment: "Prometheus метрики",
|
||
uptime: "5д 11ч", cpu: 8, memMb: 256,
|
||
},
|
||
{
|
||
id: "c3", name: "grafana-msk", serverId: "srv1",
|
||
image: "grafana/grafana", tag: "10.4.2",
|
||
status: "running",
|
||
envs: [{ key: "GF_SECURITY_ADMIN_PASSWORD", value: "*** (hidden)" }],
|
||
mounts: [{ dst: "/var/lib/grafana", src: "/disk1/grafana" }],
|
||
interfaces: ["veth-grafana"],
|
||
startOnBoot: true, comment: "Grafana — дашборды мониторинга",
|
||
uptime: "5д 11ч", cpu: 5, memMb: 128,
|
||
},
|
||
{
|
||
id: "c4", name: "wg-portal-spb", serverId: "srv2",
|
||
image: "wgportal/wg-portal", tag: "v1.3.1",
|
||
status: "running",
|
||
envs: [{ key: "WG_PORTAL_ADMIN_USER", value: "admin" }],
|
||
mounts: [{ dst: "/app/data", src: "/disk1/wgportal" }],
|
||
interfaces: ["veth-wgportal"],
|
||
startOnBoot: true, comment: "WireGuard Portal — управление клиентами",
|
||
uptime: "3д 7ч", cpu: 1, memMb: 48,
|
||
},
|
||
{
|
||
id: "c5", name: "unbound-fra", serverId: "srv3",
|
||
image: "mvance/unbound", tag: "1.19.3",
|
||
status: "stopped",
|
||
envs: [],
|
||
mounts: [],
|
||
interfaces: ["veth-unbound"],
|
||
startOnBoot: false, comment: "Unbound DNS резолвер (в резерве)",
|
||
cpu: 0, memMb: 0,
|
||
},
|
||
]
|
||
|
||
// ─── Certificate mock data ────────────────────────────────────────────────────
|
||
|
||
export const routerCertificates: RouterCertificate[] = [
|
||
{
|
||
id: "cert1", name: "mt-msk-core-01-server", serverId: "srv1",
|
||
commonName: "mt-msk-core-01.routerlists.io",
|
||
sans: ["mt-msk-core-01.routerlists.io","10.0.0.1"],
|
||
issuedBy: "MikrotikManager Internal CA", validFrom: "2024-01-15",
|
||
validUntil: "2026-01-15", daysLeft: 261,
|
||
keySize: 4096, usage: ["server"], trusted: true, status: "valid",
|
||
},
|
||
{
|
||
id: "cert2", name: "routerlists-internal-ca", serverId: "srv1",
|
||
commonName: "MikrotikManager Internal CA",
|
||
sans: [],
|
||
issuedBy: "MikrotikManager Internal CA (self-signed)", validFrom: "2023-06-01",
|
||
validUntil: "2033-06-01", daysLeft: 2589,
|
||
keySize: 4096, usage: ["ca","crl-sign"], trusted: true, status: "valid",
|
||
},
|
||
{
|
||
id: "cert3", name: "mt-spb-edge-01-server", serverId: "srv2",
|
||
commonName: "mt-spb-edge-01.routerlists.io",
|
||
sans: ["mt-spb-edge-01.routerlists.io","10.0.1.1"],
|
||
issuedBy: "MikrotikManager Internal CA", validFrom: "2024-01-15",
|
||
validUntil: "2026-01-15", daysLeft: 261,
|
||
keySize: 4096, usage: ["server"], trusted: true, status: "valid",
|
||
},
|
||
{
|
||
id: "cert4", name: "mt-fra-edge-01-server", serverId: "srv3",
|
||
commonName: "mt-fra-edge-01.routerlists.io",
|
||
sans: ["mt-fra-edge-01.routerlists.io","10.0.2.1"],
|
||
issuedBy: "Let's Encrypt", validFrom: "2026-01-10",
|
||
validUntil: "2026-04-10", daysLeft: -19,
|
||
keySize: 2048, usage: ["server"], trusted: true, status: "expired",
|
||
},
|
||
{
|
||
id: "cert5", name: "wg-client-admin", serverId: "srv1",
|
||
commonName: "admin.routerlists.io",
|
||
sans: ["admin.routerlists.io"],
|
||
issuedBy: "MikrotikManager Internal CA", validFrom: "2025-06-01",
|
||
validUntil: "2026-06-01", daysLeft: 33,
|
||
keySize: 2048, usage: ["client"], trusted: true, status: "valid",
|
||
},
|
||
{
|
||
id: "cert6", name: "mt-ams-edge-01-server", serverId: "srv4",
|
||
commonName: "mt-ams-edge-01.routerlists.io",
|
||
sans: ["mt-ams-edge-01.routerlists.io"],
|
||
issuedBy: "MikrotikManager Internal CA", validFrom: "2024-04-01",
|
||
validUntil: "2026-05-15", daysLeft: 16,
|
||
keySize: 2048, usage: ["server"], trusted: false, status: "valid",
|
||
},
|
||
{
|
||
id: "cert7", name: "mt-msk-lab-01-server", serverId: "srv7",
|
||
commonName: "mt-msk-lab-01.routerlists.io",
|
||
sans: ["mt-msk-lab-01.routerlists.io","10.0.0.7"],
|
||
issuedBy: "MikrotikManager Internal CA", validFrom: "2025-09-01",
|
||
validUntil: "2026-09-01", daysLeft: 125,
|
||
keySize: 4096, usage: ["server"], trusted: true, status: "valid",
|
||
},
|
||
]
|