Unbound with ipset support

I’m using ipfire for quite some time now. In previous releases, the DNS server was using dnsmasq as DNS server, which was very useful, as it had the ability to specify option --ipset in /etc/sysconfig/dnsmasq
as
“CUSTOM_ARGS=”–ipset=/domain1/domain2/ipset/"
which I was using a lot for my custom rules.
Upon an update of ipfire, I saw that it now uses unbound DNS server.
The unbound DNS server also has a module for ipsets, however it needs to be compiled into the daemon.
From what I can see, this isn’t the case, unfortunately:

]# unbound -V
Version 1.20.0

Configure line: --prefix=/usr --sysconfdir=/etc --with-pidfile=/var/run/unbound.pid --with-rootkey-file=/var/lib/unbound/root.key --disable-static --with-libevent --enable-event-api --enable-tfo-client --enable-tfo-server ac_cv_func_getentropy=no
Linked libs: libevent 2.1.12-stable (it uses epoll), OpenSSL 3.2.2 4 Jun 2024
Linked modules: dns64 respip validator iterator

It would be necessary to compile it with parameters --enable-ipset --with-libmnl

The issue is a blocker for me so that I cannot upgrade ipfire due to this (I could compile it myself and swap out the daemon with my self-compiled version, but that would be necessary on every update and is therefore a source for potential problems). I’d like to ask if it would be possible to incorporate ipset support in future versions of ipfire or if there are any other ways to keep this functionality with newer ipfire versions?

Thank you in advance.

I’m sure IPfire has ipset.

2 Likes

That was not my question, ipfire has ipset, of course. I need an ipset–trigger within unbound as it used to be with dnsmasq (whenever a Domain is looked up that matches a certein mask, its ip has to be added to an ipset automatically)

Two questions:

  • what is the purpose of your ipset rules?
  • where did you find an ipset module in unbound?

Hi,

Thank you for your reply.
Ad 1) The purpose of the ipset rules is to unlock an application by a certain provider who isn’t abele to give a list of fixed IP-Addresses to unlock for access, but gives out domain names that need to be looked up (so all subdomains under a specific domain can be contacted and need to be unlocked.
I’m not a big fan of this and consider it bad practice by the Software vendor, but unfortunately, I cannot change it.

Microsoft is also using this scheme, unfortunately, to allow access to its MS Office Activation servers only by unlocking a list of domains and they recently started to block MS Office with an unlimited license after 6 months of usage if license servers cannot be contacted within this period. I didn’t unlock all the Microsoft Domains using this technique, as I consider it as being too risky, as this may over time unlock the whole Azure cloud if they keep changings IPs constantly, but it serves as a good example for this bad practice of Software companies.

Ad 2) Unbound: doc/README.ipset.md | Fossies
unbound/ipset/ipset.c at master · NLnetLabs/unbound · GitHub

Best regards

1 Like

Could you create a ipset
Then make a firewall rule?

I think it is best to post a request on bugzilla.
Remains the transfer from dnsmasq config to unbound config.

Ok, filed a bug report:
https://bugzilla.ipfire.org/show_bug.cgi?id=13791

The problem is the CREATION of an ipset automatically via a DNS lookup-trigger. There is not problem with using ipsets in iptables-rules.

I’m currently working around the problem with this cron.hourly script on the test machine, but I don’t want to use that in production, as it’s a real bad hack and of course unreliable:

#!/bin/bash

# Script, das temporaer mal hilft, bis das mit der fehlenden ipset lookup-funktion in unbound gefixt ist

# Define the IP set
IPSET_NAME="alloweddns"
ipset create $IPSET_NAME hash:ip -exist

# Define the domains to look up
DOMAINS=("activation.sls.microsoft.com")

# Function to recursively resolve a domain to IP addresses
resolve_ips() {
    local domain="$1"
    local resolved_ips=()

    # Perform the initial query
    local results=$(dig +short "$domain")

    # Iterate through the results
    for result in $results; do
        # If the result is an IP address, add it to the list
        if [[ $result =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
            resolved_ips+=("$result")
        else
            # If it's a CNAME, recursively resolve it
            local cname_ips=$(resolve_ips "$result")
            resolved_ips+=($cname_ips)
        fi
    done

    # Return the list of resolved IPs
    echo "${resolved_ips[@]}"
}

# Update IP set with resolved IPs for each domain
for domain in "${DOMAINS[@]}"; do
    #echo "Resolving IPs for domain: $domain"
    resolved_ips=$(resolve_ips "$domain")

    for ip in $resolved_ips; do
        # Add each resolved IP to the IP set
        ipset add $IPSET_NAME "$ip" -exist
    done
done