Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Next revisionBoth sides next revision
docs:guide-user:firewall:filtering_traffic_at_ip_addresses_by_dns [2022/05/01 08:26] pliniosenioredocs:guide-user:firewall:filtering_traffic_at_ip_addresses_by_dns [2024/01/13 12:53] – [Improvements] plinioseniore
Line 1: Line 1:
 ====== fw4 Filtering traffic with IP sets by DNS ====== ====== fw4 Filtering traffic with IP sets by DNS ======
-{{section>meta:infobox:howto_links#cli_skills&noheader&nofooter&noeditbutton}}+{{section>meta:infobox:howto_links#basic_skills&noheader&nofooter&noeditbutton}}
  
 ===== Introduction ===== ===== Introduction =====
 This guide create a **set** of IP address for traffic filtering, is an equivalent of [[:docs:guide-user:firewall:fw3_configurations:dns_ipset]] based on **nftables/fw4** that is the default starting from //OpenWrt 22.03//. This guide create a **set** of IP address for traffic filtering, is an equivalent of [[:docs:guide-user:firewall:fw3_configurations:dns_ipset]] based on **nftables/fw4** that is the default starting from //OpenWrt 22.03//.
  
-===== Goals ===== +===== Goal ===== 
-Avoid bypass of [[:docs:guide-user:firewall:fw3_configurations:fw3_parent_controls#blocking_name_resolution_dns_by_adblockers | DNS based filtering ]] with direct connection to the IP address of the website of 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.+Avoid bypass of [[:docs:guide-user:firewall:fw3_configurations:fw3_parent_controls#blocking_name_resolution_dns_by_adblockers | 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*.+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 =====  ===== Prerequisites ===== 
-  - You need a firewall zone without forwarding to **wan**, so that no traffic to the internet is allowed by default+  - 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   - Have **dig** and **grep** installed
-  - Create a new interface (called *wildlan* in the below example) for which no forward is set in the firewall settings, so that only IP addresses in the //set// will be allowed 
   - Is assumed a standard fw4 configuration with //inet fw4// table   - Is assumed a standard fw4 configuration with //inet fw4// table
  
-===== Command-line instructions ===== +This wiki covers two cases, based on the //dnsmasq// running version. The //Case 1// applies only to //dnsmasq// 2.87 or greater.
  
-In ///etc/rc.local// 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**+===== [CASE 1] Command-line instructions =====  
 + 
 +Install //dnsmasq-full// as follows 
 + 
 +<code bash> 
 +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; 
 +</code> 
 + 
 +Confirm the //dnsmasq// that is running with 
 + 
 +<code bash> 
 +opkg list-installed dns* 
 +</code> 
 + 
 +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** 
 + 
 +<code bash> 
 +# 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 
 +</code> 
 + 
 +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 
 + 
 +<code bash> 
 +# 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 
 +... 
 +</code> 
 + 
 +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. 
 + 
 +<code bash> 
 +nftset=/#/4#inet#fw4#blackhole 
 +</code> 
 + 
 +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//
 + 
 +<code bash> 
 +nft list set inet fw4 blackhole 
 +</code> 
 + 
 +===== [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**
  
 <code bash> <code bash>
Line 27: Line 79:
 ## Add element to "blackhole" from file urls.txt ## Add element to "blackhole" from file urls.txt
 for address in $(dig a -f /etc/sets-ipdns/wildlan-urls.list +short | grep -v '\.$'); do for address in $(dig a -f /etc/sets-ipdns/wildlan-urls.list +short | grep -v '\.$'); do
- nft add element inet fw4 blackhole {$address}+ nft add element inet fw4 blackhole {$address timeout 24h}
 done done
  
-## Allow packes in "blackhole" (all others are denied by default) 
 nft insert rule inet fw4 forward_wildlan ip daddr @blackhole accept nft insert rule inet fw4 forward_wildlan ip daddr @blackhole accept
 </code> </code>
Line 47: Line 98:
 Based on this forward chain only the traffic with destination to the IP addresses included in @blackhole will be allowed. Based on this forward chain only the traffic with destination to the IP addresses included in @blackhole will be allowed.
  
-The //rc.local// is executed 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:+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 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. 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/rootwe execute every 15 minutes a script to update the **sets**+In the Scheduled Task in Luci or in ///etc/crontabs/root// we execute every 15 minutes a script to update the **sets**
 <code bash> <code bash>
 15 * * * * /etc/sets-ipdns/update-sets.sh 15 * * * * /etc/sets-ipdns/update-sets.sh
 </code> </code>
  
-In the */etc/sets-ipdns/update-sets.sh* include the update of sets code from ///etc/rc.local//+In the ///etc/sets-ipdns/update-sets.sh//
  
 <code bash> <code bash>
 ## Add element to "blackhole" from file urls.txt ## Add element to "blackhole" from file urls.txt
 for address in $(dig a -f /etc/sets-ipdns/wildlan-urls.list +short | grep -v '\.$'); do for address in $(dig a -f /etc/sets-ipdns/wildlan-urls.list +short | grep -v '\.$'); do
- nft add element inet fw4 blackhole {$address}+ nft add element inet fw4 blackhole {$address timeout 24h}
 done done
 </code> </code>
Line 77: Line 128:
 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). 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).
  
-===== Limitation ===== +===== Limitations ===== 
-This approach will query periodically the DNS with all domains included in ///etc/sets-ipdns/wildlan-urls.list// so that list should be reasonably small.+ 
 +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 allowedThis make //CASE 2// functionally working only for services that doesn't use multiple sub-URLs.
  
-===== Further improvement ===== +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.
-If the goal is to enforce the [[:docs:guide-user:firewall:fw3_configurations:fw3_parent_controls#blocking_name_resolution_dns_by_adblockers | DNS based filtering ]] this configuration could be modified as follow: +
-  - List of the IP addresses served by the DNS into a //set// using a timeout on the entries +
-  Allow traffic only to the IP addresses in the //set//+
  
-This require a solution similar to [[:docs:guide-user:services:dns:ipset-dns]] to have the DNS to add the resolved IP addresses automatically in the //set//.+===== Next Improvements =====
  
 +The command line instructions are included in ///etc/hotplug.d/iface/20-firewall// that trigger a rebuild of the firewall configuration at each change of any interface. Anyhow this is not trigged when a UCI/LUCI firewall change is applied. So at any change in the firewall configuration the rebuild will not involve the custom rules included in ///etc/hotplug.d/iface/20-firewall//, as result connectivity of devices that rely on this will be lost.
  
 +The rules will be reapplied at next change in status of any interface, that could also be trigged on purpose to rebuild the rules.
  
 +If in next released will be included a custom file for NFT commands that is trigged at any firewall rebuild, this problem will be solved.
  • Last modified: 2024/05/27 21:51
  • by systemcrash