Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions pkg/ip/ipmasq_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,18 @@ import (
// implementation will be used.
func SetupIPMasqForNetworks(backend *string, ipns []*net.IPNet, network, ifname, containerID string) error {
if backend == nil {
// Prefer iptables, unless only nftables is available
// Prefer iptables, unless only nftables is available. FIXME: flip this default at some point.
defaultBackend := "iptables"
if !utils.SupportsIPTables() && utils.SupportsNFTables() {
supportsIPT := utils.SupportsIPTables()
supportsNFT := utils.SupportsNFTables()
if !supportsIPT && supportsNFT {
defaultBackend = "nftables"
} else if !supportsIPT && !supportsNFT {
// Both full checks failed (likely missing CAP_NET_ADMIN at detection
// time). Fall back to binary presence as tiebreaker.
if !utils.IPTablesBinaryAvailable() && utils.NFTablesBinaryAvailable() {
defaultBackend = "nftables"
}
}
backend = &defaultBackend
}
Expand Down
16 changes: 16 additions & 0 deletions pkg/utils/netfilter.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
package utils

import (
"os/exec"

"github.com/coreos/go-iptables/iptables"
"sigs.k8s.io/knftables"
)
Expand All @@ -34,6 +36,20 @@ func SupportsIPTables() bool {
return err == nil
}

// IPTablesBinaryAvailable tests whether the iptables binary is present in PATH.
// Unlike SupportsIPTables, this does not require CAP_NET_ADMIN.
func IPTablesBinaryAvailable() bool {
_, err := exec.LookPath("iptables")
return err == nil
}

// NFTablesBinaryAvailable tests whether the nft binary is present in PATH.
// Unlike SupportsNFTables, this does not require CAP_NET_ADMIN.
func NFTablesBinaryAvailable() bool {
_, err := exec.LookPath("nft")
return err == nil
}

// SupportsNFTables tests whether the system supports using netfilter via the nftables API
// (ie, not via "iptables-nft"). (Note that this returns true if it is *possible* to use
// nftables; it does not test whether any other components on the system are *actually*
Expand Down
15 changes: 15 additions & 0 deletions pkg/utils/netfilter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,20 @@ var _ = Describe("netfilter support", func() {
It("reports that nftables is not supported", func() {
Expect(SupportsNFTables()).To(BeFalse(), "found nftables outside of PATH??")
})
It("reports that iptables binary is not available", func() {
Expect(IPTablesBinaryAvailable()).To(BeFalse(), "found iptables outside of PATH??")
})
It("reports that nft binary is not available", func() {
Expect(NFTablesBinaryAvailable()).To(BeFalse(), "found nft outside of PATH??")
})
})

When("binaries are available", func() {
It("reports that iptables binary is available", func() {
Expect(IPTablesBinaryAvailable()).To(BeTrue(), "This test should only fail if iptables is not available, but the test suite as a whole requires it to be available.")
})
It("reports that nft binary is available", func() {
Expect(NFTablesBinaryAvailable()).To(BeTrue(), "This test should only fail if nft is not available, but the test suite as a whole requires it to be available.")
})
})
})
15 changes: 13 additions & 2 deletions plugins/meta/portmap/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -320,10 +320,21 @@ func ensureBackend(conf *PortMapConf) error {
// If backend wasn't requested explicitly, default to iptables, unless it is not
// available (and nftables is). FIXME: flip this default at some point.
if conf.Backend == nil {
if !utils.SupportsIPTables() && utils.SupportsNFTables() {
supportsIPT := utils.SupportsIPTables()
supportsNFT := utils.SupportsNFTables()
switch {
case !supportsIPT && supportsNFT:
conf.Backend = &nftablesBackend
} else {
case supportsIPT || supportsNFT:
conf.Backend = &iptablesBackend
default:
// Both full checks failed (likely missing CAP_NET_ADMIN at detection
// time). Fall back to binary presence as tiebreaker.
if !utils.IPTablesBinaryAvailable() && utils.NFTablesBinaryAvailable() {
conf.Backend = &nftablesBackend
} else {
conf.Backend = &iptablesBackend
}
}
}

Expand Down
Loading