OPNsense Unbound DNSBL
This role configures DNS Blocklists (DNSBL) in OPNsense Unbound resolver via the REST API. DNSBL blocks malicious domains, ads, trackers, and other unwanted content at the DNS level.
OPNsense Unbound DNSBL Role
Overview
This role configures DNS Blocklists (DNSBL) in OPNsense Unbound resolver via the REST API. DNSBL blocks malicious domains, ads, trackers, and other unwanted content at the DNS level.
Purpose
- Ad Blocking: Block advertisements at DNS level
- Malware Protection: Block known malicious domains
- Privacy: Block tracking and telemetry domains
- Code as Configuration: Define DNSBL settings in YAML
- API-Based: Reliable automation via OPNsense REST API
- Idempotent: Safe to run multiple times
Requirements
- Ansible 2.9 or higher
- OPNsense firewall with API access enabled
- os-unbound-plus plugin installed (provides DNSBL functionality)
- API key and secret stored in Ansible Vault
- Network connectivity to OPNsense (VLAN10)
- OPNsense user with Unbound permissions
Role Variables
Required Variables
| Variable | Required | Description |
|---|---|---|
vault_opnsense_bjoffrey_user_api_key | Yes | OPNsense API key (in vault) |
vault_opnsense_bjoffrey_user_api_secret | Yes | OPNsense API secret (in vault) |
opnsense_unbound_dnsbl_config | Yes | DNSBL configuration object |
Optional Variables
| Variable | Default | Description |
|---|---|---|
opnsense_unbound_dnsbl_validate_certs | true | Validate SSL certificates |
Configuration Structure
opnsense_unbound_dnsbl_config:
enabled: "1" # Enable (1) or disable (0) DNSBL
type: # List of blocklist type codes
- ag # AdGuard List
- sb # Steven Black List
lists: # Custom blocklist URLs
- https://example.com/blocklist.txt
allowlists: # Domains to whitelist
- trusted-domain.com
- another-trusted.com
blocklists: # Domains to explicitly block
- block-this.com
wildcards: # Wildcard domain blocks
- "*.ads.example.com"
source_nets: "" # Source networks (empty = all)
address: "" # Redirect address (empty = default)
nxdomain: "0" # Return NXDOMAIN instead of redirect
cache_ttl: "72000" # Cache TTL in seconds (20 hours)
description: "default" # Description
Available Blocklist Types
Core Lists
| Code | Description |
|---|---|
atf | Abuse.ch - ThreatFox IOC database |
ag | AdGuard List |
el | EasyList |
ep | EasyPrivacy |
sb | Steven Black List |
yy | YoYo List |
Hagezi Lists
| Code | Description |
|---|---|
hgz001 | Multi LIGHT - Basic protection |
hgz002 | Multi NORMAL - All-round protection |
hgz003 | Multi PRO - Extended protection |
hgz004 | Multi PRO mini |
hgz005 | Multi PRO++ - Maximum protection |
hgz006 | Multi PRO++ mini |
hgz007 | Multi ULTIMATE - Aggressive protection |
hgz008 | Multi ULTIMATE mini |
hgz009 | Fake - scams / fakes |
hgz010 | Pop-Up Ads |
hgz011 | Threat Intelligence Feeds |
hgz012 | Threat Intelligence Feeds - Medium |
hgz013 | Threat Intelligence Feeds - Mini |
hgz014 | DoH/VPN/TOR/Proxy Bypass |
hgz015 | Safesearch not supported |
hgz016 | Dynamic DNS blocking |
hgz017 | Badware Hoster blocking |
hgz018 | Anti Piracy |
hgz019 | Gambling |
hgz020 | Gambling - Medium |
hgz021 | Gambling - Mini |
OISD Lists
| Code | Description |
|---|---|
oisd0 | Domain Blocklist Ads |
oisd1 | Domain Blocklist Big |
oisd2 | Domain Blocklist NSFW |
Dependencies
This role has no dependencies on other Ansible roles, but requires:
- OPNsense firewall with API enabled
- os-unbound-plus plugin installed
- Unbound DNS service enabled
- API key with Unbound management permissions
- Ansible Vault for storing API credentials
Example Playbook
Basic Usage
---
- name: Configure OPNsense Unbound DNSBL
hosts: mint-vm
gather_facts: false
vars_files:
- ../../roles/opnsense_unbound_dnsbl/vars/dnsbl.yml
tasks:
- name: Configure DNSBL
ansible.builtin.include_role:
name: opnsense_unbound_dnsbl
Inline Variables
---
- name: Configure Unbound DNSBL
hosts: mint-vm
gather_facts: false
vars:
opnsense_unbound_dnsbl_config:
enabled: "1"
type:
- ag # AdGuard
- sb # Steven Black
- atf # ThreatFox
lists: []
allowlists:
- trusted-domain.com
blocklists: []
wildcards: []
nxdomain: "0"
cache_ttl: "72000"
description: "Basic ad and malware blocking"
roles:
- opnsense_unbound_dnsbl
What This Role Does
- Fetches existing DNSBL config via
/api/unbound/settings/search_dnsbl - Compares with desired config (enabled, type, lists, allowlists, etc.)
- Updates if different via
/api/unbound/settings/set_dnsbl/{uuid} - Applies DNSBL changes via
/api/unbound/service/dnsbl - Displays summary of DNSBL status
OPNsense API Endpoints
Search DNSBL Configuration
GET /api/unbound/settings/search_dnsbl
Authorization: Basic (API key:secret)
Returns current DNSBL configuration.
Update DNSBL Configuration
POST /api/unbound/settings/set_dnsbl/{uuid}
Authorization: Basic (API key:secret)
Content-Type: application/json
Request body:
{
"blocklist": {
"enabled": "1",
"type": "ag,sb,atf",
"lists": "",
"allowlists": "trusted.com",
"blocklists": "",
"wildcards": "",
"source_nets": "",
"address": "",
"nxdomain": "0",
"cache_ttl": "72000",
"description": "default"
}
}
Apply DNSBL Changes
POST /api/unbound/service/dnsbl
Authorization: Basic (API key:secret)
Applies DNSBL blocklist configuration changes.
Configuration Examples
Balanced Protection (Recommended)
opnsense_unbound_dnsbl_config:
enabled: "1"
type:
- ag # AdGuard
- sb # Steven Black
- atf # ThreatFox malware
- hgz003 # Hagezi PRO
- oisd1 # OISD Big
lists: []
allowlists: []
blocklists: []
wildcards: []
nxdomain: "0"
cache_ttl: "72000"
description: "Balanced ad/malware blocking"
Maximum Protection
opnsense_unbound_dnsbl_config:
enabled: "1"
type:
- ag
- sb
- atf
- hgz007 # Hagezi ULTIMATE
- hgz009 # Fake/scams
- hgz011 # Threat Intelligence
- oisd1
lists: []
allowlists: []
blocklists: []
wildcards: []
nxdomain: "0"
cache_ttl: "72000"
description: "Maximum protection"
Privacy Focused
opnsense_unbound_dnsbl_config:
enabled: "1"
type:
- ep # EasyPrivacy
- hgz014 # DoH/VPN/TOR/Proxy Bypass
- hgz018 # Anti Piracy
lists: []
allowlists: []
blocklists: []
wildcards: []
nxdomain: "0"
cache_ttl: "72000"
description: "Privacy focused blocking"
Custom Lists
opnsense_unbound_dnsbl_config:
enabled: "1"
type:
- ag
- sb
lists:
- https://example.com/my-blocklist.txt
- https://another.com/blocklist.txt
allowlists:
- trusted-site.com
- another-trusted.com
blocklists:
- block-this.com
- and-this.com
wildcards:
- "*.ads.example.com"
nxdomain: "0"
cache_ttl: "72000"
description: "With custom lists"
Security Considerations
- API Credentials: Stored in Ansible Vault
- HTTPS: Uses SSL/TLS for API calls
- Basic Auth: API key/secret authentication
- Certificate Validation: Enabled by default
- DNS-Level Blocking: Blocks threats before they reach devices
Troubleshooting
DNSBL not blocking domains
Cause: Unbound not reconfigured or DNSBL disabled
Solution: Check that enabled: "1" and verify reconfigure task ran
”Plugin not found” errors
Cause: os-unbound-plus plugin not installed
Solution: Install the plugin via OPNsense UI: System → Firmware → Plugins → os-unbound-plus
Legitimate sites blocked
Cause: Overly aggressive blocklists
Solution: Add domains to allowlists or use less aggressive lists
DNS resolution slow
Cause: Too many blocklists or low cache TTL
Solution: Reduce number of lists or increase cache_ttl
Best Practices
- Start conservative: Begin with basic lists (ag, sb) and add more as needed
- Monitor logs: Check Unbound logs for false positives
- Whitelist carefully: Add legitimate blocked domains to allowlists
- Use cache: Keep cache_ttl high (72000s = 20 hours) for performance
- Test changes: Verify DNS resolution after applying changes
- Document choices: Use description field to explain configuration
Related Roles
This role works well with:
- opnsense_unbound_host_overrides: Manage DNS host overrides
- opnsense_unbound_settings: Configure general Unbound settings
- opnsense_firewall: Configure firewall rules for DNS traffic
License
MIT
Author
Created for homelab infrastructure management.