Skip to content

Instantly share code, notes, and snippets.

@seraphyn
Created June 28, 2025 11:34
Show Gist options
  • Select an option

  • Save seraphyn/c9d41ff4920f484e4856158acd3f0957 to your computer and use it in GitHub Desktop.

Select an option

Save seraphyn/c9d41ff4920f484e4856158acd3f0957 to your computer and use it in GitHub Desktop.
ISC DHCP to Kea CSV Import opnSense
#!/bin/bash
# DHCP Lease Extractor Script
# Extrahiert statische Leases aus dhcpd.conf und schreibt sie in eine CSV-Datei
# Standardpfade
DHCPD_CONF="/etc/dhcp/dhcpd.conf"
OUTPUT_CSV="dhcp_leases.csv"
# Funktion zur Anzeige der Hilfe
show_help() {
echo "DHCP Lease Extractor"
echo "Verwendung: $0 [OPTIONEN]"
echo ""
echo "OPTIONEN:"
echo " -f, --file FILE Pfad zur dhcpd.conf Datei (Standard: /etc/dhcp/dhcpd.conf)"
echo " -o, --output FILE Ausgabe CSV-Datei (Standard: dhcp_leases.csv)"
echo " -h, --help Diese Hilfe anzeigen"
echo ""
echo "Beispiel:"
echo " $0 -f /path/to/dhcpd.conf -o output.csv"
}
# Funktion zur IP-zu-Subnet-Konvertierung (wird nicht mehr benötigt, aber beibehalten für eventuelle Erweiterungen)
ip_to_subnet() {
local ip="$1"
if [[ $ip =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then
echo "${BASH_REMATCH[1]}.${BASH_REMATCH[2]}.${BASH_REMATCH[3]}.0/24"
else
echo "unknown"
fi
}
# Parameter parsen
while [[ $# -gt 0 ]]; do
case $1 in
-f|--file)
DHCPD_CONF="$2"
shift 2
;;
-o|--output)
OUTPUT_CSV="$2"
shift 2
;;
-h|--help)
show_help
exit 0
;;
*)
echo "Unbekannte Option: $1" >&2
show_help
exit 1
;;
esac
done
# Prüfen ob dhcpd.conf existiert
if [[ ! -f "$DHCPD_CONF" ]]; then
echo "Fehler: Datei '$DHCPD_CONF' nicht gefunden!" >&2
echo "Verwenden Sie -f um einen anderen Pfad anzugeben." >&2
exit 1
fi
# CSV Header schreiben
echo "ip_address,hw_address,hostname,description" > "$OUTPUT_CSV"
echo "Verarbeite dhcpd.conf: $DHCPD_CONF"
echo "Ausgabe in: $OUTPUT_CSV"
# Temporäre Datei für die Verarbeitung
temp_file=$(mktemp)
# Host-Blöcke extrahieren und verarbeiten
awk '
BEGIN {
in_host = 0
host_name = ""
mac_addr = ""
ip_addr = ""
option_hostname = ""
}
# Host-Block beginnt
/^[[:space:]]*host[[:space:]]+/ {
in_host = 1
# Host-Namen extrahieren
gsub(/^[[:space:]]*host[[:space:]]+/, "")
gsub(/[[:space:]]*{.*$/, "")
host_name = $0
mac_addr = ""
ip_addr = ""
option_hostname = ""
next
}
# Innerhalb eines Host-Blocks
in_host == 1 {
# MAC-Adresse extrahieren
if (/hardware ethernet/) {
gsub(/^[[:space:]]*hardware ethernet[[:space:]]+/, "")
gsub(/;.*$/, "")
gsub(/"/, "")
mac_addr = $0
}
# IP-Adresse extrahieren
if (/fixed-address/) {
gsub(/^[[:space:]]*fixed-address[[:space:]]+/, "")
gsub(/;.*$/, "")
gsub(/"/, "")
ip_addr = $0
}
# Option host-name extrahieren (nur echte option host-name, nicht set hostname-override)
if (/^[[:space:]]*option host-name[[:space:]]/ && !/set hostname-override/) {
gsub(/^[[:space:]]*option host-name[[:space:]]+/, "")
gsub(/;.*$/, "")
gsub(/"/, "")
gsub(/^[[:space:]]+|[[:space:]]+$/, "")
option_hostname = $0
}
# Host-Block endet
if (/^[[:space:]]*}[[:space:]]*$/) {
in_host = 0
# Ausgabe nur wenn alle wichtigen Felder vorhanden sind
if (host_name != "" && mac_addr != "" && ip_addr != "") {
# Wenn option host-name leer ist, verwende host_name
if (option_hostname == "") {
option_hostname = host_name
}
print host_name "|" mac_addr "|" ip_addr "|" option_hostname
}
}
}
' "$DHCPD_CONF" > "$temp_file"
# Verarbeitung der extrahierten Daten
count=0
while IFS='|' read -r duid mac_addr ip_addr hostname; do
if [[ -n "$duid" && -n "$mac_addr" && -n "$ip_addr" ]]; then
# In CSV-Datei schreiben (description bleibt leer, aber Komma wird hinzugefügt)
echo "$ip_addr,$mac_addr,$hostname," >> "$OUTPUT_CSV"
((count++))
fi
done < "$temp_file"
# Aufräumen
rm -f "$temp_file"
echo "Fertig! $count Host-Einträge wurden verarbeitet."
echo "CSV-Datei gespeichert als: $OUTPUT_CSV"
# Erste paar Zeilen der CSV-Datei anzeigen
if [[ $count -gt 0 ]]; then
echo ""
echo "Beispiel der ersten Einträge:"
head -n 5 "$OUTPUT_CSV"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment