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.
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.