Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: firewall: add nftables backend #462

Closed
wants to merge 4 commits into from

Conversation

greenpau
Copy link

Resolves: #461

@greenpau greenpau changed the title add nftables firewall backend WIP: add nftables firewall backend Mar 15, 2020
@greenpau greenpau force-pushed the nftables branch 2 times, most recently from f2cecbe to 7a04e16 Compare March 16, 2020 02:59
@greenpau greenpau changed the title WIP: add nftables firewall backend WIP: firewall: add nftables backend Mar 16, 2020
@greenpau
Copy link
Author

greenpau commented Mar 16, 2020

@mars1024 , could you please take a look at this PR? 🙏 It is almost ready (pending adding tests), but I did update README.md.

@mars1024
Copy link
Member

@mars1024 , could you please take a look at this PR? 🙏 It is almost ready (pending adding tests), but I did update README.md.

Of course, and you should add some tests later.

@mars1024
Copy link
Member

BTW, cc firewall plugin author @dcbw

@greenpau greenpau force-pushed the nftables branch 2 times, most recently from e7653d0 to fc12e49 Compare March 17, 2020 01:53
@greenpau
Copy link
Author

@mars1024 , I tried ./test_linux.sh, but it tests all plugins, not just firewall.

@greenpau greenpau force-pushed the nftables branch 2 times, most recently from 756e3fd to e30bde3 Compare March 17, 2020 02:20
@mars1024
Copy link
Member

ginko can also work with go test, please try go test github.com/containernetworking/plugins/plugins/meta/firewall

@mars1024
Copy link
Member

We need more tests @greenpau

@greenpau
Copy link
Author

We need more tests @greenpau

@mars1024 , working on ti. Thank you for the review!

@greenpau
Copy link
Author

How about move these rules into a new chain of filter table? just like iptables backend

@mars1024, after thinking about it a bit, it may require its own chain .. for consistency.

What would the logic behind naming the individual chains? For example, I see IP masquarade chaing names in the following fashion. I guess, what is the logic behind 586108da8523562bc2ca795b ?

table ip nat { # handle 27

        chain POSTROUTING { # handle 3
                ip saddr 192.168.124.145  counter packets 0 bytes 0 jump CNI-586108da8523562bc2ca795b # handle 562

        chain CNI-586108da8523562bc2ca795b { # handle 559
                ip daddr 192.168.124.0/24  counter packets 0 bytes 0 accept # handle 560
                ip daddr != 224.0.0.0/4  counter packets 0 bytes 0 masquerade  # handle 561
        }

@greenpau
Copy link
Author

@mars1024, after thinking about it a bit, it may require its own chain .. for consistency.

@mars1024 , running into an issue implementing it as a chain. how many chain would you create for the below rules?

nft insert rule filter FORWARD position 51 oifname "cni-podman0" ip daddr 192.168.124.0/24 ct state established,related counter packets 0 bytes 0 accept
nft insert rule filter FORWARD position 51 iifname "cni-podman0" ip saddr 192.168.124.0/24 counter packets 0 bytes 0 accept

Do you create a chain for interface? e.g. CNI-FORWARD-PODMAN0? them sub-chain for each IP address?

I am still think it could be proper to do it with a subnet match.

@greenpau
Copy link
Author

Back on this PR.

@greenpau greenpau force-pushed the nftables branch 3 times, most recently from e0dd778 to 1e5820c Compare July 31, 2020 01:35
@greenpau
Copy link
Author

Pivoting from invoking nft via shell to using github.com/google/nftables.

Found decent blog posts on the subject:

@greenpau greenpau force-pushed the nftables branch 4 times, most recently from 64af31c to 88bb21e Compare August 1, 2020 00:52
@dcbw
Copy link
Member

dcbw commented Aug 5, 2020

@erig0 can you review this one too? thanks!

@greenpau
Copy link
Author

greenpau commented Aug 5, 2020

@erig0 can you review this one too? thanks!

@mars1024 , @dcbw , @erig0, it might actually not work due to the fact the containernetworking/plugins using older version of Go. Please see this comment: google/nftables#110 (comment). Would love your input as to how to resolve this.

@dcbw
Copy link
Member

dcbw commented Aug 5, 2020

@greenpau we can certainly bump the required Go version of the CNI plugins repo. Our general policy is Go versions N and N-1, which means we should support Go 1.13 and Go 1.14. If it's possible to support 1.12 that's great, but not required. Anything 1.11 and lower is not supported.

pushed as a PR in #521

@greenpau
Copy link
Author

greenpau commented Aug 5, 2020

we can certainly bump the required Go version of the CNI plugins repo.

@dcbw , that would be great!

@erig0
Copy link

erig0 commented Aug 6, 2020

Pivoting from invoking nft via shell to using github.com/google/nftables.

@greenpau, Another option is to use libnftables. This what nft uses. firewalld also uses the JSON support from libnftables.

```

Prior to the invocation of CNI `firewall` plugin, the `FORWARD` chain in `filter`
table might be configured be as follows:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not guaranteed to exist. It will likely exist on any machine that uses the iptables-nft variant of iptables as it implicitly create this table/chain. I would not assume the table/chain exists.

CNI could use its own table and set of chains and thus avoid many interaction issues with iptables-nft. However, a separate table and chains has its own issue related to netfilter hooks. The tl;dr is nftables allows multiple chains to use the same netfilter hook. A consequence of this is that packets that are accepted are still subject to the rules of other chains hooked into the hook type.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not guaranteed to exist. It will likely exist on any machine that uses the iptables-nft variant of iptables as it implicitly create this table/chain. I would not assume the table/chain exists.

@erig0, I can create a chain. that is I do it when testing changes.

@dcbw , @mars1024 , agreed?

Comment on lines +321 to +337
chain cnins-3-4026550857-dummy0 {
oifname "dummy0" ip daddr 192.168.100.100 ct state established,related counter packets 0 bytes 0 accept
iifname "dummy0" ip saddr 192.168.100.100 counter packets 0 bytes 0 accept
iifname "dummy0" oifname "dummy0" counter packets 0 bytes 0 accept
}
}
table ip6 filter {
chain FORWARD {
type filter hook forward priority filter; policy drop;
jump cnins-3-4026550857-dummy0
}

chain cnins-3-4026550857-dummy0 {
oifname "dummy0" ip6 daddr 2001:db8:100:100::1 ct state established,related counter packets 0 bytes 0 accept
iifname "dummy0" ip6 saddr 2001:db8:100:100::1 counter packets 0 bytes 0 accept
iifname "dummy0" oifname "dummy0" counter packets 0 bytes 0 accept
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally these would be combined into one chain in a table of family inet. I don't think there is value in splitting them up. It can probably avoid some duplicate rules.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally these would be combined into one chain in a table of family inet. I don't think there is value in splitting them up. It can probably avoid some duplicate rules.

@erig0, please see @mars1024 comment that he wanted a jump.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think there is value in splitting them up. It can probably avoid some duplicate rules.

@erig0, it has a value in a sense that it is easier to delete the rule when you have a jump like this. It would be very hard to parse each rule.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get the jump to a dedicated chain. That 100% makes sense. I was saying I don't think you need to split the "ip" and "ip6" families. You could use "inet" which covers both IPv4 and IPv6.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get the jump to a dedicated chain. That 100% makes sense. I was saying I don't think you need to split the "ip" and "ip6" families. You could use "inet" which covers both IPv4 and IPv6.

@erig0, that I could do. 👍 It makes sense because IPv4/6 are all a part of the same construct.

@greenpau
Copy link
Author

greenpau commented Aug 6, 2020

From failed tests:

  Unexpected error:
      <*errors.errorString | 0xc000085fa0>: {
          s: "nftBackend.Add() error: failed parsing netfilter tables: nftables table filter not found",
      }
      nftBackend.Add() error: failed parsing netfilter tables: nftables table filter not found
  occurred

Now most of the tests pass. Noticed the issue with table filter not found. Per comment by @erig0 , need to add the chain creation.

@greenpau
Copy link
Author

greenpau commented Aug 7, 2020

just noticed an issue with chanName. I forgot to add ContainerID in the mix.

@greenpau
Copy link
Author

another issue is with the interface name ... I take the interface name of the container. It should be the interface name of the bridge ... the very first interface of in the list.

@greenpau greenpau changed the title firewall: add nftables backend WIP: firewall: add nftables backend Aug 10, 2020
@greenpau
Copy link
Author

Added working version of nftables plugin in https://github.com/greenpau/cni-plugins#cni-nftables-firewall. Still testing it.

@PavelSosin-320
Copy link

Why firewall configuration is needed when Podman runs inside a VM container, like WSL2 ? A firewall is always supplied by the Host node. The communication between the Podman network and interface Eth0 provided dynamically by the Virtual switch doesn't need any filtering. In the overlay network, the entire local network can be protected by the router if it runs OpenWRT or Free Balena.

@06kellyjac
Copy link

Why firewall configuration is needed when Podman runs inside a VM container, like WSL2 ? A firewall is always supplied by the Host node. The communication between the Podman network and interface Eth0 provided dynamically by the Virtual switch doesn't need any filtering. In the overlay network, the entire local network can be protected by the router if it runs OpenWRT or Free Balena.
@PavelSosin-320

In this context the firewall plugin is how networking is set up for the containers. This is separate to what you refer to as the "overlay network".
You can use a "fully featured" firewall like firewalld or, as most people use containers, it'll actually be using iptables (a packet filter).
This PR is to add nftables as an option (a different packet filter).

You can read up on the CNI firewall plugin here: https://github.com/containernetworking/plugins/blob/master/plugins/meta/firewall/README.md

You can already use podman with iptables in WSL2 without this PR, as long as your linux distro still uses iptables.


If I got anything wrong here let me know

@dcbw
Copy link
Member

dcbw commented Sep 10, 2020

another issue is with the interface name ... I take the interface name of the container. It should be the interface name of the bridge ... the very first interface of in the list.

Note that this won't always be the first interface... we've struggled with this for other plugins (eg bandwidth) too, and don't have a great answer yet because some plugins might not have a host-side network interface, like VMs that use tap. But in any case, take a look at what the bandwidth plugin does; I think it takes the first non-sandbox interface in the list. If you just look for the first interface, it may be the container interface, so you have to look at the "Sandbox" key.

@greenpau
Copy link
Author

Note that this won't always be the first interface...

@dcbw , I reworked the plugin completely ... please see https://github.com/greenpau/cni-plugins/tree/main/pkg/firewall

I was thinking of linking from here to https://github.com/greenpau/cni-plugins/blob/6b7a838e15f159e8695df59b4f4f722ca3f49118/pkg/firewall/cmd.go#L12. Any objections?

Also, on a separate note, I found out that portmap will not work on RHEL 7, just RHEL 8.

@cjschroeder
Copy link

Has there been any movement on this front? Nftables support (not firewalld) is a necessary need for those using the nftables service on Fedora, for instance.

@SilverBut
Copy link
Contributor

Not sure what's going on there since its now closed. @greenpau Any idea?

@greenpau
Copy link
Author

Not sure what's going on there since its now closed.

@SilverBut , closed it since I implemented it here: https://github.com/greenpau/cni-plugins

@3nprob
Copy link

3nprob commented Jan 22, 2022

@dcbw @squeed @mars1024 @erig0 Considering that the PR author abandoned getting this merged here and are content with their own fork - what's missing for you (apart from rebasing) to get this PR to a mergable state?

nftables support for firewall is a pretty important feature, and getting moreso as more and more migrate to nft.

@rtgiskard
Copy link

I'm using nftables with customized rules, and do not want any part of the system to alter the rules itself, so that all the firewall rules can be managed in one place and easy to check.

Is it possible to have an option to disable iptables just like docker?

@mccv1r0
Copy link
Member

mccv1r0 commented Jul 26, 2022

@rtgiskard

Is it possible to have an option to disable iptables just like docker?

I suggest you create a new issue.

@rtgiskard
Copy link

@rtgiskard

Is it possible to have an option to disable iptables just like docker?

I suggest you create a new issue.

thank you, here is the new issue

@unknowndevQwQ
Copy link

Not sure what's going on there since its now closed.

@SilverBut , closed it since I implemented it here: https://github.com/greenpau/cni-plugins

@greenpau What's stopping you from merging this beautiful new feature into Upstream?

@3nprob
Copy link

3nprob commented Mar 17, 2023

@unknowndevQwQ the same thing stopping you, presumably :p
It'd have to get merged by a maintainer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ERROR: table `nat' is incompatible, use 'nft' tool.