Skip to content

Instantly share code, notes, and snippets.

@nick-lupien
Created July 4, 2024 15:42
Show Gist options
  • Select an option

  • Save nick-lupien/bb62b77bba4768644c04906c5c169cad to your computer and use it in GitHub Desktop.

Select an option

Save nick-lupien/bb62b77bba4768644c04906c5c169cad to your computer and use it in GitHub Desktop.
pfSense script that parses Kea DHCP conf and lease files and generates an /etc/hosts-like file
#!/bin/sh
# Paths to the necessary files
LEASE_FILE="/var/lib/kea/dhcp4.leases"
KEA_CONF_FILE="/usr/local/etc/kea/kea-dhcp4.conf"
DHCP_HOSTS_FILE="/etc/dhcp-hosts"
TEMP_DHCP_HOSTS_FILE="/tmp/dhcp-hosts.new"
TEMP_DHCP_HOSTS_FILE_SORTED="/tmp/dhcp-hosts.new.sorted"
LOG_DIR="/var/log/dhcp-hosts"
# Ensure the log directory exists
mkdir -p $LOG_DIR
# Extract domain name from kea-dhcp4.conf
extract_domain_name() {
jq -r '.Dhcp4["option-data"][] | select(.name == "domain-name") | .data' $KEA_CONF_FILE
}
# Function to update dhcp-hosts file
update_hosts_file() {
# Extract the domain name
DOMAIN_NAME=$(extract_domain_name)
echo "Domain name extracted: $DOMAIN_NAME"
# Clear the temporary hosts file
> $TEMP_DHCP_HOSTS_FILE
# Ingest static DHCP reservations from the Kea JSON config
jq -r '.Dhcp4.subnet4[].reservations[] | select(.hostname != null and .["ip-address"] != null) | "\(.["ip-address"]) \(.hostname)"' $KEA_CONF_FILE | while read -r entry; do
address=$(echo $entry | awk '{print $1}')
hostname=$(echo $entry | awk '{print $2}' | sed 's/\.$//')
echo "$address $hostname.$DOMAIN_NAME $hostname" >> $TEMP_DHCP_HOSTS_FILE
done
# Ingest DHCP leases
while IFS=',' read -r address hwaddr client_id valid_lifetime expire subnet_id fqdn_fwd fqdn_rev hostname state user_context pool_id; do
# Skip the header line
[ "$address" = "address" ] && continue
# Skip entries without hostname
[ -z "$hostname" ] && continue
# Remove trailing dots from hostname
hostname=$(echo "$hostname" | sed 's/\.$//')
# Add the entry to the temporary file
echo "$address $hostname.$DOMAIN_NAME $hostname" >> $TEMP_DHCP_HOSTS_FILE
done < $LEASE_FILE
# Sort and remove duplicate entries, then create a new sorted hosts file
sort -u -t ' ' -k 1,1 $TEMP_DHCP_HOSTS_FILE > $TEMP_DHCP_HOSTS_FILE_SORTED
# Check if there are any changes
if ! cmp -s $TEMP_DHCP_HOSTS_FILE_SORTED $DHCP_HOSTS_FILE; then
# Log the changes
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
LOG_FILE="$LOG_DIR/dhcp-hosts-changes-$TIMESTAMP.log"
echo "Changes detected in DHCP hosts file:" > $LOG_FILE
diff $DHCP_HOSTS_FILE $TEMP_DHCP_HOSTS_FILE_SORTED >> $LOG_FILE
# If the files are different, replace the old hosts file with the new one
mv $TEMP_DHCP_HOSTS_FILE_SORTED $DHCP_HOSTS_FILE
echo "DHCP hosts file updated. Restarting DNS resolver."
# Restart dnsmasq to apply the changes
pfSsh.php playback svc restart dnsmasq
else
echo "No changes detected in DHCP hosts file. No need to restart DNS resolver."
rm $TEMP_DHCP_HOSTS_FILE_SORTED
fi
# Clean up temporary file
rm $TEMP_DHCP_HOSTS_FILE
}
# Call the function to update the hosts file
update_hosts_file
@nick-lupien
Copy link
Author

nick-lupien commented Jul 4, 2024

How I got here

I recently migrated from ISC DHCP to Kea DHCP in pfSense 24.03-RELEASE (Netgate HW), at Netgate's recommendation. For context, I also run pfSense's DNS Forwarder (dnsmasq), which is supposed to resolve against my local DHCP leases before forwarding to my local DNS (pihole).

Yesterday I edited the DNS Forwarder config with an unrelated custom option (filter-AAAA), and after applying the setting, the DNS Forwarder stopped replying to DNS lookups for my local systems. Even after reverting the custom option, Kea and dnsmasq no longer interacted.

What this script does

This script manually parses Kea's static config and dynamic lease file, and then generates a file (/etc/dhcp-hosts) in dnsmasq format.

Requirements

jq: run pkg install jq from the command prompt
cron: install from the pfSense package manager - do not use crontab

How to automate it

  1. Place this script somewhere like /usr/local/bin and chmod +x it
  2. Install pfSense's cron package and set this script to run every few minutes.
  3. Under DNS Forwarder -> Custom options, add the line addn-hosts=/etc/dhcp-hosts

To make sure it's working, run cat /etc/dhcp-hosts from the command prompt.

Note: this supports IPv4 only.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment