Skip to content

Commit

Permalink
fix(ipset): fix configuring IP range for ipsets with nftables
Browse files Browse the repository at this point in the history
Setting an IP range with nftables did not work:

    firewall-cmd --permanent --delete-ipset=testipset || :
    firewall-cmd --permanent --delete-zone=testzone || :

    ENTRY=1.1.1.1-1.1.1.10

    firewall-cmd --permanent --new-ipset=testipset --type=hash:ip
    firewall-cmd --permanent --ipset=testipset --add-entry="$ENTRY"
    firewall-cmd --permanent --info-ipset=testipset
    firewall-cmd --permanent --new-zone=testzone
    firewall-cmd --permanent --zone=testzone --add-rich-rule='rule family="ipv4" source ipset="testipset" service name="ssh" accept'

    firewall-cmd --reload &

This would generate the following JSON request:

    {
      "add": {
        "element": {
          "family": "inet",
          "table": "firewalld",
          "name": "testipset",
          "elem": [
            "1.1.1.1-1.1.1.10"
          ]
        }
      }
    }

libnftables will try to resolve "1.1.1.1-1.1.1.10" via getaddrinfo().  Calling
getaddrinfo() to resolve names is bound to fail, and it blocks the process for
a very long time. libnftables should not block the calling process ([1]).

We need to generate the correct JSON request, which is

    {
      "add": {
        "element": {
          "family": "inet",
          "table": "firewalld",
          "name": "testipset",
          "elem": [
            {
              "range": [
                "1.1.1.1",
                "1.1.1.10"
              ]
            }
          ]
        }
      }
    }

This is an ugly fix, because the parsing of ipset entries is duplicated
and inconsistent.  A better solution for that shall follow.

[1] https://marc.info/?l=netfilter-devel&m=168901121103612

https://bugzilla.redhat.com/show_bug.cgi?id=2028748

Fixes: 1582c5d ('feat: nftables: convert to libnftables JSON interface')
(cherry picked from commit 4db89e3)
  • Loading branch information
thom311 authored and erig0 committed Oct 2, 2023
1 parent 047f64e commit 5c5924b
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 14 deletions.
27 changes: 15 additions & 12 deletions src/firewall/core/nftables.py
Original file line number Diff line number Diff line change
Expand Up @@ -1795,19 +1795,22 @@ def _set_entry_fragment(self, name, entry):
fragment.append({"range": [port_str[:index], port_str[index+1:]]})

elif format in ["ip", "net"]:
try:
index = entry_tokens[i].index("/")
except ValueError:
addr = entry_tokens[i]
if "family" in obj.options and obj.options["family"] == "inet6":
addr = normalizeIP6(addr)
fragment.append(addr)
if '-' in entry_tokens[i]:
fragment.append({"range": entry_tokens[i].split('-') })
else:
addr = entry_tokens[i][:index]
if "family" in obj.options and obj.options["family"] == "inet6":
addr = normalizeIP6(addr)
fragment.append({"prefix": {"addr": addr,
"len": int(entry_tokens[i][index+1:])}})
try:
index = entry_tokens[i].index("/")
except ValueError:
addr = entry_tokens[i]
if "family" in obj.options and obj.options["family"] == "inet6":
addr = normalizeIP6(addr)
fragment.append(addr)
else:
addr = entry_tokens[i][:index]
if "family" in obj.options and obj.options["family"] == "inet6":
addr = normalizeIP6(addr)
fragment.append({"prefix": {"addr": addr,
"len": int(entry_tokens[i][index+1:])}})
else:
fragment.append(entry_tokens[i])
return [{"concat": fragment}] if len(type_format) > 1 else fragment
Expand Down
4 changes: 2 additions & 2 deletions src/tests/cli/firewall-cmd.at
Original file line number Diff line number Diff line change
Expand Up @@ -890,15 +890,15 @@ FWD_START_TEST([ipset])

dnl multi dimensional sets
FWD_CHECK([--permanent --new-ipset=foobar --type=hash:ip,port], 0, ignore)
FWD_CHECK([--permanent --ipset=foobar --add-entry=10.10.10.10,1234], 0, ignore)
FWD_CHECK([--permanent --ipset=foobar --add-entry=10.10.10.10-10.10.10.12,1234], 0, ignore)
FWD_CHECK([--permanent --ipset=foobar --add-entry=10.10.10.10,2000-2100], 0, ignore)
FWD_RELOAD
NFT_LIST_SET([foobar], 0, [dnl
table inet firewalld {
set foobar {
type ipv4_addr . inet_proto . inet_service
flags interval
elements = { 10.10.10.10 . tcp . 1234,
elements = { 10.10.10.10-10.10.10.12 . tcp . 1234,
10.10.10.10 . tcp . 2000-2100 }
}
}
Expand Down

0 comments on commit 5c5924b

Please sign in to comment.