containers/netavark

Firewalld backend forward port even for non-local-targeting traffic

karuboniru opened this issue · 2 comments

Reproduce of the problem:
Start a container with port forwarding using firewalld backend.

$ sudo NETAVARK_FW=firewalld podman run -p 12345:12345 --rm -it alpine
 ...
# ip a 
 ...
 ... 10.88.0.2/16 ...
 ...
# python3 -m http.server 12345
 ...

Firewalld state:

$ sudo firewall-cmd --info-policy=netavark_portfwd
netavark_portfwd (active)
  priority: -1
  target: CONTINUE
  ingress-zones: ANY
  egress-zones: ANY
  services: 
  ports: 
  protocols: 
  masquerade: no
  forward-ports: 
	port=12345:proto=tcp:toport=12345:toaddr=10.88.0.2
  source-ports: 
  icmp-blocks: 
  rich rules: 

In another container

$ sudo NETAVARK_FW=firewalld podman run --rm -it alpine
 ...
# curl 10.88.0.2:12345
 ... (reply from python, listing contents in /)
# curl 10.88.0.12:12345
 curl: (7) Failed to connect to 10.88.0.12 port 12345 after 3108 ms: Couldn't connect to server
# curl 1.1.1.1:12345
 ... (reply from python, listing contents in /)

It is unexpected to me that 1.1.1.1:12345 would be successful, as traffic to 1.1.1.1:12345 should be masqueraded to real 1.1.1.1 and result in Failed to connect as cloudflared should not have a python http.server running in /.


Reason:
Generated nft rule from firewalld:

	chain nat_PREROUTING {
		type nat hook prerouting priority dstnat + 10; policy accept;
		jump nat_PREROUTING_POLICIES
	}
	chain nat_PREROUTING_POLICIES {
...
		jump nat_PRE_policy_netavark_portfwd
...
	}
	chain nat_PRE_policy_netavark_portfwd {
...
		jump nat_PRE_policy_netavark_portfwd_allow
...
	}
	chain nat_PRE_policy_netavark_portfwd_allow {
		meta nfproto ipv4 tcp dport 12345 dnat ip to 10.88.0.2:12345
	}

This makes the dnat rule apply to every traffic that hit prerouting chain without checking fib information.

Consider the container is running with -p 443:443 and the machine running the container is a router, every traffic to anyip:443 would be forwarded to the container, which is bad. (This is the exact reason why #881 exist as I wanted to limit the address forwarded from, which did not work since the issue) I thought that forwarding even for non-local-targeting traffic is somewhat designed but after swiched back to iptables backend I realized that this might be a bug.


Behavior when iptables backend is used (rules are transleted by iptables-nft)

...
		fib daddr type local counter packets 50672 bytes 4178234 jump NETAVARK-HOSTPORT-DNAT
...

we have the fib daddr type local check here.


This might be hard to fix I guess, as I can't think of a way to match fib in firewalld rules for now, maybe some cooperation with firewalld is needed.

mheon commented

Definitely a firewalld bug. I'm working through some bugs with the firewalld team as part of the process of getting #885 merged but have not noticed this one yet - I'll add it to the list.

Until #885 merges (which will be after the bugs are addressed enough that our tests start passing), I do not recommend using the firewalld driver.

Luap99 commented

it was mentioned here: #859
Looks like I forgot to ping you there.