Ipset-extras, ipset storage and blocking DNS over HTTPS

When following the guide to block DNS over HTTPS from the wiki it assumes ipset-extras and hotplug-extras are installed. The 60-ipset-doh script downloads a list of domains which then is converted into IPs by resolveip used in ipset-extras.

However, ipset-extras sets the resulting ipset to hash:net as seen below, which as far as I understand expects a CIDR-range and not a single IP per entry, see below:

uci -q batch << EOI
set firewall.'${IPSET_NAME}'='ipset'
set firewall.'${IPSET_NAME}'.name='${IPSET_NAME}'
set firewall.'${IPSET_NAME}'.family='${IPSET_FAMILY}'
set firewall.'${IPSET_NAME}'.storage='hash'
set firewall.'${IPSET_NAME}'.match='net'
$(sed -n -e "s/^.*${IPSET_MATCH}.*$/\
del_list firewall.'${IPSET_NAME}'.entry='\0'\n\
add_list firewall.'${IPSET_NAME}'.entry='\0'/p" "${IPSET_TEMP}")
EOI
}

The resulting ipset is therefore useless for the purpose of blocking. Altering the script to instead store the entries as hash:ip produces the expected results. This can be tested through going through the procedure as described in the wiki-page for blocking DNS over HTTPS and adding a rule as such:

config rule
        option name 'testing ipset'
        option src '*'
        option dest '*'
        option proto 'all'
        option family 'ipv4'
        option ipset 'doh dest'
        option target 'REJECT'

And trying to ping for example 1.1.1.1 which will succeed. Using hash:ip results in the ping being blocked as expected.

As a solution to this issue, the easiest way would probably be to modify the ipset-extras script to add a {IPSET_HASH} variable which is set depending on which of the functions (ipset_domain, ipset_cidr, ipset_asn) are called to fill the {IPSET_ENTRY} variable. Now, my (b)ash scripting skills are seriously subpar, so I'm at a loss of how to properly do this.

Or am I missing something here? :slight_smile:

EDIT: Using OWRT 21.02 and ipset v7.6

If I were in your shoes, I'd check who authored latest changes/most of the content of that wiki page and tag that person in your post.

1 Like

It should work with both CIDRs and IPs.

That's quite possible as it works for me.
Try to open https://8.8.8.8/ from the client and then check on OpenWrt:

ipset -t list doh; ipset test doh 8.8.8.8; iptables-save -c | grep -e doh