From 9516b633fa651875503bb61b5194bfb7e5f409e3 Mon Sep 17 00:00:00 2001 From: Franck Cuny Date: Thu, 6 Apr 2023 17:37:27 -0700 Subject: tools/dnsmasq-leases-html: create a HTML page with leases from dnsmasq Parse the file that contains all the leases assigned by dnsmasq, and create a static HTML page from it. This can be served by nginx to make it easy to see what IP is assigned to a machine, and which machines are currently on the network. --- tools/dnsmasq-leases-html/README.md | 37 +++++++++++++++ tools/dnsmasq-leases-html/default.nix | 36 ++++++++++++++ tools/dnsmasq-leases-html/dnsmasq-leases-html.py | 37 +++++++++++++++ tools/dnsmasq-leases-html/templates/index.html | 60 ++++++++++++++++++++++++ 4 files changed, 170 insertions(+) create mode 100644 tools/dnsmasq-leases-html/README.md create mode 100644 tools/dnsmasq-leases-html/default.nix create mode 100755 tools/dnsmasq-leases-html/dnsmasq-leases-html.py create mode 100644 tools/dnsmasq-leases-html/templates/index.html (limited to 'tools/dnsmasq-leases-html') diff --git a/tools/dnsmasq-leases-html/README.md b/tools/dnsmasq-leases-html/README.md new file mode 100644 index 0000000..2437deb --- /dev/null +++ b/tools/dnsmasq-leases-html/README.md @@ -0,0 +1,37 @@ +Generates a static HTML page with a list of all the leases allocated by `dnsmasq`. + +A simple template written in the jinja syntax is used. + +The file containing the leases is expected to be at `/var/lib/dnsmasq/dnsmasq.leases`, but this can be overwritten by setting the environment variable `DNSMASQ_LEASES`. + +The output of the script is written to `/var/lib/dnsmasq/leases.html` by default, but the destination can be overwritten by setting the environment variable `DNSMASQ_LEASES_OUT`. + +The script can be executed automatically by `dnsmasq` if the configuration for `dhcp-script` is set to the path of the script. This will only be executed when a *new* lease is created or an *old* lease is deleted. To execute the script when a lease is *updated* you need to use the configuration `script-on-renewal`. + +A configuration looks like this: + +``` ini +dhcp-script=${pkgs.tools.dnsmasq-to-html}/bin/dnsmasq-leases-html +script-on-renewal +``` + +## nginx +To serve the page with nginx, you can use the following configuration: + +``` nix +services.nginx = { + enable = true; + virtualHosts."dnsmasq" = { + listen = [ + { + addr = "192.168.6.1"; + port = 8067; + } + ]; + locations."/" = { + root = "/var/lib/dnsmasq"; + index = "leases.html"; + }; + }; +}; +``` diff --git a/tools/dnsmasq-leases-html/default.nix b/tools/dnsmasq-leases-html/default.nix new file mode 100644 index 0000000..4848ea7 --- /dev/null +++ b/tools/dnsmasq-leases-html/default.nix @@ -0,0 +1,36 @@ +{ self, lib, stdenvNoCC, pkgs }: + +stdenvNoCC.mkDerivation rec { + pname = "dnsmasq-leases-html"; + src = ./dnsmasq-leases-html.py; + templates = ./templates; + version = "0.1.0"; + + buildInputs = [ + (pkgs.python310.withPackages (ps: with ps; [ + jinja2 + ])) + ]; + + propagatedBuildInputs = [ + (pkgs.python310.withPackages (ps: with ps; [ + jinja2 + ])) + ]; + + dontUnpack = true; + dontBuild = true; + + installPhase = '' + mkdir -p $out/bin + cp $src $out/bin/${pname} + cp -r $templates $out/bin/templates + ''; + + meta = with pkgs.lib; { + description = "CLI to generate a HTML page with dnsmasq leases."; + license = licenses.mit; + platforms = platforms.unix; + maintainers = [ ]; + }; +} diff --git a/tools/dnsmasq-leases-html/dnsmasq-leases-html.py b/tools/dnsmasq-leases-html/dnsmasq-leases-html.py new file mode 100755 index 0000000..c1f03db --- /dev/null +++ b/tools/dnsmasq-leases-html/dnsmasq-leases-html.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 + +import datetime +import ipaddress +import os + +from jinja2 import Environment, FileSystemLoader + + +outfile = os.getenv("DNSMASQ_LEASES_OUT", "/var/lib/dnsmasq/leases.html") +leases_file = os.getenv("DNSMASQ_LEASES", "/var/lib/dnsmasq/dnsmasq.leases") + +leases = [] + +with open(leases_file, "r") as f: + for line in f: + content = line.rstrip("\n").split(" ") + lease = dict() + if int(content[0]) == 0: + lease["expire"] = "never" + else: + lease["expire"] = datetime.datetime.fromtimestamp(int(content[0])) + lease["MAC"] = content[1] + lease["IP"] = ipaddress.ip_address(content[2]) + lease["hostname"] = content[3] + leases.append(lease) + +leases = sorted(leases, key=lambda d: d["IP"]) + +dir_path = os.path.dirname(os.path.realpath(__file__)) +templates_dir = os.path.join(dir_path, "templates") +environment = Environment(loader=FileSystemLoader(templates_dir)) +template = environment.get_template("index.html") + +content = template.render(leases=leases) +with open(outfile, "w") as fh: + print(content, file=fh) diff --git a/tools/dnsmasq-leases-html/templates/index.html b/tools/dnsmasq-leases-html/templates/index.html new file mode 100644 index 0000000..913a0c9 --- /dev/null +++ b/tools/dnsmasq-leases-html/templates/index.html @@ -0,0 +1,60 @@ + + + + + Leases assigned by dnsmasq + + + + + + + + + + + + {% for lease in leases %} + + + + + + + {% endfor %} +
IP addressMAC addressHostnameExpire
{{ lease.IP }}{{ lease.MAC }}{{ lease.hostname }}{{ lease.expire }}
+ + -- cgit 1.4.1