Firewall-cmd and ipset show conflicting information, cannot update ipset

I’m having a lot of problems configuring firewalld. I was able to create a firewall configuration with blocking based on ipsets using the GUI, but I cannot figure out how to script updates to the ipsets. When I use ipset to make changes, ipset shows me the changes are successful and I can tell the new blockset are working. But, when I use firewall-cmd I see the old ipset lists, which makes no sense at all.

Why is firewall-cmd not showing the same thing as ipset?

How do I write a script that can change an existing ipset list that already exists?

1 Like

Check out an example:


And make sure you are not mixing runtime and permanent configurations.

Hmm, well, I am aware of the difference between permanent and runtime. I don’t see anything on that page that makes me think I’m doing it wrong. Unless there is a reason you cannot use ipset outside of firewall-cmd, which is not what is says anywhere I’ve read.

Here’s the problem. I have an ipset with this in it:

# ipset list local-blocklist
Name: local-blocklist
Type: hash:net
Revision: 6
Header: family inet hashsize 1024 maxelem 512
Size in memory: 600
References: 7
Number of entries: 4
Members:
103.133.104.0/23
112.85.0.0/16
103.125.0.0/16
103.114.0.0/16

But, firewall-cmd doesn’t see the same thing:
# firewall-cmd --ipset=local-blocklist --get-entries
112.85.0.0/16
103.114.0.0/16
103.125.0.0/16

The permanent ipset is the same:
# firewall-cmd --permanent --ipset=local-blocklist --get-entries
112.85.0.0/16
103.114.0.0/16
103.125.0.0/16

Okay so, if I remove the extra ip network with ipset, then add it back with firewall-cmd, then it shows up correctly.

# ipset del local-blocklist 103.133.104.0/23
# firewall-cmd --ipset=local-blocklist --add-entry=103.133.104.0/23
success
# ipset list local-blocklist
Name: local-blocklist
Type: hash:net
Revision: 6
Header: family inet hashsize 1024 maxelem 512
Size in memory: 600
References: 7
Number of entries: 4
Members:
103.133.104.0/23
112.85.0.0/16
103.125.0.0/16
103.114.0.0/16
# firewall-cmd --ipset=local-blocklist --get-entries
112.85.0.0/16
103.114.0.0/16
103.125.0.0/16
103.133.104.0/23

But there is no reason for this behavior. How is it possible for firewall-cmd --add-entry to update the active ipsets without firewall-cmd --get-entries reading the active ipsets? Is firewall-cmd not actually reading the ipsets from the kernel when I run --get-entries? Is it some kind firewalld copy of the real ipset it keeps showing me? That is not explained in the documentation. Exactly why these “example” tutorials are incomplete. I mean, it still looks like bug. How can I be sure this is correct behavior and not a bug?

Yep, you should not use raw commands such as iptables and ip6tables if you want to sync the status with firewalld.
It may not be mentioned explicitly, but it seems to be relevant for the ipset command as well.
Perhaps you should make an alias/function for firewall-cmd --ipset=... --add-entry=... if you find it inconvenient.

Probably there is, e.g. we can cache the configuration and don’t need to invoke low-level API functions to fetch and parse it again.

You can analyze the source code or try to raise an issue.

I think you are right. I just cost me a lot of time. I used the ipset ‘swap’ command which is atomic and ideal for updating ipsets. With firewall-cmd, which does not re-implement the swap sub-command, I had to completely change the logic of the script. I worked it out, but I had to start over.

If firewall-cmd was supposed to be a substitute, is should implement the same command set.

Just wish it had said that anywhere I read. Bother.

Thanks all!