Show pagesourceOld revisionsBacklinksBack to top × Table of Contents fw4 Filtering traffic with IP sets by DNS Introduction Goal Prerequisites [CASE 1] Command-line instructions [CASE 2] Command-line instructions Limitations Improvements fw4 Filtering traffic with IP sets by DNS This article relies on the following: Accessing web interface / command-line interface Managing configs / packages / services / logs Introduction This guide create a set of IP address for traffic filtering, is an equivalent of dns_ipset based on nftables/fw4 that is the default starting from OpenWrt 22.03. Goal Avoid bypass of DNS based filtering with direct connection to the IP address of the website or with DoH. The general use case is a traffic restriction to be applied for SmartTV, IoT and other devices for which you may want to force a limited internet access. To reach this goal a set of IP addresses is created from a list of allowed or denied domains, a firewall rule to allow or deny traffic to those IP address is then created. The below example refer to the allow case for a specific interface called wildlan. Prerequisites You need a firewall zone without forwarding to wan, so that no traffic to the internet is allowed by default. Below this firewall zone is referenced as wildlan Have dig and grep installed Is assumed a standard fw4 configuration with inet fw4 table This wiki covers two cases, based on the dnsmasq running version. The Case 1 applies only to dnsmasq 2.87 or greater. [CASE 1] Command-line instructions Install dnsmasq-full as follows opkg update; cd /tmp/ && opkg download dnsmasq-full; opkg install ipset libnettle8 libnetfilter-conntrack3; opkg remove dnsmasq; opkg install dnsmasq-full --cache /tmp/; rm -f /tmp/dnsmasq-full*.ipk; Confirm the dnsmasq that is running with opkg list-installed dns* A valid result should looks like dnsmasq-full - 2.88-1 In /etc/hotplug.d/iface/20-firewall add the below code to create the nft set in which we will save the IP addresses, the proposed code is ipv4 only but can be extended to cover ipv6 # Filter wildlan by IP addresses ## Create a set for "inet fw4" table with name "blackhole" that can include "ipv4_addr" nft add set inet fw4 blackhole { type ipv4_addr \;} nft insert rule inet fw4 forward_wildlan ip daddr @blackhole accept The wildlan zone has no access to internet unless the target IP address is listed in blackhole, with dnsmasq 2.87 we can have that resolved IPs are automatically added to a set. Edit /etc/dnsmasq.conf with # The IP address corresponding to allowed.url URLs will be saved in the nftset (/4# filters for ipv4) nftset=/first.allowed.urls/4#inet#fw4#blackhole nftset=/second.allowed.urls/4#inet#fw4#blackhole ... Looking to the case in which you want to ensure that only IP addresses resolved via your DNS are allowed, then use # wildcard. This make sense if you want avoid access via direct IP without a filter for specific URLs. nftset=/#/4#inet#fw4#blackhole The relevant IP address of the allowed URLs can be listed with the below command, the set will anyhow remain empty till any of the allowed URLs is resolved via dnsmasq. nft list set inet fw4 blackhole [CASE 2] Command-line instructions This applies only for OpenWrt 22.03, OpenWrt 22.03.1 and OpenWrt 22.03.2 that have an older release of dnsmasq. In this case we cannot use dnsmasq to automatically fill the IP addresses in the set, so this have to be done with a script. In /etc/hotplug.d/iface/20-firewall add the below code to create the nft set in which we will save the IP addresses, the proposed code is ipv4 only but can be extended to cover ipv6 # Filter wildlan by IP addresses ## Create a set for "inet fw4" table with name "blackhole" that can include "ipv4_addr" nft add set inet fw4 blackhole { type ipv4_addr \;} ## Add element to "blackhole" from file urls.txt for address in $(dig a -f /etc/sets-ipdns/wildlan-urls.list +short | grep -v '\.$'); do nft add element inet fw4 blackhole {$address timeout 24h} done nft insert rule inet fw4 forward_wildlan ip daddr @blackhole accept The list of domains to which traffic will be allowed shall be included in a the custom file /etc/sets-ipdns/wildlan-urls.list, to create the file cd /etc mkdir sets-ipdns cd sets-ipdns vim wildlan-urls.list List inside vim the domain names that shall be allowed. Based on this forward chain only the traffic with destination to the IP addresses included in @blackhole will be allowed. The /etc/hotplug.d/iface/20-firewall is executed at any change of any interface (so mostly at boot time), so that @blackhole will be filled with IP addresses only at that stage. That set shall be periodically updated for two reasons: 1. The IP addresses may change 2. In case of DNS Load Balancing, the same DNS query will result in different IP addresses (all valid) based on time of request. In the Scheduled Task in Luci or in /etc/crontabs/root we execute every 15 minutes a script to update the sets 15 * * * * /etc/sets-ipdns/update-sets.sh In the /etc/sets-ipdns/update-sets.sh ## Add element to "blackhole" from file urls.txt for address in $(dig a -f /etc/sets-ipdns/wildlan-urls.list +short | grep -v '\.$'); do nft add element inet fw4 blackhole {$address timeout 24h} done Enable the script and reboot chmod +x /etc/sets-ipdns/update-sets.sh reboot After the reboot, verify the content of the @blackhole and the result should be a list of ipv4 addresses. nft list set inet fw4 blackhole The final crosscheck is to verify that addresses listed in /etc/sets-ipdns/wildlan-urls.list can be accessed, no other domains should be accessible unless the same IP address is shared between multiple domains (that happen with CDNs). Limitations In CASE 1 any URL and sub-URL that is listed will be allowed, rather in CASE 2 only the exact listed URL will be allowed. This make CASE 2 functionally working only for services that doesn't use multiple sub-URLs. In CASE 2 the script will periodically query the DNS with all domains included in /etc/sets-ipdns/wildlan-urls.list so that list should be reasonably small. Improvements Previous version of this wiki page use etc/rc.local instead of /etc/hotplug.d/iface/20-firewall. This has been proven to be an improvement as the commands included in etc/rc.local runs at end of boot but any change in the state of the interfaces will retrigger a rebuild of fw4. Including the commands in etc/rc.local needs a sleep to ensure that all interfaces are up, even if any late restart of any interface erase the commands included in etc/rc.local. Using instead /etc/hotplug.d/iface/20-firewall and including the nft commands just after fw4 -q reload ensure consistency across restart of interfaces. This website uses cookies. By using the website, you agree with storing cookies on your computer. Also you acknowledge that you have read and understand our Privacy Policy. If you do not agree leave the website.OKMore information about cookies Last modified: 2023/11/18 02:28by rexbinary