Simple controller for disabling/enabling Unbound DNS Ad blocker (DNSBL) on an OPNSense router/firewall.
  • Go 94%
  • Makefile 6%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Damien Stuart a5308c8c4d release: 0.1.1
Builds now run on macOS 13 and later, rather than only on the macOS that
built them, so the packaged app opens on Intel Macs running Sequoia. The
app bundle is also signed ad hoc, so it is not reported as damaged when
copied to another Mac.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 00:20:21 -04:00
tools/icongen Initial commit 2026-10-03 23:04:37 -04:00
.gitignore Initial commit 2026-10-03 23:04:37 -04:00
controller.go Initial commit 2026-10-03 23:04:37 -04:00
controller_test.go Initial commit 2026-10-03 23:04:37 -04:00
dialogs.go Initial commit 2026-10-03 23:04:37 -04:00
duration.go Initial commit 2026-10-03 23:04:37 -04:00
duration_test.go Initial commit 2026-10-03 23:04:37 -04:00
FyneApp.toml Initial commit 2026-10-03 23:04:37 -04:00
go.mod Initial commit 2026-10-03 23:04:37 -04:00
go.sum Initial commit 2026-10-03 23:04:37 -04:00
icon.go Initial commit 2026-10-03 23:04:37 -04:00
Icon.png Initial commit 2026-10-03 23:04:37 -04:00
LICENSE Initial commit 2026-10-03 23:04:37 -04:00
main.go Initial commit 2026-10-03 23:04:37 -04:00
Makefile build: run on macOS 13 and later, and sign the app bundle 2026-10-04 00:18:14 -04:00
menu.go Initial commit 2026-10-03 23:04:37 -04:00
opnsense.go Initial commit 2026-10-03 23:04:37 -04:00
opnsense_test.go Initial commit 2026-10-03 23:04:37 -04:00
prefs.go Initial commit 2026-10-03 23:04:37 -04:00
prefs_test.go Initial commit 2026-10-03 23:04:37 -04:00
README.md build: run on macOS 13 and later, and sign the app bundle 2026-10-04 00:18:14 -04:00
ui.go Initial commit 2026-10-03 23:04:37 -04:00
ui_test.go Initial commit 2026-10-03 23:04:37 -04:00
version.go release: 0.1.1 2026-10-04 00:20:21 -04:00
version_test.go Initial commit 2026-10-03 23:04:37 -04:00

DNSBL Control

A small desktop app for turning off your OPNsense firewall's Unbound DNS blocklist (DNSBL, its ad-blocking) for a while and having it come back on by itself.

  • Shows whether DNSBL is enabled, checking again every minute.
  • Disables it for 1, 5, 15 or 30 minutes, an hour, a custom length, or indefinitely, then re-enables it when the timer runs out.
  • Enable DNSBL turns it back on at once and cancels any timer.
  • Quitting while a timer is running asks first: re-enable and quit, leave it disabled and quit, or cancel. When re-enabling, a Quit Now button lets you go without waiting for the firewall to rebuild the blocklist. The firewall finishes on its own, but you won't hear about it if the rebuild fails.

Written in Go with Fyne.

Firewall setup

The app uses the OPNsense REST API, which authenticates with an API key and secret rather than a username and password.

  1. In OPNsense, go to System › Access › Users and create a user for this app (or pick an existing one).
  2. Give it only the Services: Unbound privilege. That covers the endpoints the app uses and nothing else.
  3. Under the user's API keys, click + to create a key. Your browser downloads a file with the key and secret. The secret can't be shown again.

OPNsense version

The app switches the global unbound.dnsbl.enabled setting, which OPNsense had up to 25.7.7. Version 25.7.8 replaced it with a list of blocklists, each enabled separately. Against a newer firewall the app reports "unsupported OPNsense version" rather than guessing.

API calls used:

Purpose Call
Status GET /api/unbound/settings/get (reads unbound.dnsbl.enabled)
Change POST /api/unbound/settings/set with {"unbound":{"dnsbl":{"enabled":"0"|"1"}}}
Apply POST /api/unbound/service/dnsbl

Build

Needs Go and a C compiler (Xcode command line tools on macOS); Fyne uses CGO.

make            # ./dnsbl for this Mac's processor only
make test       # unit tests, with the race detector
make package    # "DNSBL Control.app" for Apple Silicon and Intel Macs
make dmg        # disk image of the app
make icon       # redraw Icon.png from tools/icongen
make clean

Running on other Macs

make package and make dmg build one app that runs on both Apple Silicon and Intel Macs. Plain make builds only for the Mac doing the build.

Every build runs on macOS 13 (Ventura) or later, whatever macOS built it; Go 1.27 itself needs macOS 13. To require a newer macOS, set MACOS_MIN:

make package MACOS_MIN=15.0

make package prints the minimum for each processor type when it finishes.

The app is signed ad hoc, not with an Apple Developer ID. If it reaches another Mac by AirDrop, download or Messages, macOS quarantines it and blocks the first launch. To allow it, either:

  • open System Settings › Privacy & Security and click Open Anyway next to the message about DNSBL Control, or
  • run xattr -dr com.apple.quarantine "/Applications/DNSBL Control.app".

Copying it over a file share or a USB drive normally avoids the quarantine.

The icon is drawn by tools/icongen, a white shield holding a stopwatch on a blue tile. Its colours and the stopwatch hand's angle are constants at the top of tools/icongen/main.go.

The version is declared once, as appVersion in version.go. The About dialog adds the commit the binary was built from.

Run

./dnsbl

On first run the Settings dialog opens. Enter:

  • Firewall URL: the web UI address, e.g. https://firewall.example.lan (scheme, host and optional port only).
  • API Key and API Secret: from the downloaded key file.
  • Skip TLS certificate verification: tick this if the firewall still uses the self-signed certificate OPNsense starts with.

Settings can be changed later with the gear button or Preferences… (⌘,).

Where settings are kept

  • The URL, API key, TLS option and last-used duration are kept in Fyne's preference store: ~/Library/Preferences/fyne/org.dstuart.dnsbl/ on macOS, $XDG_CONFIG_HOME/fyne/org.dstuart.dnsbl/ elsewhere.
  • The API secret is kept in the OS keychain (macOS Keychain, Windows Credential Manager, or the Secret Service on Linux), under the service org.dstuart.dnsbl. If the keychain refuses it, the app says so and keeps the secret only until it quits.

How the timer behaves

  • The countdown follows the wall clock. If the computer sleeps past the end of a timer, DNSBL is re-enabled as soon as it wakes.
  • If re-enabling fails (say the firewall can't be reached), the app keeps retrying every 30 seconds until it works.
  • With DNSBL already disabled, the Change Timer button sets a new length (or Indefinite) without contacting the firewall.
  • If DNSBL is re-enabled somewhere else, such as the web UI, the app notices at its next check and drops its timer.
  • The timer exists only while the app is running. If you quit and leave DNSBL disabled, it stays disabled until you enable it.

When changes take effect

Each change is saved and then applied. Turning DNSBL back on makes the firewall rebuild the blocklist, which can take a minute or more. The app shows "enabled" as soon as the setting is saved, with an amber dot and "Rebuilding the blocklist…" until the rebuild finishes; the dot then turns green. Turning DNSBL off has nothing to rebuild and finishes quickly.

After that, OPNsense's blocklist module reloads its data at most once a minute, so a change can take up to about another 60 seconds to reach DNS answers. Devices may also keep blocked answers cached for up to an hour. Flushing the DNS cache on a device (or waiting) clears that.

License

BSD 3-Clause; see LICENSE.