containers / containers/netavark
Firewalld backend forward port even for non-local-targeting traffic
- Dominant language
- Rust
- Stars
- 794
- Forks
- 161
- Avg merge
- 8d 17h
- Merged PRs (30d)
- 3
Description
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 https://github.com/containers/netavark/issues/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.
Contributor guide
Assessment
This issue has not been assessed yet.