Was macht Netzwerk-Konfigurationsvalidierung?
Verwenden Sie diesen Skill, um die Netzwerkkonfiguration vor einem Change-Fenster oder bevor eine Automatisierung Produktionsgeräte berührt, zu überprüfen.
Wann Verwenden
- Überprüfung von Cisco IOS- oder IOS-XE-ähnlichen Snippets vor dem Deployment.
- Audit von generierten Konfigurationen aus Skripten oder Templates.
- Suche nach gefährlichen Befehlen, doppelten IP-Adressen oder Subnetz-Überlappungen.
- Prüfung, ob ACLs, Route-Maps, Prefix-Listen oder Line-Policies referenziert, aber nicht definiert sind.
- Erstellung von schlanken Preflight-Skripten für die Netzwerkautomatisierung.
Wie es Funktioniert
Behandeln Sie die Konfigurationsvalidierung als schichtweise Evidenz, nicht als vollständigen Parser. Regex-Prüfungen sind nützlich für Preflight-Warnungen, aber die endgültige Freigabe erfordert weiterhin einen Netzwerktechniker, der die Absicht, die Plattformsyntax und die Rollback-Schritte überprüft.
Validieren Sie in dieser Reihenfolge:
- Destruktive Befehle.
- Credential- und Management-Ebene-Exposition.
- Doppelte Adressen und überlappende Subnetze.
- Veraltete Referenzen auf ACLs, Route-Maps, Prefix-Listen und Interfaces.
- Betriebshygiene wie NTP, Zeitstempel, Remote-Logging und Banner.
Erkennung Gefährlicher Befehle
import re
GEFAHRLICHE_MUSTER: list[tuple[re.Pattern[str], str]] = [
(re.compile(r"\breload\b", re.I), "Reload verursacht Ausfallzeit"),
(re.compile(r"\berase\s+(startup|nvram|flash)", re.I), "löscht persistenten Speicher"),
(re.compile(r"\bformat\b", re.I), "formatiert ein Geräte-Dateisystem"),
(re.compile(r"\bno\s+router\s+(bgp|ospf|eigrp)\b", re.I), "entfernt einen Routing-Prozess"),
(re.compile(r"\bno\s+interface\s+\S+", re.I), "entfernt Interface-Konfiguration"),
(re.compile(r"\baaa\s+new-model\b", re.I), "ändert das Authentifizierungsverhalten"),
(re.compile(r"\bcrypto\s+key\s+(zeroize|generate)\b", re.I), "ändert Geräte-SSH-Schlüssel"),
]
def finde_gefaehrliche_befehle(zeilen: list[str]) -> list[dict[str, str | int]]:
funde = []
for zeilennummer, zeile in enumerate(zeilen, start=1):
bereinigt = zeile.strip()
for muster, grund in GEFAHRLICHE_MUSTER:
if muster.search(bereinigt):
funde.append({
"zeile": zeilennummer,
"befehl": bereinigt,
"grund": grund,
})
return funde
Doppelte IPs und Subnetz-Überlappungen
import ipaddress
import re
from collections import Counter
IP_ADRESSE_RE = re.compile(
r"^\s*ip address\s+"
r"(?P<ip>\d{1,3}(?:\.\d{1,3}){3})\s+"
r"(?P<maske>\d{1,3}(?:\.\d{1,3}){3})\b",
re.I | re.M,
)
def extrahiere_interfaces(config: str) -> list[dict[str, str]]:
ergebnisse = []
aktuell = None
for zeile in config.splitlines():
if zeile.startswith("interface "):
aktuell = zeile.split(maxsplit=1)[1]
continue
treffer = IP_ADRESSE_RE.match(zeile)
if aktuell and treffer:
ip = treffer.group("ip")
maske = treffer.group("maske")
netzwerk = ipaddress.ip_interface(f"{ip}/{maske}").network
ergebnisse.append({"interface": aktuell, "ip": ip, "netzwerk": str(netzwerk)})
return ergebnisse
def finde_doppelte_ips(config: str) -> list[str]:
ips = [eintrag["ip"] for eintrag in extrahiere_interfaces(config)]
zaehlung = Counter(ips)
return sorted(ip for ip, anzahl in zaehlung.items() if anzahl > 1)
def finde_subnetz_ueberlappungen(config: str) -> list[tuple[str, str]]:
netzwerke = [ipaddress.ip_network(eintrag["netzwerk"]) for eintrag in extrahiere_interfaces(config)]
ueberlappungen = []
for index, links in enumerate(netzwerke):
for rechts in netzwerke[index + 1:]:
if links.overlaps(rechts):
ueberlappungen.append((str(links), str(rechts)))
return ueberlappungen
Management-Ebene-Checks
VTY-Blöcke abschnittsweise parsen, damit Access-Class-Prüfungen nicht auf unabhängige Zeilen übergreifen.
import re
def iteriere_bloecke(config: str, beginnt_mit: str) -> list[str]:
bloecke = []
aktuell: list[str] = []
for zeile in config.splitlines():
if zeile.startswith(beginnt_mit):
if aktuell:
bloecke.append("\n".join(aktuell))
aktuell = [zeile]
continue
if aktuell:
if zeile and not zeile.startswith(" "):
bloecke.append("\n".join(aktuell))
aktuell = []
else:
aktuell.append(zeile)
if aktuell:
bloecke.append("\n".join(aktuell))
return bloecke
def pruefe_vty_bloecke(config: str) -> list[str]:
probleme = []
for block in iteriere_bloecke(config, "line vty"):
if re.search(r"transport\s+input\s+.*telnet", block, re.I):
probleme.append("VTY erlaubt Telnet; nur SSH zulassen.")
if not re.search(r"\baccess-class\s+\S+\s+in\b", block, re.I):
probleme.append("VTY-Block hat keine eingehende Access-Class-Quellenbeschränkung.")
if not re.search(r"\bexec-timeout\s+\d+\s+\d+\b", block, re.I):
probleme.append("VTY-Block hat kein explizites exec-timeout.")
return probleme
Sicherheitshygiene-Checks
SICHERHEITS_MUSTER = [
(re.compile(r"\bsnmp-server community\s+(public|private)\b", re.I),
"Standard-SNMP-Community konfiguriert"),
(re.compile(r"\bsnmp-server community\s+\S+", re.I),
"SNMPv2-Community-String konfiguriert; SNMPv3 authPriv bevorzugen"),
(re.compile(r"\bip ssh version 1\b", re.I),
"SSH Version 1 aktiviert"),
(re.compile(r"\benable password\b", re.I),
"enable password vorhanden; enable secret verwenden"),
(re.compile(r"\busername\s+\S+\s+password\b", re.I),
"Lokaler Benutzername verwendet Passwort statt Secret"),
]
BEST_PRACTICE_MUSTER = [
(re.compile(r"\bntp server\b", re.I), "NTP-Server"),
(re.compile(r"\bservice timestamps\b", re.I), "Log-Zeitstempel"),
(re.compile(r"\blogging\s+\S+", re.I), "Logging-Ziel oder -Puffer"),
(re.compile(r"\bsnmp-server group\s+\S+\s+v3\s+priv\b", re.I), "SNMPv3 authPriv-Gruppe"),
(re.compile(r"\bbanner\s+(login|motd)\b", re.I), "Login-Banner"),
]
def pruefe_sicherheit(config: str) -> list[str]:
return [meldung for muster, meldung in SICHERHEITS_MUSTER if muster.search(config)]
def pruefe_fehlende_hygiene(config: str) -> list[str]:
return [
f"Fehlend: {beschreibung}"
for muster, beschreibung in BEST_PRACTICE_MUSTER
if not muster.search(config)
]
Beispiele
Change-Fenster-Preflight
- Führen Sie Checks auf gefährliche Befehle für das exakte einzufügende Snippet durch.
- Führen Sie Checks auf doppelte IPs und Subnetz-Überlappungen für die vollständige Kandidatenkonfiguration durch.
- Bestätigen Sie, dass jede referenzierte ACL, Route-Map und Prefix-Liste existiert.
- Bestätigen Sie Rollback-Befehle und Out-of-Band-Zugriff vor jeder Änderung an der Management-Ebene.
Automatisierungs-Preflight
Verwenden Sie die Validierung als blockierendes Gate, bevor Netmiko, NAPALM, Ansible oder eine API-Automatisierung eine generierte Konfiguration pusht. Fail closed bei gefährlichen Befehlen und Credentials. Warnen Sie bei Best-Practice-Lücken, die außerhalb des Change-Umfangs liegen.
Anti-Patterns
- Regex-Validierung als Geräteparser behandeln.
- Generierte Konfiguration ohne Dry-Run-Diff anwenden.
- SNMPv2-Community-Strings als Überwachungsanforderung empfehlen.
- VTY-Blöcke mit Regex prüfen, die versehentlich auf unabhängige Abschnitte übergreifen können.
- Firewall-Verhalten testen, indem ACLs deaktiviert werden, anstatt Zähler/Logs zu lesen.
Siehe Auch
- Agent:
network-config-reviewer - Agent:
network-troubleshooter - Skill:
network-interface-health