dnsmasq: store leases in sqlite database
To avoid dnsmasq writing out the whole leasefile on each request before replying. This gets slow on high‐latency storage. Also tweak DNS updates a bit.
This commit is contained in:
parent
b6b4a16fd4
commit
8e3772e475
|
@ -2,9 +2,10 @@
|
|||
package:
|
||||
name:
|
||||
- dnsmasq
|
||||
- bind-tools
|
||||
- krb5
|
||||
- py3-pexpect
|
||||
- bind-tools # for DNS updates
|
||||
- krb5 # for DNS updates
|
||||
- py3-pexpect # for creating kerberos keytab
|
||||
- sqlite # for lease DB
|
||||
|
||||
- name: Configure kerberos
|
||||
template:
|
||||
|
@ -23,11 +24,11 @@
|
|||
args:
|
||||
creates: /etc/krb5.keytab
|
||||
|
||||
- name: Copy DNS updater script
|
||||
- name: Copy DHCP lease script
|
||||
template:
|
||||
dest: "/usr/local/bin/dns-update"
|
||||
src: "dns-update.j2"
|
||||
mode: 0700
|
||||
dest: "/usr/local/bin/dnsmasq-script"
|
||||
src: "dnsmasq-script.j2"
|
||||
mode: 0755
|
||||
|
||||
- name: Configure dnsmasq
|
||||
template:
|
||||
|
|
|
@ -18,4 +18,8 @@ interface = {{ interfaces | map(attribute='name') | join(',') }}
|
|||
dhcp-option = option:dns-server,{{ dns | join(',') }}
|
||||
dhcp-option = option:ntp-server,{{ ntp | join(',') }}
|
||||
|
||||
dhcp-script = /usr/local/bin/dns-update
|
||||
dhcp-script = /usr/local/bin/dnsmasq-script
|
||||
dhcp-scriptuser = dnsmasq
|
||||
|
||||
# track leases with dnsmasq-script instead
|
||||
leasefile-ro
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
# don’t spam the DNS server when starting dnsmasq
|
||||
if [ -n "${DNSMASQ_INTERFACE}" ] ; then
|
||||
exit
|
||||
fi
|
||||
|
||||
domain={{ domain }}
|
||||
ldap_user={{ password.ldap_user }}
|
||||
ttl=3600
|
||||
|
||||
address="${3}"
|
||||
|
||||
case "${1}" in
|
||||
add)
|
||||
host="${4}"
|
||||
kinit -k "${ldap_user}"
|
||||
nsupdate -g <<EOF
|
||||
update add ${host}.${domain} ${ttl} A ${address}
|
||||
send
|
||||
EOF
|
||||
;;
|
||||
old)
|
||||
if [ -n "${DNSMASQ_OLD_HOSTNAME}" -a -n "${DNSMASQ_SUPPLIED_HOSTNAME}" ] ; then
|
||||
kinit -k "${ldap_user}"
|
||||
nsupdate -g <<EOF
|
||||
update del ${DNSMASQ_OLD_HOSTNAME}.${domain}
|
||||
update add ${DNSMASQ_SUPPLIED_HOSTNAME}.${domain} ${ttl} A ${address}
|
||||
send
|
||||
EOF
|
||||
fi
|
||||
;;
|
||||
# TODO del, probably
|
||||
esac
|
76
roles/dnsmasq/templates/dnsmasq-script.j2
Normal file
76
roles/dnsmasq/templates/dnsmasq-script.j2
Normal file
|
@ -0,0 +1,76 @@
|
|||
#!/bin/sh
|
||||
|
||||
# This script replaces the dnsmasq leasefile with an sqlite database
|
||||
# for performance on slow storage, and updates DNS records for
|
||||
# assigned addresses.
|
||||
|
||||
cmd="${1}"
|
||||
|
||||
# dnsmasq calls this script on startup for each known lease, ignore it
|
||||
[ "${cmd}" != "init" ] && [ -z "${DNSMASQ_INTERFACE}" ] && exit 0
|
||||
|
||||
# parameters
|
||||
db=/var/lib/misc/dnsmasq.leases.db
|
||||
domain={{ domain }}
|
||||
ldap_user={{ password.ldap_user }}
|
||||
ttl=3600
|
||||
|
||||
# sanitize input
|
||||
mac="${2//[![:xdigit:]:]/}"
|
||||
ipv4="${3//[![:digit:].]/}"
|
||||
hostname="${4//[![:alnum:]_-]/}"
|
||||
client_id="${DNSMASQ_CLIENT_ID//[![:xdigit:]:]/}"
|
||||
|
||||
# construct SQL to query or update leases, and nsupdate script to update DNS records
|
||||
dns=""
|
||||
sql=""
|
||||
case "${cmd}" in
|
||||
"init")
|
||||
# init runs as root, so ensure the dnsmasq user can write to database later
|
||||
touch "${db}"
|
||||
chown dnsmasq:dnsmasq "${db}"
|
||||
setfacl -m u:dnsmasq:rwx "$(dirname ${db})"
|
||||
setfacl -m u:dnsmasq:r "/etc/krb5.keytab" # needed for DNS updates
|
||||
|
||||
# ensure the leases table exists, and get all leases from it
|
||||
sql="CREATE TABLE IF NOT EXISTS leases (
|
||||
ipv4 TEXT PRIMARY KEY NOT NULL,
|
||||
mac TEXT NOT NULL,
|
||||
hostname TEXT NOT NULL,
|
||||
client_id TEXT NOT NULL,
|
||||
renewed INTEGER NOT NULL);
|
||||
SELECT renewed, mac, ipv4, hostname, client_id FROM leases;"
|
||||
;;
|
||||
|
||||
"add" | "old")
|
||||
# add or update the lease
|
||||
sql="INSERT INTO leases
|
||||
VALUES ('${ipv4}', '${mac}', '${hostname:-*}', '${client_id:-*}', unixepoch())
|
||||
ON CONFLICT(ipv4) DO UPDATE SET renewed = unixepoch();"
|
||||
|
||||
# add or update the DNS record
|
||||
if [ -n "${hostname}" ] ; then
|
||||
dns="update add ${hostname}.${domain} ${ttl} A ${ipv4}\n"
|
||||
fi
|
||||
if [ -n "${DNSMASQ_OLD_HOSTNAME}" ] ; then
|
||||
dns="${dns}update del ${DNSMASQ_OLD_HOSTNAME}.${domain}\n"
|
||||
fi
|
||||
;;
|
||||
|
||||
"del")
|
||||
# delete the lease
|
||||
sql="DELETE FROM leases WHERE ipv4 = '${ipv4}';"
|
||||
# TODO probably delete the DNS record
|
||||
;;
|
||||
esac
|
||||
|
||||
# update lease database
|
||||
if [ -n "${sql}" ]; then
|
||||
sqlite3 -separator " " "${db}" "${sql}"
|
||||
fi
|
||||
|
||||
# update DNS records
|
||||
if [ -n "${dns}" ]; then
|
||||
kinit -k "${ldap_user}"
|
||||
echo -e "${dns}send" | nsupdate -g
|
||||
fi
|
Loading…
Reference in a new issue