IPSET(8)
๐ธ IPSET(8) โ the ipset page, but make it make sense ๐ธ
okay bestie, buckle up, because this is the manual for ipset and we're doing the whole thing together ๐
โจ NAME โจ
ipset โ administration tool for IP sets
โจ SYNOPSIS โจ
ipset [ OPTIONS ] COMMAND [ COMMAND-OPTIONS ]
COMMANDS := { create | add | del | test | destroy | list | save |
restore | flush | rename | swap | help | version | - }
OPTIONS := { -exist | -output { plain | save | xml } | json } | -quiet |
-resolve | -sorted | -name | -terse | -file filename }
ipset create SETNAME TYPENAME [ CREATE-OPTIONS ]
ipset add SETNAME ADD-ENTRY [ ADD-OPTIONS ]
ipset del SETNAME DEL-ENTRY [ DEL-OPTIONS ]
ipset test SETNAME TEST-ENTRY [ TEST-OPTIONS ]
ipset destroy [ SETNAME ]
ipset list [ SETNAME ]
ipset save [ SETNAME ]
ipset restore
ipset flush [ SETNAME ]
ipset rename SETNAME-FROM SETNAME-TO
ipset swap SETNAME-FROM SETNAME-TO
ipset help [ TYPENAME ]
ipset version
ipset -
โจ DESCRIPTION โจ
So ipset is your girl for setting up, maintaining and inspecting the so-called IP sets living inside the Linux kernel. And depending on what type of set you're working with, an IP set can hold IP(v4/v6) addresses, (TCP/UDP) port numbers, IP and MAC address pairs, IP address and port number pairs, etc. ๐ All the set type definitions are down below, don't worry.
Iptables matches and targets that point at sets create references, and those references protect the sets in the kernel. Meaning: a set cannot be destroyed while there's even a single reference pointing at it. no cap. ๐ซถ
โจ OPTIONS โจ
The options ipset recognizes split up into a few different groups. vibe check time ๐
๐ฏ COMMANDS
These options say what action you want to happen. Only one of them can be specified on the command line unless it says otherwise below. And for all the long versions of the command names, you only need to type enough letters for ipset to tell it apart from every other command. The ipset parser walks the order below when it's hunting for the shortest match in the long command names. iykyk ๐
n,createSETNAME TYPENAME [ CREATE-OPTIONS ] โ create a set identified with setname and the type you specified. The type might demand type-specific options. If the-existoption is given,ipsetignores the error it would otherwise raise when that exact same set already exists (same setname, same create parameters). โจaddSETNAME ADD-ENTRY [ ADD-OPTIONS ] โ add the given entry to the set. If the-existoption is given,ipsetignores it when the entry is already added to the set. ๐ซถdelSETNAME DEL-ENTRY [ DEL-OPTIONS ] โ delete an entry from a set. If the-existoption is given and the entry isn't in the set (maybe it already expired?), then the command is just ignored. ๐testSETNAME TEST-ENTRY [ TEST-OPTIONS ] โ test whether an entry is in a set or not. The exit status number is zero if the tested entry is in the set, and nonzero if it's missing from the set. ๐ฅx,destroy[ SETNAME ] โ destroy the specified set, or all the sets if none is given.
If the set has got reference(s), nothing happens and no set gets destroyed. ๐
list[ SETNAME ] [ OPTIONS ] โ list the header data and the entries for the specified set, or for all sets if none is given. The-resolveoption forces name lookups (which may be slow ๐ญ). When-sortedis given, entries are listed/saved sorted (which may also be slow ๐ญ). The-outputoption controls the format of the listing:plain,save,xmlorjson. (The default isplain.) If-nameis specified, just the names of the existing sets get listed. If-terseis specified, just the set names and headers get listed. Output goes to stdout, and the-fileoption lets you name a filename instead of stdout. ๐save[ SETNAME ] โ save the given set, or all sets if none is given, to stdout in a format thatrestorecan read. The-fileoption lets you name a filename instead of stdout. ๐พrestoreโ restore a saved session generated bysave. The saved session can be fed from stdin, or the-fileoption lets you name a filename instead of stdin.
Please note, existing sets and elements are not erased byrestoreunless it's specified so in the restore file. All commands are allowed in restore mode exceptlist,help,version, interactive mode andrestoreitself. ๐
flush[ SETNAME ] โ flush all entries from the specified set, or flush all sets if none is given. ๐e,renameSETNAME-FROM SETNAME-TO โ rename a set. The set identified by SETNAME-TO must not exist. โญw,swapSETNAME-FROM SETNAME-TO โ swap the content of two sets, or in other words, exchange the name of two sets. The referred sets must exist, and only compatible types of sets can be swapped. ๐help[ TYPENAME ] โ print help, plus set type specific help if TYPENAME is specified. ๐versionโ print program version. ๐-โ if a dash is specified as command, thenipsetenters a simple interactive mode and the commands are read from standard input. You finish interactive mode by entering the pseudo-commandquit. ๐ฆ
๐ OTHER OPTIONS
The following extra options can be specified too. And heads up: the long option names cannot be abbreviated. ๐
-!,-existโ ignore errors when exactly the same set is to be created, or an already added entry is added, or a missing entry is deleted. ๐-o,-output { plain | save | xml | json }โ select the output format for thelistcommand. โจ-q,-quietโ suppress any output to stdout and stderr.ipsetwill still exit with an error if it cannot continue. ๐คซ-r,-resolveโ when listing sets, enforce name lookup. The program will try to display the IP entries resolved to host names, which requires slow DNS lookups. ๐-s,-sortedโ sorted output. When listing or saving sets, the entries are listed sorted. ๐ค-n,-nameโ list just the names of the existing sets, i.e. suppress listing of set headers and members. ๐ท๏ธ-t,-terseโ list the set names and headers, i.e. suppress listing of set members. โ๏ธ-f,-filefilename โ specify a filename to print into instead of stdout (listorsavecommands), or to read from instead of stdin (restorecommand). ๐
โจ INTRODUCTION โจ
A set type is made up of the storage method the data is stored by, plus the data type(s) stored in the set. So the TYPENAME parameter of the create command follows this syntax:
TYPENAME := method:datatype[,datatype[,datatype]]
where the current list of methods is bitmap, hash, and list, and the possible data types are ip, net, mac, port and iface. The dimension of a set equals the number of data types in its type name. ๐ฆ
When you're adding, deleting or testing entries in a set, that same comma separated data syntax has to be used for the entry parameter of the commands, i.e.
ipset add foo ipaddr,portnum,ipaddr
If host names or service names with a dash in the name get used instead of IP addresses or service numbers, then the host name or service name must be enclosed in square brackets. Example:
ipset add foo [test-hostname],[ftp-data]
And in the case of host names, the DNS resolver is called internally by ipset, but if it returns multiple IP addresses, only the first one is used. ๐
The bitmap and list types use a fixed sized storage. The hash types use a hash to store the elements. To avoid clashes in the hash, a limited number of chaining happens, and if that's exhausted, the doubling of the hash size is performed when entries are added by the ipset command. But when entries are added by the SET target of iptables/ip6tables, then the hash size is fixed and the set won't be duplicated, even if the new entry cannot be added to the set. ๐
โจ GENERIC CREATE AND ADD OPTIONS โจ
โณ timeout โณ
okay so bestie, every single set type supports the optional timeout parameter when you're creating a set and when you're adding entries. The value you give to timeout in the create command is the default timeout value (in seconds) for new entries. If a set is created with timeout support, then you can use that same timeout option to set non-default timeout values when adding entries. A timeout of zero means the entry is added permanent to the set. You can change the timeout value of already added elements by re-adding the element with the -exist option. The largest possible timeout value is 2147483 (in seconds). Example:
ipset create test hash:ip timeout 300
ipset add test 192.168.0.1 timeout 60
ipset -exist add test 192.168.0.1 timeout 600
When you're listing the set, the number of entries printed in the header might be larger than the listed number of entries for sets with the timeout extensions: the number of entries in the set is updated when elements are added/deleted to the set and periodically when the garbage collector evicts the timed out entries.
๐ counters, packets, bytes ๐
All set types support the optional counters option when creating a set. If you specify it, the set is created with packet and byte counters per element support. The packet and byte counters are initialized to zero when the elements are (re-)added to the set, unless the packet and byte counter values are explicitly specified by the packets and bytes options. Here's an example when an element is added to a set with non-zero counter values:
ipset create foo hash:ip counters
ipset add foo 192.168.1.1 packets 42 bytes 1024
๐ฌ comment ๐ฌ
All set types support the optional comment extension. Enabling this extension on an ipset lets you annotate an ipset entry with an arbitrary string. This string is completely ignored by both the kernel and ipset itself and is purely for providing a convenient means to document the reason for an entry's existence. Comments must not contain any quotation marks and the usual escape character (\) has no meaning. For example, the following shell command is illegal:
ipset add foo 1.1.1.1 comment "this comment is \"bad\""
In the above, your shell will of course escape the quotation marks and ipset will see the quote marks in the argument for the comment, which will result in a parse error. If you are writing your own system, you should avoid creating comments containing a quotation mark if you do not want to break ipset save and ipset restore, nonetheless, the kernel will not stop you from doing so. The following is perfectly acceptable:
ipset create foo hash:ip comment
ipset add foo 192.168.1.1/24 comment "allow access to SMB share
on \\\\fileserv\\"
the above would appear as: "allow access to SMB share on
\\fileserv\"
๐ skbinfo, skbmark, skbprio, skbqueue ๐
All set types support the optional skbinfo extension. This extension allows you to store the metainfo (firewall mark, tc class and hardware queue) with every entry and map it to packets by usage of SET netfilter target with --map-set option. skbmark option format: MARK or MARK/MASK, where MARK and MASK are 32bit hex numbers with 0x prefix. If only mark is specified mask 0xffffffff are used. skbprio option has tc class format: MAJOR:MINOR, where major and minor numbers are hex without 0x prefix. skbqueue option is just decimal number.
ipset create foo hash:ip skbinfo
ipset add foo 192.168.0.1 skbmark 0x1111/0xff00ffff skbprio 1:10
skbqueue 10
#๏ธโฃ hashsize #๏ธโฃ
This parameter is valid for the create command of all hash type sets. It defines the initial hash size for the set, default is 1024. The hash size must be a power of two, the kernel automatically rounds up non power of two hash sizes to the first correct value. Example:
ipset create test hash:ip hashsize 1536
๐ข maxelem ๐ข
This parameter is valid for the create command of all hash type sets. It defines the maximal number of elements which can be stored in the set, default 65536. Example:
ipset create test hash:ip maxelem 2048
๐ชฃ bucketsize ๐ชฃ
This parameter is valid for the create command of all hash type sets. It specifies the maximal number of elements which can be stored in a hash bucket. Possible values are any even number between 2-14 and the default is 14. Setting the value lower forces ipset to create larger hashes which consumes more memory but gives more speed at matching in the set. Example:
ipset create test hash:ip bucketsize 2
๐ family { inet | inet6 } ๐
This parameter is valid for the create command of all hash type sets except for hash:mac. It defines the protocol family of the IP addresses to be stored in the set. The default is inet, i.e IPv4. For the inet family one can add or delete multiple entries by specifying a range or a network of IPv4 addresses in the IP address part of the entry:
ipaddr := { ip | fromaddr-toaddr | ip/cidr }
netaddr := { fromaddr-toaddr | ip/cidr }
Example:
ipset create test hash:ip family inet6
๐ซ nomatch ๐ซ
The hash set types which can store net type of data (i.e. hash:*net*) support the optional nomatch option when adding entries. When matching elements in the set, entries marked as nomatch are skipped as if those were not added to the set, which makes possible to build up sets with exceptions. See the example at hash type hash:net below.
When elements are tested by ipset, the nomatch flags are taken into account. If one wants to test the existence of an element marked with nomatch in a set, then the flag must be specified too.
๐ช forceadd ๐ช
All hash set types support the optional forceadd parameter when creating a set. When sets created with this option become full the next addition to the set may succeed and evict a random entry from the set.
ipset create foo hash:ip forceadd
โจ wildcard โจ
This flag is valid when adding elements to a hash:net,iface set. If the flag is set, then prefix matching is used when comparing with this element. For example, an element containing the interface name "eth" will match any name with that prefix.
๐ SET TYPES ๐
๐ bitmap:ip ๐
The bitmap:ip set type uses a memory range to store either IPv4 host (default) or IPv4 network addresses. A bitmap:ip type of set can store up to 65536 entries.
CREATE-OPTIONS := range fromip-toip|ip/cidr [ netmask cidr ] [ timeout value ] [ counters ] [ comment ] [ skbinfo ]
ADD-ENTRY := { ip | fromip-toip | ip/cidr }
ADD-OPTIONS := [ timeout value ] [ packets value ] [ bytes value ] [ comment string ] [ skbmark value ] [ skbprio value ] [ skbqueue value ]
DEL-ENTRY := { ip | fromip-toip | ip/cidr }
TEST-ENTRY := ip
Mandatory create options:
range fromip-toip|ip/cidrโ Create the set from the specified inclusive address range expressed in an IPv4 address range or network. The size of the range (in entries) cannot exceed the limit of maximum65536elements.
Optional create options:
netmask cidrโ When the optionalnetmaskparameter specified, network addresses will be stored in the set instead of IP host addresses. Thecidrprefix value must be between1-32. An IP address will be in the set if the network address, which is resulted by masking the address with the specified netmask, can be found in the set.
The bitmap:ip type supports adding or deleting multiple entries in one command.
Examples:
ipset create foo bitmap:ip range 192.168.0.0/16
ipset add foo 192.168.1/24
ipset test foo 192.168.1.1
๐ bitmap:ip,mac ๐
The bitmap:ip,mac set type uses a memory range to store IPv4 and a MAC address pairs. A bitmap:ip,mac type of set can store up to 65536 entries.
CREATE-OPTIONS := range fromip-toip|ip/cidr [ timeout value ] [ counters ] [ comment ] [ skbinfo ]
ADD-ENTRY := ip[,macaddr]
ADD-OPTIONS := [ timeout value ] [ packets value ] [ bytes value ] [ comment string ] [ skbmark value ] [ skbprio value ] [ skbqueue value ]
DEL-ENTRY := ip[,macaddr]
TEST-ENTRY := ip[,macaddr]
Mandatory options to use when creating a bitmap:ip,mac type of set:
range fromip-toip|ip/cidrโ Create the set from the specified inclusive address range expressed in an IPv4 address range or network. The size of the range cannot exceed the limit of maximum65536entries.
The bitmap:ip,mac type is exceptional in the sense that the MAC part can be left out when adding/deleting/testing entries in the set. If we add an entry without the MAC address specified, then when the first time the entry is matched by the kernel, it will automatically fill out the missing MAC address with the MAC address from the packet. The source MAC address is used if the entry matched due to a src parameter of the set match, and the destination MAC address is used if available and the entry matched due to a dst parameter. If the entry was specified with a timeout value, the timer starts off when the IP and MAC address pair is complete.
The bitmap:ip,mac type of sets require two src/dst parameters of the set match and SET target netfilter kernel modules. For matches on destination MAC addresses, see COMMENTS below.
Examples:
ipset create foo bitmap:ip,mac range 192.168.0.0/16
ipset add foo 192.168.1.1,12:34:56:78:9A:BC
ipset test foo 192.168.1.1
๐ bitmap:port ๐
The bitmap:port set type uses a memory range to store port numbers and such a set can store up to 65536 ports.
CREATE-OPTIONS := range fromport-toport [ timeout value ] [ counters ] [ comment ] [ skbinfo ]
ADD-ENTRY := { [proto:]port | [proto:]fromport-toport }
ADD-OPTIONS := [ timeout value ] [ packets value ] [ bytes value ] [ comment string ] [ skbmark value ] [ skbprio value ] [ skbqueue value ]
DEL-ENTRY := { [proto:]port | [proto:]fromport-toport }
TEST-ENTRY := [proto:]port
Mandatory options to use when creating a bitmap:port type of set:
range [proto:]fromport-toportโ Create the set from the specified inclusive port range.
The set match and SET target netfilter kernel modules interpret the stored numbers as TCP or UDP port numbers.
proto only needs to be specified if a service name is used and that name does not exist as a TCP service. The protocol is never stored in the set, just the port number of the service.
Examples:
ipset create foo bitmap:port range 0-1024
ipset add foo 80
ipset test foo 80
ipset del foo udp:[macon-udp]-[tn-tl-w2]
๐ hash:ip ๐
The hash:ip set type uses a hash to store IP host addresses (default) or network addresses. Zero valued IP address cannot be stored in a hash:ip type of set.
okay bestie, picking right back up where we left off โ here's the rest of what hash:ip is willing to take at create time, plus what you can hand it per entry:
CREATE-OPTIONS := [ family { inet | inet6 } ] [ hashsize value ] [ maxelem value ] [ bucketsize value ] [ netmask cidr ] [ bitmask mask ] [ timeout value ] [ counters ] [ comment ] [ skbinfo ]
ADD-ENTRY := ipaddr
ADD-OPTIONS := [ timeout value ] [ packets value ] [ bytes value ] [ comment string ] [ skbmark value ] [ skbprio value ] [ skbqueue value ]
DEL-ENTRY := ipaddr
TEST-ENTRY := ipaddr
Optional create options, and yes we're doing them again because each set type has its own lil rules ๐
netmask cidrโ when you actually pass this optionalnetmaskparameter, the set stores network addresses instead of IP host addresses. Thatcidrprefix value has to sit between 1-32 for IPv4 and between 1-128 for IPv6. An IP address counts as being in the set if the network address โ the one you get by masking the address with the netmask โ can be found in the set. Like, the whole vibe is "we're matching blocks not people". Examples:
ipset create foo hash:ip netmask 30
ipset add foo 192.168.1.0/24
ipset test foo 192.168.1.2
bitmask maskโ this one works similar tonetmaskbut it will accept any valid IPv4/v6 address. It does not have to be a valid netmask. so yeah, it's the unhinged flexible cousin ๐ฆ
๐ hash:mac ๐
The hash:mac set type uses a hash to store MAC addresses. Zero valued MAC addresses cannot be stored in a hash:mac type of set โ like, it's just not happening, bestie. For matches on destination MAC addresses, see COMMENTS below.
CREATE-OPTIONS := [ hashsize value ] [ maxelem value ] [ bucketsize value ] [ timeout value ] [ counters ] [ comment ] [ skbinfo ]
ADD-ENTRY := macaddr
ADD-OPTIONS := [ timeout value ] [ packets value ] [ bytes value ] [ comment string ] [ skbmark value ] [ skbprio value ] [ skbqueue value ]
DEL-ENTRY := macaddr
TEST-ENTRY := macaddr
Examples, because seeing it > reading it fr fr:
ipset create foo hash:mac
ipset add foo 01:02:03:04:05:06
ipset test foo 01:02:03:04:05:06
๐ฆ hash:ip,mac ๐ฆ
The hash:ip,mac set type uses a hash to store IP and a MAC address pairs โ it's giving power couple, honestly. Zero valued MAC addresses cannot be stored in a hash:ip,mac type of set. For matches on destination MAC addresses, see COMMENTS below.
CREATE-OPTIONS := [ family { inet | inet6 } ] [ hashsize value ] [ maxelem value ] [ bucketsize value ] [ timeout value ] [ counters ] [ comment ] [ skbinfo ]
ADD-ENTRY := ipaddr,macaddr
ADD-OPTIONS := [ timeout value ] [ packets value ] [ bytes value ] [ comment string ] [ skbmark value ] [ skbprio value ] [ skbqueue value ]
DEL-ENTRY := ipaddr,macaddr
TEST-ENTRY := ipaddr,macaddr
Examples:
ipset create foo hash:ip,mac
ipset add foo 1.1.1.1,01:02:03:04:05:06
ipset test foo 1.1.1.1,01:02:03:04:05:06
๐ hash:net ๐
The hash:net set type uses a hash to store different sized IP network addresses. A network address with zero prefix size cannot be stored in this type of sets. periodt.
CREATE-OPTIONS := [ family { inet | inet6 } ] [ hashsize value ] [ maxelem value ] [ bucketsize value ] [ timeout value ] [ counters ] [ comment ] [ skbinfo ]
ADD-ENTRY := netaddr
ADD-OPTIONS := [ timeout value ] [ nomatch ] [ packets value ] [ bytes value ] [ comment string ] [ skbmark value ] [ skbprio value ] [ skbqueue value ]
DEL-ENTRY := netaddr
TEST-ENTRY := netaddr
where netaddr := ip[/cidr]
When you're adding/deleting/testing entries, if the cidr prefix parameter is not specified, then the host prefix value is assumed. When adding/deleting entries, the exact element is added/deleted and overlapping elements are not checked by the kernel. When testing entries, if a host address is tested, then the kernel tries to match the host address in the networks added to the set and reports the result accordingly. so basically it'll go looking for you ๐
From the set netfilter match point of view, the searching for a match always starts from the smallest size of netblock (most specific prefix) to the largest one (least specific prefix) added to the set. When adding/deleting IP addresses to the set by the SET netfilter target, it will be added/deleted by the most specific prefix which can be found in the set, or by the host prefix value if the set is empty.
The lookup time grows linearly with the number of the different prefix values added to the set โ iykyk, more prefixes, more walking.
Example:
ipset create foo hash:net
ipset add foo 192.168.0.0/24
ipset add foo 10.1.0.0/16
ipset add foo 192.168.0/24
ipset add foo 192.168.0/30 nomatch
When matching the elements in the set above, all IP addresses will match from the networks 192.168.0.0/24, 10.1.0.0/16 and 192.168.0/24 except the ones from 192.168.0/30. slay.
๐ hash:net,net ๐
The hash:net,net set type uses a hash to store pairs of different sized IP network addresses. Bear in mind that the first parameter has precedence over the second, so a nomatch entry could be potentially be ineffective if a more specific first parameter existed with a suitable second parameter. Network address with zero prefix size cannot be stored in this type of set.
CREATE-OPTIONS := [ family { inet | inet6 } ] [ hashsize value ] [ maxelem value ] [ bucketsize value ] [ netmask cidr ] [ bitmask mask ] [ timeout value ] [ counters ] [ comment ] [ skbinfo ]
ADD-ENTRY := netaddr,netaddr
ADD-OPTIONS := [ timeout value ] [ nomatch ] [ packets value ] [ bytes value ] [ comment string ] [ skbmark value ] [ skbprio value ] [ skbqueue value ]
DEL-ENTRY := netaddr,netaddr
TEST-ENTRY := netaddr,netaddr
where netaddr := ip[/cidr]
When adding/deleting/testing entries, if the cidr prefix parameter is not specified, then the host prefix value is assumed. When adding/deleting entries, the exact element is added/deleted and overlapping elements are not checked by the kernel. When testing entries, if a host address is tested, then the kernel tries to match the host address in the networks added to the set and reports the result accordingly.
From the set netfilter match point of view, the searching for a match always starts from the smallest size of netblock (most specific prefix) to the largest one (least specific prefix) with the first param having precedence. When adding/deleting IP addresses to the set by the SET netfilter target, it will be added/deleted by the most specific prefix which can be found in the set, or by the host prefix value if the set is empty.
The lookup time grows linearly with the number of the different prefix values added to the first parameter of the set. The number of secondary prefixes further increases this as the list of secondary prefixes is traversed per primary prefix. (not me explaining quadratic suffering ๐ญ)
Optional create options:
netmask cidrโ when the optionalnetmaskparameter is specified, network addresses will be stored in the set instead of IP host addresses. Thecidrprefix value must be between 1-32 for IPv4 and between 1-128 for IPv6. An IP address will be in the set if the network address, which is resulted by masking the address with the netmask, can be found in the set.bitmask maskโ this works similar tonetmaskbut it will accept any valid IPv4/v6 address. It does not have to be a valid netmask.
Example:
ipset create foo hash:net,net
ipset add foo 192.168.0.0/24,10.0.1.0/24
ipset add foo 10.1.0.0/16,10.255.0.0/24
ipset add foo 192.168.0/24,192.168.54.0-192.168.54.255
ipset add foo 192.168.0/30,192.168.64/30 nomatch
When matching the elements in the set above, all IP addresses will match from the networks 192.168.0.0/24<->10.0.1.0/24, 10.1.0.0/16<->10.255.0.0/24 and 192.168.0/24<->192.168.54.0/24 except the ones from 192.168.0/30<->192.168.64/30.
๐ hash:ip,port ๐
The hash:ip,port set type uses a hash to store IP address and port number pairs. The port number is interpreted together with a protocol (default TCP) and zero protocol number cannot be used.
CREATE-OPTIONS := [ family { inet | inet6 } ] [ hashsize value ] [ maxelem value ] [ bucketsize value ] [ netmask cidr ] [ bitmask mask ] [ timeout value ] [ counters ] [ comment ] [ skbinfo ]
ADD-ENTRY := ipaddr,[proto:]port
ADD-OPTIONS := [ timeout value ] [ packets value ] [ bytes value ] [ comment string ] [ skbmark value ] [ skbprio value ] [ skbqueue value ]
DEL-ENTRY := ipaddr,[proto:]port
TEST-ENTRY := ipaddr,[proto:]port
The [proto:]port part of the elements may be expressed in the following forms, where the range variations are valid when adding or deleting entries:
portname[-portname]โ TCP port or range of ports expressed in TCP portname identifiers from/etc/servicesportnumber[-portnumber]โ TCP port or range of ports expressed in TCP port numberstcp|sctp|udp|udplite:portname|portnumber[-portname|portnumber]โ TCP, SCTP, UDP or UDPLITE port or port range expressed in port name(s) or port number(s)icmp:codename|type/codeโ ICMP codename or type/code. The supported ICMP codename identifiers can always be listed by the help command.icmpv6:codename|type/codeโ ICMPv6 codename or type/code. The supported ICMPv6 codename identifiers can always be listed by the help command.proto:0โ all other protocols, as an identifier from/etc/protocolsor number. The pseudo port number must be zero.
The hash:ip,port type of sets require two src/dst parameters of the set match and SET target kernel modules. heads up ๐
Optional create options:
netmask cidrโ when the optionalnetmaskparameter is specified, network addresses will be stored in the set instead of IP host addresses. Thecidrprefix value must be between 1-32 for IPv4 and between 1-128 for IPv6. An IP address will be in the set if the network address, which is resulted by masking the address with the netmask, can be found in the set.bitmask maskโ this works similar tonetmaskbut it will accept any valid IPv4/v6 address. It does not have to be a valid netmask.
Examples:
ipset create foo hash:ip,port
ipset add foo 192.168.1.0/24,80-82
ipset add foo 192.168.1.1,udp:53
ipset add foo 192.168.1.1,vrrp:0
ipset test foo 192.168.1.1,80
โจ hash:net,port โจ
The hash:net,port set type uses a hash to store different sized IP network address and port pairs. The port number is interpreted together with a protocol (default TCP) and zero protocol number cannot be used. Network address with zero prefix size is not accepted either. like, zero prefix, zero chill ๐
CREATE-OPTIONS := [ family { inet | inet6 } ] [ hashsize value ] [ maxelem value ] [ bucketsize value ] [ timeout value ] [ counters ] [ comment ] [ skbinfo ]
ADD-ENTRY := netaddr,[proto:]port
so the hash:net,port element syntax wraps up like this, bestie:
ADD-OPTIONS := [ timeout value ] [ nomatch ] [ packets value ] [ bytes
value ] [ comment string ] [ skbmark value ] [ skbprio value ] [
skbqueue value ]
DEL-ENTRY := netaddr,[proto:]port
TEST-ENTRY := netaddr,[proto:]port
where netaddr := ip[/cidr]
For the netaddr part of the elements, go look at the hash:net set type description. For the [proto:]port part, it's the hash:ip,port set type description. Easy peasy. โจ
When you're adding/deleting/testing entries and you don't specify the cidr prefix parameter, the host prefix value is assumed. When adding/deleting entries, the exact element is added/deleted and the kernel does not check overlapping elements. When testing entries, if a host address is tested, the kernel tries to match the host address in the networks added to the set and reports the result accordingly. No cap. ๐
From the set netfilter match point of view, searching for a match always starts from the smallest size of netblock (most specific prefix) to the largest one (least specific prefix) added to the set. When adding/deleting IP addresses to the set by the SET netfilter target, it will be added/deleted by the most specific prefix which can be found in the set, or by the host prefix value if the set is empty. Periodt. ๐
The lookup time grows linearly with the number of the different prefix values added to the set. Just so you know. ๐ญ
Examples, bestie:
ipset create foo hash:net,port
ipset add foo 192.168.0/24,25
ipset add foo 10.1.0.0/16,80
ipset test foo 192.168.0/24,25
hash:ip,port,ip ๐
The hash:ip,port,ip set type uses a hash to store IP address, port number and a second IP address triples. The port number is interpreted together with a protocol (default TCP) and zero protocol number cannot be used. Slay. โจ
CREATE-OPTIONS := [ family { inet | inet6 } ] [ hashsize value ] [
maxelem value ] [ bucketsize value ] [ timeout value ] [ counters ] [
comment ] [ skbinfo ]
ADD-ENTRY := ipaddr,[proto:]port,ip
ADD-OPTIONS := [ timeout value ] [ packets value ] [ bytes value ] [
comment string ] [ skbmark value ] [ skbprio value ] [ skbqueue value ]
DEL-ENTRY := ipaddr,[proto:]port,ip
TEST-ENTRY := ipaddr,[proto:]port,ip
For the first ipaddr and [proto:]port parts of the elements, see the descriptions at the hash:ip,port set type. The hash:ip,port,ip type of sets require three src/dst parameters of the set match and SET target kernel modules. ๐ฅ
Examples:
ipset create foo hash:ip,port,ip
ipset add foo 192.168.1.1,80,10.0.0.1
ipset test foo 192.168.1.1,udp:53,10.0.0.1
hash:ip,port,net ๐ฆ
The hash:ip,port,net set type uses a hash to store IP address, port number and IP network address triples. The port number is interpreted together with a protocol (default TCP) and zero protocol number cannot be used. Network address with zero prefix size cannot be stored either. Not me finding that out the hard way. ๐
CREATE-OPTIONS := [ family { inet | inet6 } ] [ hashsize value ] [
maxelem value ] [ bucketsize value ] [ timeout value ] [ counters ] [
comment ] [ skbinfo ]
ADD-ENTRY := ipaddr,[proto:]port,netaddr
ADD-OPTIONS := [ timeout value ] [ nomatch ] [ packets value ] [ bytes
value ] [ comment string ] [ skbmark value ] [ skbprio value ] [
skbqueue value ]
DEL-ENTRY := ipaddr,[proto:]port,netaddr
TEST-ENTRY := ipaddr,[proto:]port,netaddr
where netaddr := ip[/cidr]
For the ipaddr and [proto:]port parts of the elements, see the descriptions at the hash:ip,port set type. For the netaddr part, see the description at the hash:net set type.
From the set netfilter match point of view, searching for a match always starts from the smallest size of netblock (most specific cidr) to the largest one (least specific cidr) added to the set. When adding/deleting triples to the set by the SET netfilter target, it will be added/deleted by the most specific cidr which can be found in the set, or by the host cidr value if the set is empty. Iconic. ๐
The lookup time grows linearly with the number of the different cidr values added to the set.
The hash:ip,port,net type of sets require three src/dst parameters of the set match and SET target kernel modules.
Examples:
ipset create foo hash:ip,port,net
ipset add foo 192.168.1,80,10.0.0/24
ipset add foo 192.168.2,25,10.1.0.0/16
ipset test foo 192.168.1,80.10.0.0/24
hash:ip,mark ๐
The hash:ip,mark set type uses a hash to store IP address and packet mark pairs. Cute. โจ
CREATE-OPTIONS := [ family { inet | inet6 } ] [ markmask value ] [
hashsize value ] [ maxelem value ] [ bucketsize value ] [ timeout value
] [ counters ] [ comment ] [ skbinfo ]
ADD-ENTRY := ipaddr,mark
ADD-OPTIONS := [ timeout value ] [ packets value ] [ bytes value ] [
comment string ] [ skbmark value ] [ skbprio value ] [ skbqueue value ]
DEL-ENTRY := ipaddr,mark
TEST-ENTRY := ipaddr,mark
Optional create options:
markmask valueโ Lets you set bits you are interested in the packet mark. This value is then used to perform bitwise AND operation for every mark added.markmaskcan be any value between1and4294967295, by default all 32 bits are set. ๐
The mark can be any value between 0 and 4294967295.
The hash:ip,mark type of sets require two src/dst parameters of the set match and SET target kernel modules.
Examples:
ipset create foo hash:ip,mark
ipset add foo 192.168.1.0/24,555
ipset add foo 192.168.1.1,0x63
ipset add foo 192.168.1.1,111236
hash:net,port,net ๐
The hash:net,port,net set type behaves similarly to hash:ip,port,net but accepts a cidr value for both the first and last parameter. Either subnet is permitted to be a /0 should you wish to match port between all destinations. Main character energy fr fr. ๐
CREATE-OPTIONS := [ family { inet | inet6 } ] [ hashsize value ] [
maxelem value ] [ bucketsize value ] [ timeout value ] [ counters ] [
comment ] [ skbinfo ]
ADD-ENTRY := netaddr,[proto:]port,netaddr
ADD-OPTIONS := [ timeout value ] [ nomatch ] [ packets value ] [ bytes
value ] [ comment string ] [ skbmark value ] [ skbprio value ] [
skbqueue value ]
DEL-ENTRY := netaddr,[proto:]port,netaddr
TEST-ENTRY := netaddr,[proto:]port,netaddr
where netaddr := ip[/cidr]
For the [proto:]port part of the elements, see the description at the hash:ip,port set type. For the netaddr part, see the description at the hash:net set type.
From the set netfilter match point of view, searching for a match always starts from the smallest size of netblock (most specific cidr) to the largest one (least specific cidr) added to the set. When adding/deleting triples to the set by the SET netfilter target, it will be added/deleted by the most specific cidr which can be found in the set, or by the host cidr value if the set is empty. The first subnet has precedence when performing the most-specific lookup, just as for hash:net,net. The way that works is lowkey iconic. โจ
The lookup time grows linearly with the number of the different cidr values added to the set and by the number of secondary cidr values per primary.
The hash:net,port,net type of sets require three src/dst parameters of the set match and SET target kernel modules.
Examples:
ipset create foo hash:net,port,net
ipset add foo 192.168.1.0/24,0,10.0.0/24
ipset add foo 192.168.2.0/24,25,10.1.0.0/16
ipset test foo 192.168.1.1,80,10.0.0.1
hash:net,iface ๐ง
The hash:net,iface set type uses a hash to store different sized IP network address and interface name pairs. Obsessed. ๐
CREATE-OPTIONS := [ family { inet | inet6 } ] [ hashsize value ] [
maxelem value ] [ bucketsize value ] [ timeout value ] [ counters ] [
comment ] [ skbinfo ]
ADD-ENTRY := netaddr,[physdev:]iface
ADD-OPTIONS := [ timeout value ] [ nomatch ] [ packets value ] [ bytes
value ] [ comment string ] [ skbmark value ] [ skbprio value ] [
skbqueue value ] [ wildcard ]
DEL-ENTRY := netaddr,[physdev:]iface
TEST-ENTRY := netaddr,[physdev:]iface
where netaddr := ip[/cidr]
For the netaddr part of the elements, see the description at the hash:net set type.
When adding/deleting/testing entries, if the cidr prefix parameter is not specified, then the host prefix value is assumed. When adding/deleting entries, the exact element is added/deleted and overlapping elements are not checked by the kernel. When testing entries, if a host address is tested, then the kernel tries to match the host address in the networks added to the set and reports the result accordingly. No cap. ๐
From the set netfilter match point of view, searching for a match always starts from the smallest size of netblock (most specific prefix) to the largest one (least specific prefix) added to the set. When adding/deleting IP addresses to the set by the SET netfilter target, it will be added/deleted by the most specific prefix which can be found in the set, or by the host prefix value if the set is empty.
The second direction parameter of the set match and SET target modules corresponds to the incoming/outgoing interface: src to the incoming one (similar to the -i flag of iptables), while dst to the outgoing one (similar to the -o flag of iptables). When the interface is flagged with physdev:, the interface is interpreted as the incoming/outgoing bridge port. iykyk. ๐
The lookup time grows linearly with the number of the different prefix values added to the set.
The internal restriction of thehash:net,ifaceset type is that the same network prefix cannot be stored with more than64different interfaces in a single set. Not me crying about that limit. ๐ญ
Examples:
ipset create foo hash:net,iface
ipset add foo 192.168.0/24,eth0
ipset add foo 10.1.0.0/16,eth1
ipset test foo 192.168.0/24,eth0
list:set ๐
The list:set type uses a simple list in which you can store set names. So meta. โจ
CREATE-OPTIONS := [ size value ] [ timeout value ] [ counters ] [
comment ] [ skbinfo ]
ADD-ENTRY := setname [ { before | after } setname ]
ADD-OPTIONS := [ timeout value ] [ packets value ] [ bytes value ] [
comment string ] [ skbmark value ] [ skbprio value ] [ skbqueue value ]
DEL-ENTRY := setname [ { before | after } setname ]
TEST-ENTRY := setname [ { before | after } setname ]
Optional create options:
size valueโ The size of the list, the default is8. The parameter is ignored since ipset version6.24. So like, it's giving legacy. ๐
By the ipset command you can add, delete and test set names in a list:set type of set. Periodt. ๐
Okay bestie, so you can totally poke at the sets inside a <code>list:set</code> using the <code>set</code> match or the <code>SET</code> target from netfilter ๐ โ like, test entries, add entries, delete entries, all of it. The match is gonna go hunting for a matching entry inside those sets, and the target is gonna try to yeet an entry into the first set that'll actually take it. โจ
And the number of direction options you hand to the match and target? Lowkey the whole plot. Sets that need more parameters than you specified get skipped, periodt. Sets with equal or fewer parameters get checked, and their elements get added or deleted. So if a and b are list:set type sets, then in this command:
iptables -m set --match-set a src,dst -j SET --add-set b src,dst
the match and target will skip any set in a and b that stores data triples ๐ซ, but will match every set with single or double data storage in a, stop matching at the first successful set, and then add src to the first single-storage set โ or src,dst to the first double-storage set โ in b that can accept the entry. Think of a list:set type set as an ordered union of the set elements. Iconic, honestly. ๐
Not me being dramatic, but please note: with theipsetcommand you can add, delete and test the setnames in alist:settype of set โ not whether some set's member (like an IP address) is present. Different thing entirely, bestie. ๐ซถ
๐ง GENERAL RESTRICTIONS ๐ง
- Zero valued set entries? Cannot vibe with hash methods at all. Nope.
- Zero protocol value with ports? Also a no. ๐ซ
๐ฌ COMMENTS ๐ฌ
Okay so real talk, choosing your set type is a whole personality decision and here's the tea:
- Wanna store same-size subnets from one given network (say
/24blocks out of a/8network)? Use thebitmap:ipset type. ๐ - Wanna store random same-size networks (say random
/24blocks)? Use thehash:ipset type. ๐ฆ - Got random-size netblocks?
hash:net. Boom, that's the one. ๐
Now, about matching on destination MAC addresses using the dst parameter of the set match netfilter kernel modules โ this only works if the destination MAC address is actually available in the packet at that processing stage. Which means: it only applies to incoming packets in the PREROUTING, INPUT and FORWARD chains, matched against the MAC address as originally found in the received packet (typically, one of the MAC addresses of the local host). ๐ซก
Important: this is not the destination MAC address that a destination IP address resolves to, after routing. Not the same thing, don't get it twisted. If the MAC address isn't available (e.g. in the OUTPUT chain), the packet will simply not match. That's it, that's the rule. ๐
Backward compatibility is maintained, so the old ipset syntax is still supported. Slay, legacy support. ๐
And heads up: the iptree and iptreemap set types are removed โ if you refer to them, they get automatically replaced by hash:ip type of sets. Gone but not forgotten, ig. โจ
๐ฉบ DIAGNOSTICS ๐ฉบ
Various error messages get printed to standard error. The exit code is 0 for correct functioning. So if you see a 0, you ate. ๐
๐ BUGS ๐
Bugs? No, just funny features. :-) OK, just kidding...
(She's unserious and I love that for her. ๐ญ)
๐ SEE ALSO ๐
๐ AUTHORS ๐
- Jozsef Kadlecsik wrote
ipset, which is based onippoolby Joakim Axelsson, Patrick Schaaf and Martin Josefsson. ๐ซถ - Sven Wegener wrote the
iptreemaptype. ๐
๐ LAST REMARK ๐
I stand on the shoulders of giants.
Periodt. That's the whole page, bestie โ go forth and configure your sets, you absolute main character. ๐ โจ๐ธ
This gorgeous thing came from ipset by Jozsef Kadlecsik, dated Jun 25, 2015, and it's page IPSET(8). Bye babes, ily, go read iptables(8) next ๐๐
๐ฆ where this page comes from
- alpine 3.22: ipset-doc 7.24-r0 ยท GPL-2.0-only
- alpine 3.23: ipset-doc 7.24-r0 ยท GPL-2.0-only
- alpine 3.24: ipset-doc 7.24-r0 ยท GPL-2.0-only
- arch rolling: ipset 7.24-1 ยท GPL-2.0-only
- fedora 43: ipset 7.24-2.fc43 ยท GPL-2.0-only
- fedora 44: ipset 7.24-3.fc44 ยท GPL-2.0-only
- nixos 26.05: ipset 7.24
- nixpkgs unstable: ipset 7.24
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms