Can't add rules to a firewall chain with firewalld

Issues related to configuring your network
Post Reply
PaulJBIs
Posts: 4
Joined: 2020/04/24 18:00:48

Can't add rules to a firewall chain with firewalld

Post by PaulJBIs » 2020/04/24 18:16:02

Hello:

I have a CentOS 7 machine where I'm trying to add some custom firewall rules. I usually use firewalld, so I added them this way:

Code: Select all

firewall-cmd --permanent --direct --add-chain ipv4 filter DOCKER-USER
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 0 -j REJECT -i eth0 -dport 27017
The rules get written to the direct.xml file, which looks like this:

Code: Select all

<?xml version="1.0" encoding="utf-8"?>
<direct>
  <chain table="filter" ipv="ipv4" chain="DOCKER-USER"/>
  <rule priority="0" table="filter" ipv="ipv4" chain="DOCKER-USER">-j REJECT -i 
eth0 -dport 27017</rule>
</direct>
...Buuut, when I try to load them with "firewall-cmd --reload", I get this error:

Code: Select all

Error: COMMAND_FAILED: Direct: '/usr/sbin/iptables-restore -w -n' failed: iptables-restore v1.4.21: The -t option (seen in line 3) cannot be used in iptables-restore.
I found a bug report at https://bugzilla.redhat.com/show_bug.cgi?id=1787510, which make it seem like there's some inconsistency in a command-line parser somewhere, but I don't really understand where or why. What's going on?

User avatar
jlehtone
Posts: 4530
Joined: 2007/12/11 08:17:33
Location: Finland

Re: Can't add rules to a firewall chain with firewalld

Post by jlehtone » 2020/04/25 08:58:03

Lets test on-the-fly:

Code: Select all

# firewall-cmd --direct --add-rule ipv4 filter INPUT 0 -j REJECT -i eth0 -dport 27017
Error: COMMAND_FAILED: '/usr/sbin/iptables-restore -w -n' failed: Bad argument `27017'
Error occurred at line: 2
Try `iptables-restore -h' or 'iptables-restore --help' for more information.
I'd guess that -dport is taken as -d -p -o -r -t. Lets double the dash:

Code: Select all

# firewall-cmd --direct --add-rule ipv4 filter INPUT 0 -j REJECT -i eth0 --dport 27017
Error: COMMAND_FAILED: '/usr/sbin/iptables-restore -w -n' failed: iptables-restore v1.4.21: unknown option "--dport"
Error occurred at line: 2
Try `iptables-restore -h' or 'iptables-restore --help' for more information.
Only some protocols have ports. Test with udp:

Code: Select all

# firewall-cmd --direct --add-rule ipv4 filter INPUT 0 -j REJECT -i eth0 -p udp --dport 27017
success

PaulJBIs
Posts: 4
Joined: 2020/04/24 18:00:48

Re: Can't add rules to a firewall chain with firewalld

Post by PaulJBIs » 2020/04/25 15:42:29

Thanks, that worked. (I used TCP instead of UDP, but it's the same). At least the rule gets added now.

Now for another question: why doesn't the rule "work"? In the sense of it blocking connections.

First let me explain: I'm trying to protect a dockerized server so that it cannot be reached from the Internet, only from localhost. The way Docker works with iptables is explained at https://docs.docker.com/network/iptables/ , but to summarise:

1. Docker manipulates iptables to allow connections to all its containers on startup, adding its own rules in the DOCKER chain.
2. Docker will respect the iptables "DOCKER-USER" chain, and leave those rules alone. In fact, it will process them before the others (at least according to the docs).

So my iptables -nvL says the following:

Code: Select all

Chain DOCKER (2 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     tcp  --  !br-6e1ea609aa86 br-6e1ea609aa86  0.0.0.0/0            172.16.233.100       tcp dpt:53
    0     0 ACCEPT     udp  --  !br-6e1ea609aa86 br-6e1ea609aa86  0.0.0.0/0            172.16.233.100       udp dpt:53
    0     0 ACCEPT     tcp  --  !br-6e1ea609aa86 br-6e1ea609aa86  0.0.0.0/0            172.16.233.11        tcp dpt:443
    0     0 ACCEPT     tcp  --  !br-6e1ea609aa86 br-6e1ea609aa86  0.0.0.0/0            172.16.233.11        tcp dpt:80
    0     0 ACCEPT     tcp  --  !br-6e1ea609aa86 br-6e1ea609aa86  0.0.0.0/0            172.16.233.201       tcp dpt:8025
    0     0 ACCEPT     tcp  --  !br-6e1ea609aa86 br-6e1ea609aa86  0.0.0.0/0            172.16.233.16        tcp dpt:27017
    0     0 ACCEPT     tcp  --  !br-6e1ea609aa86 br-6e1ea609aa86  0.0.0.0/0            172.16.233.15        tcp dpt:11211
    0     0 ACCEPT     tcp  --  !br-6e1ea609aa86 br-6e1ea609aa86  0.0.0.0/0            172.16.233.14        tcp dpt:6379
    0     0 ACCEPT     tcp  --  !br-6e1ea609aa86 br-6e1ea609aa86  0.0.0.0/0            172.16.233.12        tcp dpt:3306
    0     0 ACCEPT     tcp  --  !br-6e1ea609aa86 br-6e1ea609aa86  0.0.0.0/0            172.16.233.13        tcp dpt:5432

Chain DOCKER-ISOLATION (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DROP       all  --  docker0 br-6e1ea609aa86  0.0.0.0/0            0.0.0.0/0           
    0     0 DROP       all  --  br-6e1ea609aa86 docker0  0.0.0.0/0            0.0.0.0/0           
11489   15M RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain DOCKER-USER (0 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 REJECT     tcp  --  etho   *       0.0.0.0/0            0.0.0.0/0            tcp dpt:27017 reject-with icmp-port-unreachable
    0     0 REJECT     tcp  --  etho   *       0.0.0.0/0            0.0.0.0/0            tcp dpt:6379 reject-with icmp-port-unreachable

And yet, if I telnet to port 27017 from another host, I can connect with no problems. Is there anything wrong with my rules?

User avatar
jlehtone
Posts: 4530
Joined: 2007/12/11 08:17:33
Location: Finland

Re: Can't add rules to a firewall chain with firewalld

Post by jlehtone » 2020/04/25 16:06:51

1. iptables -S is more informative than iptables -vL (except that it does not show) the counters.

2. Your custom rules have interface etho. That is neither eth0 nor br-6e1ea609aa86.

3. Can you show also INPUT/FORWARD/whatever, where jumps to DOCKER, DOCKER-ISOLATION, and DOCKER-USER do actually happen? (To proof that USER has higher priority.)

PaulJBIs
Posts: 4
Joined: 2020/04/24 18:00:48

Re: Can't add rules to a firewall chain with firewalld

Post by PaulJBIs » 2020/04/25 17:31:37

Sure. This is my entire list of rules, except the f2b-sshd chain. which is for rules created by fail2ban.

Code: Select all

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
 4481  420K f2b-sshd   tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            multiport dports 22
 3156  342K ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
    0     0 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0           
 3449  139K INPUT_direct  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
 3449  139K INPUT_ZONES_SOURCE  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
 3449  139K INPUT_ZONES  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
   30  5523 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0            ctstate INVALID
  406 21568 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DOCKER-ISOLATION  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 DOCKER     all  --  *      br-71b1db558314  0.0.0.0/0            0.0.0.0/0           
    0     0 ACCEPT     all  --  *      br-71b1db558314  0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
    0     0 ACCEPT     all  --  br-71b1db558314 !br-71b1db558314  0.0.0.0/0            0.0.0.0/0           
    0     0 ACCEPT     all  --  br-71b1db558314 br-71b1db558314  0.0.0.0/0            0.0.0.0/0           
    0     0 DOCKER     all  --  *      docker0  0.0.0.0/0            0.0.0.0/0           
    0     0 ACCEPT     all  --  *      docker0  0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
    0     0 ACCEPT     all  --  docker0 !docker0  0.0.0.0/0            0.0.0.0/0           
    0     0 ACCEPT     all  --  docker0 docker0  0.0.0.0/0            0.0.0.0/0           
    0     0 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
    0     0 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0           
    0     0 FORWARD_direct  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 FORWARD_IN_ZONES_SOURCE  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 FORWARD_IN_ZONES  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 FORWARD_OUT_ZONES_SOURCE  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 FORWARD_OUT_ZONES  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0            ctstate INVALID
    0     0 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited

Chain OUTPUT (policy ACCEPT 63 packets, 7260 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     all  --  *      lo      0.0.0.0/0            0.0.0.0/0           
12722 1077K OUTPUT_direct  all  --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain DOCKER (2 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     tcp  --  !br-71b1db558314 br-71b1db558314  0.0.0.0/0            172.16.233.100       tcp dpt:53
    0     0 ACCEPT     udp  --  !br-71b1db558314 br-71b1db558314  0.0.0.0/0            172.16.233.100       udp dpt:53
    0     0 ACCEPT     tcp  --  !br-71b1db558314 br-71b1db558314  0.0.0.0/0            172.16.233.11        tcp dpt:443
    0     0 ACCEPT     tcp  --  !br-71b1db558314 br-71b1db558314  0.0.0.0/0            172.16.233.11        tcp dpt:80
    0     0 ACCEPT     tcp  --  !br-71b1db558314 br-71b1db558314  0.0.0.0/0            172.16.233.14        tcp dpt:6379
    0     0 ACCEPT     tcp  --  !br-71b1db558314 br-71b1db558314  0.0.0.0/0            172.16.233.201       tcp dpt:8025
    0     0 ACCEPT     tcp  --  !br-71b1db558314 br-71b1db558314  0.0.0.0/0            172.16.233.15        tcp dpt:11211
    0     0 ACCEPT     tcp  --  !br-71b1db558314 br-71b1db558314  0.0.0.0/0            172.16.233.16        tcp dpt:27017
    0     0 ACCEPT     tcp  --  !br-71b1db558314 br-71b1db558314  0.0.0.0/0            172.16.233.13        tcp dpt:5432
    0     0 ACCEPT     tcp  --  !br-71b1db558314 br-71b1db558314  0.0.0.0/0            172.16.233.12        tcp dpt:3306

Chain DOCKER-ISOLATION (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DROP       all  --  docker0 br-71b1db558314  0.0.0.0/0            0.0.0.0/0           
    0     0 DROP       all  --  br-71b1db558314 docker0  0.0.0.0/0            0.0.0.0/0           
 1308 1730K RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain DOCKER-USER (0 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DROP       tcp  --  eth0   *       0.0.0.0/0            0.0.0.0/0            tcp dpt:27017
    0     0 DROP       tcp  --  eth0   *       0.0.0.0/0            0.0.0.0/0            tcp dpt:6379

Chain FORWARD_IN_ZONES (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 FWDI_public  all  --  eth0   *       0.0.0.0/0            0.0.0.0/0           [goto] 
    0     0 FWDI_public  all  --  +      *       0.0.0.0/0            0.0.0.0/0           [goto] 

Chain FORWARD_IN_ZONES_SOURCE (1 references)
 pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD_OUT_ZONES (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 FWDO_public  all  --  *      eth0    0.0.0.0/0            0.0.0.0/0           [goto] 
    0     0 FWDO_public  all  --  *      +       0.0.0.0/0            0.0.0.0/0           [goto] 

Chain FORWARD_OUT_ZONES_SOURCE (1 references)
 pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD_direct (1 references)
 pkts bytes target     prot opt in     out     source               destination         

Chain FWDI_public (2 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 FWDI_public_log  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 FWDI_public_deny  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 FWDI_public_allow  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain FWDI_public_allow (1 references)
 pkts bytes target     prot opt in     out     source               destination         

Chain FWDI_public_deny (1 references)
 pkts bytes target     prot opt in     out     source               destination         

Chain FWDI_public_log (1 references)
 pkts bytes target     prot opt in     out     source               destination         

Chain FWDO_public (2 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 FWDO_public_log  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 FWDO_public_deny  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 FWDO_public_allow  all  --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain FWDO_public_allow (1 references)
 pkts bytes target     prot opt in     out     source               destination         

Chain FWDO_public_deny (1 references)
 pkts bytes target     prot opt in     out     source               destination         

Chain FWDO_public_log (1 references)
 pkts bytes target     prot opt in     out     source               destination         

Chain INPUT_ZONES (1 references)
 pkts bytes target     prot opt in     out     source               destination         
 3449  139K IN_public  all  --  eth0   *       0.0.0.0/0            0.0.0.0/0           [goto] 
    0     0 IN_public  all  --  +      *       0.0.0.0/0            0.0.0.0/0           [goto] 

Chain INPUT_ZONES_SOURCE (1 references)
 pkts bytes target     prot opt in     out     source               destination         

Chain INPUT_direct (1 references)
 pkts bytes target     prot opt in     out     source               destination         

Chain IN_public (2 references)
 pkts bytes target     prot opt in     out     source               destination         
 3449  139K IN_public_log  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
 3449  139K IN_public_deny  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
 3449  139K IN_public_allow  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
 1727 57792 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain IN_public_allow (1 references)
 pkts bytes target     prot opt in     out     source               destination         
  205 10992 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:22 ctstate NEW,UNTRACKED
 1078 43140 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:21 ctstate NEW,UNTRACKED
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:21 ctstate NEW,UNTRACKED
    3   120 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpts:50000:50500 ctstate NEW,UNTRACKED
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:3336 ctstate NEW,UNTRACKED

Chain IN_public_deny (1 references)
 pkts bytes target     prot opt in     out     source               destination         

Chain IN_public_log (1 references)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT_direct (1 references)
 pkts bytes target     prot opt in     out     source               destination         
I just had a look, and br-71b1db558314 is a virtual network interface created by Docker for the internal subnet where the containers live.

As for "etho", it must have been the spellchecker in my computer when pasting the rules here. I just had a look again, and the iptables output in my server does say "eth0", as it should. In fact, the above rules are correct, as you can see.

User avatar
jlehtone
Posts: 4530
Joined: 2007/12/11 08:17:33
Location: Finland

Re: Can't add rules to a firewall chain with firewalld

Post by jlehtone » 2020/04/25 20:50:48

Ok, interfaces eth0, docker0, and br-71b1db558314 do exists, but that is not important.

This is:
PaulJBIs wrote:
2020/04/25 17:31:37

Code: Select all

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DOCKER-ISOLATION  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 DOCKER     all  --  *      br-71b1db558314  0.0.0.0/0            0.0.0.0/0           
    ...
    0     0 DOCKER     all  --  *      docker0  0.0.0.0/0            0.0.0.0/0           
    ...

Chain DOCKER (2 references)
 ...

Chain DOCKER-ISOLATION (1 references)
 ...

Chain DOCKER-USER (0 references)
 ...
1. You did create chain DOCKER-USER. It was not created by docker for you.
2. Nobody uses DOCKER-USER. No packet will ever see rules in that chain.
3. There is chain DOCKER-ISOLATION that is visited before chain DOCKER.

Quick websearch does not find DOCKER-ISOLATION, but does find DOCKER-ISOLATION-STAGE-1 and DOCKER-ISOLATION-STAGE-2.

You could jump to DOCKER-USER in the beginning of FORWARD in order to enable your rules.*
However, the chains inserted by (this version of) docker do not match any documentation.
Do the docker-packages have documentation that would match the actual behaviour?


[edit]
* I doubt that works. If firewalld loads your rules first and docker then prepends its chains on boot, then your DOCKER-USER ends up after DOCKER.

PaulJBIs
Posts: 4
Joined: 2020/04/24 18:00:48

Re: Can't add rules to a firewall chain with firewalld

Post by PaulJBIs » 2020/04/26 21:16:05

Well, you put me in the right track. After reading this, I checked again and it turns out that I wasn't running the latest version of Docker. I just did a "yum install docker" when setting up the server, and it was actually a quite old version. :roll: After I followed the instructions on Docker's page, added their repo and installed the latest version, the firewall works properly.

Post Reply