feat(mcp): подготовить сервер и доступ к приёмке
This commit is contained in:
commit
bf3d50e1ff
3835 files changed
+537122
No files matched your search
+854
@@ -0,0 +1,854 @@
|
||||
export type ServerStatus = "online" | "offline" | "degraded" | "unknown"
|
||||
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 | null
|
||||
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 type FirewallTable = "filter" | "nat" | "mangle" | "raw"
|
||||
|
||||
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
|
||||
family?: "ip" | "ip6" | "any"
|
||||
table?: FirewallTable
|
||||
serverId?: string
|
||||
serverName?: string
|
||||
rosId?: string
|
||||
tlsHost?: string
|
||||
connRateLimit?: string
|
||||
layer7Proto?: string
|
||||
nfqueueId?: number
|
||||
log?: boolean
|
||||
logPrefix?: string
|
||||
}
|
||||
|
||||
export interface FirewallAddressListEntry {
|
||||
id: string
|
||||
list: string
|
||||
address: string
|
||||
comment: string
|
||||
disabled: boolean
|
||||
timeout?: string
|
||||
family?: "ip" | "ip6"
|
||||
serverId?: string
|
||||
serverName?: string
|
||||
rosId?: string
|
||||
}
|
||||
|
||||
export interface Backup {
|
||||
id: string
|
||||
server: string
|
||||
serverId?: string | null
|
||||
filename: string
|
||||
size: string
|
||||
sizeBytes?: number
|
||||
created: string
|
||||
kind: "auto" | "manual"
|
||||
notes: string
|
||||
storage: "local" | "s3" | "both"
|
||||
uploadError?: string
|
||||
localFileStatus?: "available" | "missing" | "unknown" | "not-stored"
|
||||
}
|
||||
|
||||
// ─── 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 | null
|
||||
mtu?: number // actual interface MTU; absent in legacy snapshots
|
||||
arpProxy: boolean
|
||||
arpMode?: "disabled" | "enabled" | "local-proxy-arp" | "proxy-arp" | "reply-only"
|
||||
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
|
||||
rosId?: 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", table: "filter", family: "ip", serverId: "srv1", serverName: "mt-msk-core-01", rosId: "*1", 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", table: "mangle", family: "ip", serverId: "srv1", serverName: "mt-msk-core-01", rosId: "*1", 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", table: "nat", family: "ip", serverId: "srv1", serverName: "mt-msk-core-01", rosId: "*1", 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", table: "filter", family: "ip", serverId: "srv1", serverName: "mt-msk-core-01", rosId: "*2", 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", table: "filter", family: "ip", serverId: "srv1", serverName: "mt-msk-core-01", rosId: "*3", 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", table: "filter", family: "ip", serverId: "srv1", serverName: "mt-msk-core-01", rosId: "*4", 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 },
|
||||
{ id: "fw7", table: "filter", family: "ip6", serverId: "srv1", serverName: "mt-msk-core-01", rosId: "*1", chain: "input", action: "accept", proto: "icmpv6", src: "fe80::/10", dst: "—", port: "—", iface: "—", comment: "IPv6 link-local ICMPv6", enabled: true, hits: 1204 },
|
||||
{ id: "fw8", table: "filter", family: "ip6", serverId: "srv1", serverName: "mt-msk-core-01", rosId: "*2", chain: "forward", action: "accept", proto: "tcp", src: "2a01:4f8::/32", dst: "::/0", port: "443", iface: "wan-bgp", comment: "IPv6 HTTPS forward", enabled: true, hits: 88421 },
|
||||
]
|
||||
|
||||
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: "снапшот перед обновлением", storage: "local" },
|
||||
{ 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: "", storage: "local" },
|
||||
{ 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: "", storage: "s3" },
|
||||
{ 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", storage: "both" },
|
||||
{ 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: "", storage: "local" },
|
||||
]
|
||||
|
||||
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
|
||||
/** Live CHR отдаёт только secret; proposal-поля есть у моков / формы */
|
||||
encAlg?: IpsecEncAlg
|
||||
authAlg?: IpsecAuthAlg
|
||||
dhGroup?: IpsecDhGroup
|
||||
ikeVersion?: IkeVersion
|
||||
lifetime?: string
|
||||
pfs?: boolean
|
||||
}
|
||||
|
||||
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",
|
||||
},
|
||||
]
|
||||
Reference in new issue
Block a user