KI statt Handarbeit: OPNsense automatisch dokumentieren und aus der Firewall-Konfiguration einen fertigen Report erzeugen
Eine Firewall ist in vielen Netzwerken nicht nur ein technisches Gerät am Rand des Netzes. Sie ist oft der zentrale Knotenpunkt für Routing, VLANs, DHCP, DNS, VPN-Verbindungen, NAT, Sicherheitsregeln und administrative Zugänge. Genau deshalb ist eine saubere Dokumentation so wichtig. Wer eine OPNsense-Installation betreibt, kennt aber auch die andere Seite: Die Konfiguration wächst über Jahre, wird bei Störungen angepasst, bei Migrationen erweitert und bei neuen Anforderungen schnell ergänzt. Die Dokumentation bleibt dabei häufig zurück.
Das Projekt opnsense-report setzt genau an diesem Punkt an. Es unterstützt dabei, aus einer exportierten OPNsense-Konfiguration automatisch eine strukturierte, deutschsprachige Dokumentation zu erzeugen. Statt jede Schnittstelle, jedes VLAN und jede relevante Dienstkonfiguration manuell zusammenzutragen, verarbeitet das Projekt die config.xml, entfernt sensible Informationen und erstellt daraus eine gut lesbare Markdown-Datei. Zusätzlich kann aus dieser Markdown-Datei eine formatierte HTML-Ansicht erzeugt werden.
Das Repository ist hier zu finden: GitHub Repository
Warum eine automatisierte OPNsense-Dokumentation sinnvoll ist
Netzwerkdokumentation ist selten das Problem, wenn alles funktioniert. Sie wird wichtig, sobald etwas nicht funktioniert, jemand Neues das System übernehmen soll oder eine Änderung vorbereitet wird. Dann zählt nicht nur, welche Einstellungen aktuell aktiv sind, sondern auch, ob diese Informationen vollständig, nachvollziehbar und schnell verfügbar sind.
Bei Firewalls ist das besonders kritisch. Eine einzelne Regel kann entscheiden, ob ein Dienst erreichbar ist oder nicht. Ein falsch verstandenes VLAN kann eine Migration verzögern. Eine nicht dokumentierte VPN-Verbindung kann im Störungsfall wertvolle Zeit kosten. Und wenn DHCP, DNS, Routing und Firewall-Regeln zusammenwirken, reicht ein Blick in einen einzelnen Menüpunkt oft nicht aus.
Manuelle Dokumentation hat dabei drei typische Schwächen. Erstens ist sie oft veraltet. Zweitens ist sie abhängig davon, wie sorgfältig sie gepflegt wurde. Drittens bildet sie selten den echten Konfigurationsstand ab, sondern nur das, was jemand einmal aufgeschrieben hat. Eine automatisch generierte Dokumentation kann diese Probleme nicht vollständig lösen, aber sie schafft eine deutlich bessere Grundlage: Sie beginnt beim tatsächlichen Export der Firewall-Konfiguration.
opnsense-report ist deshalb kein Ersatz für fachliches Verständnis. Es ist ein Werkzeug, das aus vorhandenen Konfigurationsdaten eine lesbare, prüfbare und wiederholbare Dokumentation erzeugt. Der Mensch bewertet weiterhin, ob Regeln sinnvoll sind, ob Netze richtig getrennt wurden und ob Empfehlungen umgesetzt werden sollen. Das Projekt nimmt ihm aber die mühsame Erstarbeit ab.
Was das Projekt macht
Der Kern des Projekts besteht aus drei Python-Skripten. Jedes Skript hat eine klar abgegrenzte Aufgabe.
cleanup.py bereinigt eine OPNsense-Konfigurationsdatei. Dabei werden XML-Elemente entfernt oder geleert, deren Namen auf sensible Inhalte hindeuten. Dazu gehören beispielsweise Passwörter, Tokens, Secrets, private Schlüssel, Pre-Shared Keys und ähnliche sicherheitskritische Werte. Ziel ist, dass keine Geheimnisse in die weitere Verarbeitung oder in die erzeugte Dokumentation gelangen.
create.py ist der eigentliche Generator. Das Skript sucht eine passende OPNsense-Konfiguration, bereinigt sie, baut daraus einen Prompt und ruft die OpenAI Responses API auf. Das Modell erhält dabei klare Regeln: Es soll eine vollständige Markdown-Dokumentation auf Deutsch erzeugen, keine Werte erfinden, nicht sichtbare Werte als solche kennzeichnen und keine Geheimnisse ausgeben. Die Ausgabe wird anschließend normalisiert und als doku.md gespeichert.
render.py wandelt die erzeugte Markdown-Datei in eine HTML-Datei um. Dabei entsteht kein schwergewichtiges Webprojekt, sondern eine eigenständige, gut lesbare doku.html mit eingebettetem Styling. Tabellen, Überschriften, Metadaten und technische Werte werden so aufbereitet, dass die Dokumentation auch außerhalb eines Markdown-Editors gut nutzbar ist.
Das Ergebnis ist ein einfacher Workflow: OPNsense-Konfiguration exportieren, Skript ausführen, Markdown und HTML erhalten.
Ein Blick in den Code
Spannend an opnsense-report ist, dass das Projekt keinen großen Framework-Überbau braucht. Die eigentliche Logik ist gut nachvollziehbar und auf wenige Skripte verteilt. Genau das macht den Ansatz robust: Erst werden sensible Daten entfernt, dann wird die bereinigte Konfiguration an die KI-gestützte Dokumentation übergeben, danach wird das Ergebnis als HTML gerendert.
Der erste wichtige Baustein steckt in cleanup.py. Dort wird definiert, welche XML-Tags als sensibel gelten:
SENSITIVE_NAME_PARTS = (
"password",
"passwd",
"passphrase",
"preshared",
"pre_shared",
"secret",
"salt",
"token",
"credential",
)
SENSITIVE_EXACT_TAGS = {
"key",
"keys",
"keysig",
"privkey",
"privatekey",
"psk",
}Dieser Code ist bewusst defensiv. Er verlässt sich nicht darauf, dass eine OPNsense-Konfiguration alle Geheimnisse immer an exakt derselben Stelle speichert. Stattdessen werden Tag-Namen nach typischen Begriffen durchsucht. Wenn ein XML-Element zum Beispiel password, secret oder privatekey enthält, wird es als kritisch behandelt. Zusätzlich gibt es exakte Treffer wie psk oder privkey, weil diese Begriffe sehr direkt auf Schlüsselmaterial oder VPN-Geheimnisse hindeuten.
Die eigentliche Bereinigung passiert rekursiv:
def scrub_tree(root: ET.Element) -> int:
removed = 0
def walk(elem: ET.Element) -> None:
nonlocal removed
for child in list(elem):
if is_sensitive_tag(child.tag):
child.clear()
child.text = ""
removed += 1
else:
walk(child)
walk(root)
return removedDie Funktion läuft durch den XML-Baum und prüft jedes Kind-Element. Wird ein sensibler Tag erkannt, wird das Element geleert. Wichtig ist: Die Struktur der XML-Datei bleibt grundsätzlich erhalten, aber der kritische Inhalt verschwindet. Das ist für die spätere Dokumentation ideal. Das Modell kann weiterhin erkennen, dass ein bestimmter Bereich existiert, bekommt aber keine Passwörter, Tokens oder Schlüsselwerte zu sehen.
Der zweite zentrale Baustein liegt in create.py. Dort wird die Eingabedatei gefunden und anschließend bereinigt:
def find_config() -> Path:
if Path("config.xml").exists():
return Path("config.xml")
matches = sorted(
path
for path in Path(".").glob("config*.xml")
if not path.stem.endswith("-clean")
)
if not matches:
raise FileNotFoundError("Keine config.xml oder config*.xml im aktuellen Ordner gefunden.")
if len(matches) > 1:
names = ", ".join(str(path) for path in matches)
raise RuntimeError(
f"Mehrere Config-Dateien gefunden: {names}. Bitte mit --config explizit auswählen."
)
return matches[0]Diese Funktion macht das Werkzeug angenehm nutzbar. Im Standardfall legt man einfach eine config.xml in den Projektordner. Wenn keine Datei mit diesem Namen existiert, sucht das Skript nach passenden Alternativen. Findet es mehrere mögliche Konfigurationsdateien, bricht es bewusst ab. Das ist die richtige Entscheidung, weil bei Firewall-Dokumentation keine falsche Datei verarbeitet werden sollte. Der Benutzer muss dann mit --config eindeutig festlegen, welche Konfiguration gemeint ist.
Danach folgt die Bereinigung:
def clean_config(source: Path, target: Path) -> int:
tree = ET.parse(source)
removed = scrub_tree(tree.getroot())
tree.write(target, encoding="utf-8", xml_declaration=True)
return removedHier sieht man die klare Trennung im Ablauf. Die Originaldatei wird gelesen, der XML-Baum wird bereinigt und das Ergebnis wird als neue Datei geschrieben. Die Rückgabe removed ist praktisch, weil das Skript später ausgeben kann, wie viele sensible Elemente bereinigt wurden. Das schafft Transparenz und hilft beim Plausibilitätscheck.
Die KI-Komponente wird ebenfalls in create.py angesteuert:
client = OpenAI()
request = {
"model": model,
"instructions": SYSTEM_MESSAGE,
"input": user_prompt,
"max_output_tokens": max_output_tokens,
}
response = client.responses.create(**request)Der entscheidende Punkt ist hier die Trennung zwischen instructions und input. Die instructions enthalten die festen Regeln für die Dokumentation: Deutsch schreiben, korrekte Umlaute verwenden, keine Werte erfinden, Geheimnisse nicht ausgeben und eine klare Abschnittsstruktur einhalten. Der input enthält dagegen die konkrete bereinigte OPNsense-Konfiguration. Damit wird aus einer technischen XML-Datei eine strukturierte Markdown-Dokumentation.
Auch die Ausgabe wird geprüft, bevor sie gespeichert wird:
def normalize_markdown(text: str) -> str:
cleaned = text.strip()
fence = re.fullmatch(r"```(?:markdown|md)?\s*(.*?)```", cleaned, re.DOTALL | re.IGNORECASE)
if fence:
cleaned = fence.group(1).strip()
if not cleaned.startswith("# "):
raise RuntimeError("Die OpenAI-Ausgabe sieht nicht wie eine vollständige Markdown-Dokumentation aus.")
return cleaned.rstrip() + "\n"Diese Funktion entfernt optional gesetzte Markdown-Codeblöcke und prüft, ob die Antwort wie ein vollständiges Markdown-Dokument beginnt. Das ist kein vollständiger Validator, aber ein sinnvoller Schutz gegen offensichtlich falsche API-Ausgaben. Gerade bei automatisierten Dokumentationsprozessen ist so eine kleine Qualitätskontrolle wertvoll.
Der dritte Baustein ist render.py. Dieses Skript macht aus Markdown eine eigenständige HTML-Datei. Ein Beispiel ist die Tabellenverarbeitung:
def render_table(lines: list[str], start: int) -> tuple[str, int]:
headers = split_table_row(lines[start])
rows: list[list[str]] = []
i = start + 2
while i < len(lines) and lines[i].strip().startswith("|"):
rows.append(split_table_row(lines[i]))
i += 1
output = ["<div class=\"table-wrap\"><table>", "<thead><tr>"]
output.extend(f"<th>{inline_markup(cell)}</th>" for cell in headers)
output.append("</tr></thead><tbody>")Die Funktion erkennt Markdown-Tabellen, trennt Kopfzeilen und Datenzeilen und baut daraus HTML. Das ist genau auf den Zweck des Projekts zugeschnitten, weil technische Firewall-Dokumentation viele strukturierte Tabellen enthält. Interfaces, VLANs, DHCP-Bereiche, VPN-Parameter und Firewall-Regeln lassen sich tabellarisch deutlich besser lesen als in langen Fließtexten.
Am Ende wird das HTML-Dokument mit eingebettetem CSS gebaut:
def build_html(title: str, body: str, meta: list[str]) -> str:
meta_html = "\n".join(f"<span>{inline_markup(item)}</span>" for item in meta)
return f"""<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{html.escape(title)}</title>
<style>{STYLE}</style>
</head>Das Ergebnis ist eine portable HTML-Datei ohne zusätzliche Build-Pipeline. Man braucht keinen Webserver, kein Frontend-Framework und keine Datenbank. Für technische Dokumentation ist das oft genau richtig: Datei öffnen, lesen, archivieren, weitergeben.
Der typische Ablauf
Am Anfang steht der Export der OPNsense-Konfiguration. OPNsense stellt ihre Konfiguration als XML-Datei bereit. Diese Datei enthält viele Informationen, die für eine Dokumentation relevant sind: Interfaces, VLANs, Dienste, Firewall-Regeln, VPN-Einstellungen, DHCP-Bereiche, DNS-Konfigurationen und weitere Systemdetails.
Genau diese Datei enthält aber häufig auch sensible Inhalte oder zumindest sicherheitsrelevante Konfigurationsfragmente. Deshalb verarbeitet opnsense-report nicht einfach blind die Originaldatei weiter. Zuerst wird eine bereinigte Variante erzeugt. Standardmäßig entsteht daraus eine Datei wie config-clean.xml.
Erst diese bereinigte Konfiguration wird an den Dokumentationsgenerator übergeben. Das ist ein wichtiger Architekturpunkt. Die Trennung zwischen Originaldatei, bereinigter XML-Datei, Markdown-Ausgabe und HTML-Ausgabe macht den Ablauf nachvollziehbar. Wer prüfen möchte, was genau verarbeitet wurde, kann die bereinigte XML-Datei kontrollieren. Wer die Dokumentation anpassen möchte, kann dies in Markdown tun. Wer eine lesbare Ansicht braucht, öffnet die HTML-Datei.
Diese Aufteilung ist auch praktisch für den Betrieb. Die Dokumentation kann nach jeder relevanten Firewall-Änderung neu erzeugt werden. Dadurch entsteht nicht nur eine einmalige Bestandsaufnahme, sondern ein wiederholbarer Prozess.
Installation und Vorbereitung
Voraussetzung ist eine lokale Python-Installation. Das Projekt ist bewusst schlank gehalten und benötigt keine komplexe Infrastruktur. Für die Generierung über die OpenAI API wird das Python-Paket openai benötigt. Außerdem muss ein API-Schlüssel vorhanden sein.
Ein typischer Start sieht so aus:
git clone <LINK_ZUM_REPOSITORY>
cd opnsense-report
python -m pip install openaiDer API-Schlüssel kann als Umgebungsvariable gesetzt werden:
$env:OPENAI_API_KEY="dein-api-schluessel"Alternativ kann im Projektordner eine .env-Datei liegen. Das Skript create.py lädt diese Datei und übernimmt dort gesetzte Variablen, sofern sie noch nicht in der Umgebung vorhanden sind. Ein minimaler Inhalt wäre:
OPENAI_API_KEY=dein-api-schluesselDie OPNsense-Konfiguration wird anschließend als config.xml im Projektordner abgelegt. Das ist der einfachste Fall, weil create.py diese Datei automatisch findet. Wer einen anderen Dateinamen nutzen möchte, kann den Pfad über einen Parameter angeben.
Dokumentation erzeugen
Wenn config.xml im Projektordner liegt und der API-Schlüssel gesetzt ist, genügt:
python create.pyDas Skript führt dann mehrere Schritte aus. Zuerst wird die XML-Datei geladen. Anschließend werden sensible Elemente bereinigt. Danach wird aus der bereinigten Konfiguration ein Prompt erzeugt. Dieser Prompt enthält klare Vorgaben für die Struktur der Dokumentation. Dazu zählen unter anderem ein Kurzüberblick, System- und Basisdienste, Interface-Übersichten, VLAN-Dokumentation, DHCP und DNS, VPN, Firewall- und Routing-Kontext, Auffälligkeiten, Empfehlungen und eine Zusammenfassung der Netze.
Die erzeugte Markdown-Datei wird standardmäßig als doku.md gespeichert. Wenn Rendering nicht deaktiviert wurde, ruft create.py danach automatisch render.py auf und erzeugt zusätzlich doku.html.
Wer nur die Markdown-Datei erzeugen möchte, kann das Rendering überspringen:
python create.py --skip-renderWer eine andere Eingabedatei verwenden möchte, nutzt:
python create.py --config pfad\zur\config.xmlAuch Zielpfade lassen sich anpassen. So kann die bereinigte Konfiguration, die Markdown-Datei oder die HTML-Datei unter einem anderen Namen gespeichert werden. Das ist nützlich, wenn mehrere OPNsense-Systeme dokumentiert werden sollen oder wenn verschiedene Stände miteinander verglichen werden.
HTML aus Markdown rendern
Falls doku.md bereits vorhanden ist oder nachträglich angepasst wurde, kann die HTML-Datei separat neu erzeugt werden:
python render.py doku.md doku.htmlDas Rendering ist bewusst einfach gehalten. Es unterstützt die typischen Elemente, die für diese technische Dokumentation gebraucht werden: Überschriften, Absätze, Listen, Tabellen, Inline-Code und hervorgehobene Hinweise. Dadurch bleibt das Ergebnis portabel. Die erzeugte HTML-Datei kann lokal geöffnet, weitergegeben, archiviert oder in interne Dokumentationssysteme übernommen werden.
Ein weiterer Vorteil: Markdown bleibt die Quelle, die leicht überprüft und versioniert werden kann. HTML ist die komfortable Ansicht für Leserinnen und Leser.
Sicherheit: Warum Bereinigung der wichtigste Schritt ist
Eine Firewall-Konfiguration ist kein harmloses Dokument. Sie kann Namen, interne Strukturen, Zugangsdaten, Schlüsselmaterial und andere sicherheitsrelevante Informationen enthalten. Deshalb ist der Bereinigungsschritt nicht nur ein nettes Extra, sondern ein zentraler Bestandteil des Projekts.
cleanup.py sucht nach XML-Tags, die aufgrund ihres Namens sensibel sein können. Dazu zählen zum Beispiel Bezeichnungen mit password, secret, token, credential, privatekey oder psk. Auch ganze Container wie API-Schlüsselbereiche oder Key-Pair-Strukturen werden berücksichtigt. Gleichzeitig gibt es Ausnahmen für Begriffe, die ähnlich aussehen, aber nicht zwingend Geheimnisse darstellen.
Trotzdem bleibt eine wichtige Regel bestehen: Automatische Bereinigung ersetzt keine Prüfung. Vor allem wenn eine Dokumentation intern weitergegeben oder extern veröffentlicht wird, sollte sie vorher gelesen werden. Das gilt auch für vermeintlich harmlose Werte. Interne Netzpläne, Hostnamen, VPN-Gegenstellen oder Dienstnamen können bereits genug Kontext liefern, um Angriffsflächen besser zu verstehen. Für eine öffentliche Veröffentlichung sollte man deshalb sehr zurückhaltend sein und konkrete Infrastrukturdetails entfernen.
Der sinnvolle Einsatzbereich liegt vor allem in internen Betriebs-, Übergabe- und Audit-Dokumentationen. Dort ist die technische Tiefe erwünscht, aber Geheimnisse dürfen trotzdem nicht auftauchen.
Wieso, weshalb, warum: Der praktische Nutzen
Der größte Nutzen liegt in der Zeitersparnis. Eine umfangreiche Firewall manuell zu dokumentieren, kostet schnell viele Stunden. Interfaces müssen geprüft, VLANs zugeordnet, DHCP-Bereiche gesammelt, DNS-Dienste verstanden und Firewall-Regeln interpretiert werden. Bei VPNs kommt noch hinzu, dass lokale und entfernte Netze, Authentifizierungsmethoden und Security Associations oft an mehreren Stellen auftauchen.
Mit opnsense-report entsteht daraus ein erster vollständiger Entwurf. Dieser Entwurf ist nicht das Ende der Arbeit, aber ein sehr guter Anfang. Statt bei null zu beginnen, prüft man eine bereits strukturierte Dokumentation. Das verschiebt den Aufwand von der Datensammlung zur fachlichen Bewertung.
Ein weiterer Nutzen ist die Wiederholbarkeit. Wenn Änderungen an der Firewall durchgeführt werden, kann die Dokumentation erneut erzeugt werden. Damit wird sichtbar, was sich verändert hat. In Kombination mit Git kann man verschiedene Dokumentationsstände vergleichen und nachvollziehen, wann welche Struktur angepasst wurde.
Auch bei Migrationen ist das hilfreich. Wer eine bestehende OPNsense-Installation auf neue Hardware, in eine andere Netzwerkstruktur oder in ein anderes Sicherheitskonzept überführt, braucht eine belastbare Übersicht. Welche Netze existieren? Welche Dienste hängen daran? Wo gibt es VPN-Abhängigkeiten? Welche Regeln sind besonders breit gefasst? Eine automatisch erzeugte Dokumentation liefert dafür eine Grundlage, die deutlich besser ist als ein manueller Blick durch zahlreiche Weboberflächen-Seiten.
Für Teams ist außerdem der Übergabeeffekt relevant. Wenn nur eine Person die Firewall wirklich kennt, entsteht ein betriebliches Risiko. Eine aktuelle, lesbare Dokumentation reduziert diese Abhängigkeit. Neue Kolleginnen und Kollegen können sich schneller einarbeiten, externe Dienstleister bekommen eine strukturierte Grundlage und im Störungsfall muss nicht erst rekonstruiert werden, wie das System aufgebaut ist.
Grenzen des Werkzeugs
Das Projekt kann nur dokumentieren, was in der Konfigurationsdatei sichtbar ist. Laufzeitinformationen, aktuelle Lease-Tabellen, tatsächliche VPN-Zustände, ARP-Tabellen oder Live-Metriken sind nicht automatisch Bestandteil der exportierten XML-Konfiguration. Wenn solche Informationen benötigt werden, müssen sie zusätzlich erhoben oder separat dokumentiert werden.
Außerdem bewertet das Werkzeug technische Konfigurationen nur eingeschränkt. Es kann Auffälligkeiten sichtbar machen und Empfehlungen formulieren, aber es kennt nicht den organisatorischen Kontext. Eine breite Firewall-Regel kann ein Problem sein, sie kann aber auch bewusst für eine Übergangsphase gesetzt worden sein. Ein deaktivierter Dienst kann vergessen worden sein oder genau dem gewünschten Zielzustand entsprechen. Die Dokumentation ist deshalb eine Entscheidungsgrundlage, keine automatische Freigabe.
Auch die Qualität der generierten Dokumentation hängt von der Qualität und Vollständigkeit der Eingabedaten ab. Wenn die Konfiguration historisch gewachsen ist, uneinheitliche Namen verwendet oder alte Einträge enthält, wird das im Report sichtbar. Das ist aber eher ein Vorteil als ein Nachteil: Solche Stellen werden endlich greifbar.
Fazit
opnsense-report ist ein pragmatisches Werkzeug für alle, die OPNsense-Konfigurationen nicht nur betreiben, sondern auch nachvollziehbar dokumentieren möchten. Es verbindet drei Dinge, die im Alltag wichtig sind: Bereinigung sensibler Daten, automatische Strukturierung und eine lesbare Ausgabe in Markdown und HTML.
Der Ansatz ist besonders nützlich für Bestandsaufnahmen, Migrationen, Audits, Übergaben und regelmäßige Dokumentationsläufe nach größeren Änderungen. Er ersetzt nicht die fachliche Prüfung durch Administratorinnen und Administratoren, aber er sorgt dafür, dass diese Prüfung auf einer deutlich besseren Grundlage beginnt.
Wer OPNsense produktiv einsetzt und bisher keine aktuelle Dokumentation hat, bekommt mit diesem Projekt einen schnellen Einstieg in einen wiederholbaren Dokumentationsprozess. Der erste Lauf liefert eine strukturierte Momentaufnahme. Die eigentliche Stärke entsteht aber, wenn dieser Prozess regelmäßig wiederholt und die Ergebnisse versioniert werden.
Repository: GitHub Repository
