ipset is a relative recent netfilter feature to manage a large group of stations/networks as a single named set. The netfilter rules can then match packet fields on the set rather than individual stations. This creates a number of efficiencies, for example a hash lookup of the station addresses in the set.
firewall3 supports the most common ipset functions. This section provides some examples to illustrate how to incorporate an ipset into netfilter rules.
In order to use the ipset netfilter feature:
ipsetapplication package must be installed.
In LuCI under System → Software , in the Download and install package:
ipset and confirm the
ipset package is installed by clicking on OK.
It will not install if the kernel does not support the ipset feature.
The 18.06 OpenWrt release do not include support for ipset by default, so you will need to install the appropriate packages to use this facility. See below for installing ipset using opkg or building a custom image including ipset.
ipset is great for collecting a large set of IP addresses/networks under one label and then using the label in subsequent rules as a single match criteria for any entry in the ipset.
One of the big uses of ipset is to block spam generators (stations or networks that randomly generate billions of spam emails daily.) There are thousands of spam generators; adding a reject rule for each makes the netfilter rule list huge and inefficient.
So all Spam networks are added to a single ipset
name and then that
name is used in the match rules.
/etc/config/firewall rules add:
config ipset option name 'dropcidr' option match 'src_net' option storage 'hash' option enabled '1' list entry '18.104.22.168/16' list entry '22.214.171.124/20' list entry '126.96.36.199/24' list entry '188.8.131.52/15' list entry '192.168.3.0/24' config rule option src 'wan' option ipset 'dropcidr' option dest_port '25' option target 'DROP' option name 'DROP-SMTP-WAN-LAN' option enabled '1'
ipset configuration instructs the firewall to create an ipset named
and matches it to the source network field using a traffic rule.
Notice the storage type is
There is a good deal of internal optimization that can be done inside the ipset kernel modules.
This ipset is configured to use a highly efficient hash rather than a linear search to match the source network.
rule section matches on a network in
dropcidr and port 25(SMTP).
If there is a match, the DROP target is called.
Use DROP and not REJECT for this rule.
See Netfilter Managment to view and verify the new firewall sections. With fw3, one should see a rule like this:
iptables \ -t filter -A zone_wan_forward \ -p tcp -m tcp --dport 25 \ -m set --match-set dropcidr src \ -m comment --comment "!fw3: DROP-SMTP-WAN-LAN" \ -j zone_lan_dest_DROP
The configuration above uses a number of
list entry lines to populate the ipset with some initial IP ranges.
192.168.3.0 is a private network on the WAN-side used to test this feature.
The others are actual spam sources.
In practice it is better to use the
loadfile option instead which allows specifying the ipset contents in an external file for easier maintenance.
Such an external file can be for example created from publicly available blocklists or populated by other programs for use with the ipset.
To use the
loadfile option, first create a plaintext file containing the IP ranges to add to the set:
cat << "EOF" > /etc/dropcidr.txt 184.108.40.206/16 220.127.116.11/20 18.104.22.168/24 22.214.171.124/15 192.168.3.0/24 EOF
Afterwards, modify the ipset declaration in the firewall configuration by removing the
list entry lines and replacing them with a sole
config ipset option name 'dropcidr' option match 'src_net' option storage 'hash' option enabled '1' option loadfile '/etc/dropcidr.txt'
ipset application can be used instead of or in addition to the
loadfile option to add entries to the set after it has been created and populated by the firewall:
ipset add dropcidr 126.96.36.199/16 ipset add dropcidr 188.8.131.52/20 ipset add dropcidr 184.108.40.206/24 ipset add dropcidr 220.127.116.11/15 ipset add dropcidr 192.168.3.0/24 ...
Entries can be added and deleted from the set at any time:
ipset del dropcidr 192.168.3.0/24 ipset list dropcidr
The CIDRs can be dynamically added and deleted in the
dropcidr table while the netfilter rule is active.
Besides adding IPs manually, package: dnsmasq-full can automatically populate the list. It can be used to add IPs that were send to hosts for certain names. This is helpful if names are used for filtering.
ipset destroy dropcidr
The ipset table cannot be destroyed while being referenced by a netfilter rule. First remove it from the firewall config and reload.
The ipset is not supported in the OpenWrt image by default, but it can be added fairly easily through opkg or by including it in a custom build.
For installing with opkg, use the following commands:
opkg update opkg install ipset
When compiling a custom build, use the OpenWrt
make menuconfig and select
ipset as built-in within the Network menu.
Then rebuild and install the resulting image.
When the image is running, confirm the
ip_set modules are loaded.
It will look something like the following:
# cat /proc/modules | grep ip_set ip_set_list_set 6704 0 - Live 0x8301c000 ip_set_hash_netiface 23888 0 - Live 0x830f0000 ip_set_hash_netport 23856 0 - Live 0x830e8000 ip_set_hash_netnet 25584 0 - Live 0x830e0000 ip_set_hash_net 22480 1 - Live 0x830d8000 ip_set_hash_netportnet 26960 0 - Live 0x830d0000 ip_set_hash_mac 10000 0 - Live 0x830cc000 ip_set_hash_ipportnet 25520 0 - Live 0x83038000 ip_set_hash_ipportip 20848 0 - Live 0x830c0000 ip_set_hash_ipport 19792 0 - Live 0x83030000 ip_set_hash_ipmark 19056 0 - Live 0x83020000 ip_set_hash_ip 18768 0 - Live 0x83028000 ip_set_bitmap_port 5648 0 - Live 0x8301e000 ip_set_bitmap_ipmac 6544 0 - Live 0x8301a000 ip_set_bitmap_ip 6384 0 - Live 0x8300e000 ip_set 22250 16 xt_set,ip_set_list_set,ip_set_hash_netiface,ip_set_hash_netport,ip_set_hash_netnet,ip_set_hash_net,ip_set_hash_netportnet,ip_set_hash_mac,ip_set_hash_ipportnet,ip_set_hash_ipportip,ip_set_hash_ipport,ip_set_hash_ipmark,ip_set_hash_ip,ip_set_bitmap_port,ip_set_bitmap_ipmac,ip_set_bitmap_ip, Live 0x83010000 nfnetlink 4199 1 ip_set, Live 0x830b6000
Then confirm the
ipset application is working.
An example is given at Blocking IPs based on their hostname This is really useful if large CDNs need to be filtered based on their names.