Files
MikrotikManager/lib/gre-export.ts

45 lines
3.5 KiB
TypeScript

import type { GreTunnel, Server } from "./data"
import { quoteRosString } from "./vxlan-export"
const commentLine = (value: string) => value.replace(/[\r\n\x00-\x1f\x7f]/g, " ")
const validKeepalive = (t: GreTunnel) => [t.keepaliveInterval, t.keepaliveRetries].every(value => Number.isInteger(value) && value >= 1 && value <= 4294967295)
export function greExportWarnings(t: GreTunnel): string[] {
return [
t.ipsec && !t.ipsec.secret ? "Шаблон: ключ IPsec скрыт. Укажите ключ перед применением." : "",
!validKeepalive(t) ? "Шаблон: задайте допустимый интервал keepalive и число попыток перед применением." : "",
t.ipsec && t.allowFastPath ? "Шаблон: IPsec несовместим с FastPath. Проверьте этот параметр перед применением." : "",
].filter(Boolean)
}
/** GRE/PSK fragment: https://help.mikrotik.com/docs/spaces/ROS/pages/24805531/GRE */
export function generateGreRsc(t: GreTunnel, servers: Record<string, Server>): string {
const server = servers[t.serverId]
const lines = ["# GRE — " + commentLine(t.name)]
if (server) lines.push("# Сервер: " + commentLine(server.name) + " (" + commentLine(server.host) + ")")
lines.push("# Фрагмент интерфейса и локального IP; удалённая сторона и маршруты не включены", "")
if (!validKeepalive(t)) lines.push("# Шаблон: задайте KEEPALIVE_SECONDS и KEEPALIVE_RETRIES — целые значения от 1 до 4294967295.")
if (t.ipsec && t.allowFastPath) lines.push("# Шаблон: IPsec несовместим с FastPath. Проверьте ALLOW_FAST_PATH перед применением.")
const args = [
"name=" + quoteRosString(t.name), "remote-address=" + quoteRosString(t.remoteAddress),
"mtu=" + t.mtu, "keepalive=" + (validKeepalive(t) ? t.keepaliveInterval + "s," + t.keepaliveRetries : "<KEEPALIVE_SECONDS>s,<KEEPALIVE_RETRIES>"),
"dscp=" + t.dscp, "clamp-tcp-mss=" + (t.clampTcpMss ? "yes" : "no"),
"allow-fast-path=" + (t.ipsec && t.allowFastPath ? "<ALLOW_FAST_PATH>" : t.allowFastPath ? "yes" : "no"), "disabled=" + (t.enabled ? "no" : "yes"),
"comment=" + quoteRosString(t.comment),
]
if (t.localAddress && t.localAddress !== "0.0.0.0") args.push("local-address=" + quoteRosString(t.localAddress))
if (t.ipsec) {
if (!t.ipsec.secret) lines.push("# Шаблон: ключ IPsec не раскрыт. Перед применением замените <IPSEC_PSK> своим ключом.")
args.push("ipsec-secret=" + quoteRosString(t.ipsec.secret || "<IPSEC_PSK>"))
}
lines.push("/interface/gre/add " + args.join(" "))
if (t.localInnerIp) {
const ipv6 = t.localInnerIp.includes(":")
if (ipv6) lines.push("# IPv6: новый статический адрес без объявления префикса; pool/EUI-64 и остальные адреса не включены")
lines.push((ipv6 ? "/ipv6/address/add" : "/ip/address/add") + " address=" + quoteRosString(t.localInnerIp) + " interface=" + quoteRosString(t.name) + (ipv6 ? " advertise=no" : ""))
}
if (t.ipsec) lines.push("# Peer/policy создаёт RouterOS по ipsec-secret; ручные объекты IPsec не экспортируются")
if (t.ipsec && t.allowFastPath) lines.push("# В снимке включён FastPath: для GRE с IPsec документация RouterOS требует allow-fast-path=no")
return lines.join("\n") + "\n"
}