
We can't use dnat from the input hook, depending on nftables (and kernel ?) version we get "Error: Could not process rule: Operation not supported" iptables backend also uses prerouting. Also 'ip6 protocol tcp' is invalid, so rework / simplify the rules Fixes 01a94e17c77e6ff8e5019e15c42d8d92cf87194f Signed-off-by: Etienne Champetier <e.champetier@ateme.com>
135 lines
5.9 KiB
Go
135 lines
5.9 KiB
Go
// Copyright 2023 CNI authors
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
. "github.com/onsi/ginkgo/v2"
|
|
. "github.com/onsi/gomega"
|
|
"sigs.k8s.io/knftables"
|
|
|
|
"github.com/containernetworking/cni/pkg/types"
|
|
)
|
|
|
|
var _ = Describe("portmapping configuration (nftables)", func() {
|
|
containerID := "icee6giejonei6so"
|
|
|
|
for _, ver := range []string{"0.3.0", "0.3.1", "0.4.0", "1.0.0"} {
|
|
// Redefine ver inside for scope so real value is picked up by each dynamically defined It()
|
|
// See Gingkgo's "Patterns for dynamically generating tests" documentation.
|
|
ver := ver
|
|
|
|
Describe("nftables rules", func() {
|
|
var pmNFT *portMapperNFTables
|
|
var ipv4Fake, ipv6Fake *knftables.Fake
|
|
BeforeEach(func() {
|
|
ipv4Fake = knftables.NewFake(knftables.IPv4Family, tableName)
|
|
ipv6Fake = knftables.NewFake(knftables.IPv6Family, tableName)
|
|
pmNFT = &portMapperNFTables{
|
|
ipv4: ipv4Fake,
|
|
ipv6: ipv6Fake,
|
|
}
|
|
})
|
|
|
|
It(fmt.Sprintf("[%s] generates correct rules on ADD", ver), func() {
|
|
configBytes := []byte(fmt.Sprintf(`{
|
|
"name": "test",
|
|
"type": "portmap",
|
|
"cniVersion": "%s",
|
|
"backend": "nftables",
|
|
"runtimeConfig": {
|
|
"portMappings": [
|
|
{ "hostPort": 8080, "containerPort": 80, "protocol": "tcp"},
|
|
{ "hostPort": 8081, "containerPort": 80, "protocol": "tcp"},
|
|
{ "hostPort": 8080, "containerPort": 81, "protocol": "udp"},
|
|
{ "hostPort": 8082, "containerPort": 82, "protocol": "udp"},
|
|
{ "hostPort": 8083, "containerPort": 83, "protocol": "tcp", "hostIP": "192.168.0.2"},
|
|
{ "hostPort": 8084, "containerPort": 84, "protocol": "tcp", "hostIP": "0.0.0.0"},
|
|
{ "hostPort": 8085, "containerPort": 85, "protocol": "tcp", "hostIP": "2001:db8:a::1"},
|
|
{ "hostPort": 8086, "containerPort": 86, "protocol": "tcp", "hostIP": "::"}
|
|
]
|
|
},
|
|
"snat": true,
|
|
"conditionsV4": ["a", "b"],
|
|
"conditionsV6": ["c", "d"]
|
|
}`, ver))
|
|
|
|
conf, _, err := parseConfig(configBytes, "foo")
|
|
Expect(err).NotTo(HaveOccurred())
|
|
conf.ContainerID = containerID
|
|
|
|
containerNet, err := types.ParseCIDR("10.0.0.2/24")
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
err = pmNFT.forwardPorts(conf, *containerNet)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
expectedRules := strings.TrimSpace(`
|
|
add table ip cni_hostport { comment "CNI portmap plugin" ; }
|
|
add chain ip cni_hostport hostip_hostports
|
|
add chain ip cni_hostport hostports
|
|
add chain ip cni_hostport masquerading { type nat hook postrouting priority 100 ; }
|
|
add chain ip cni_hostport output { type nat hook output priority -100 ; }
|
|
add chain ip cni_hostport prerouting { type nat hook prerouting priority -100 ; }
|
|
add rule ip cni_hostport hostip_hostports ip daddr 192.168.0.2 tcp dport 8083 dnat to 10.0.0.2:83 comment "icee6giejonei6so"
|
|
add rule ip cni_hostport hostports tcp dport 8080 dnat to 10.0.0.2:80 comment "icee6giejonei6so"
|
|
add rule ip cni_hostport hostports tcp dport 8081 dnat to 10.0.0.2:80 comment "icee6giejonei6so"
|
|
add rule ip cni_hostport hostports udp dport 8080 dnat to 10.0.0.2:81 comment "icee6giejonei6so"
|
|
add rule ip cni_hostport hostports udp dport 8082 dnat to 10.0.0.2:82 comment "icee6giejonei6so"
|
|
add rule ip cni_hostport hostports tcp dport 8084 dnat to 10.0.0.2:84 comment "icee6giejonei6so"
|
|
add rule ip cni_hostport masquerading ip saddr 10.0.0.2 ip daddr 10.0.0.2 masquerade comment "icee6giejonei6so"
|
|
add rule ip cni_hostport masquerading ip saddr 127.0.0.1 ip daddr 10.0.0.2 masquerade comment "icee6giejonei6so"
|
|
add rule ip cni_hostport output a b jump hostip_hostports
|
|
add rule ip cni_hostport output a b fib daddr type local jump hostports
|
|
add rule ip cni_hostport prerouting a b jump hostip_hostports
|
|
add rule ip cni_hostport prerouting a b jump hostports
|
|
`)
|
|
actualRules := strings.TrimSpace(ipv4Fake.Dump())
|
|
Expect(actualRules).To(Equal(expectedRules))
|
|
|
|
// Disable snat, generate IPv6 rules
|
|
*conf.SNAT = false
|
|
containerNet, err = types.ParseCIDR("2001:db8::2/64")
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
err = pmNFT.forwardPorts(conf, *containerNet)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
expectedRules = strings.TrimSpace(`
|
|
add table ip6 cni_hostport { comment "CNI portmap plugin" ; }
|
|
add chain ip6 cni_hostport hostip_hostports
|
|
add chain ip6 cni_hostport hostports
|
|
add chain ip6 cni_hostport output { type nat hook output priority -100 ; }
|
|
add chain ip6 cni_hostport prerouting { type nat hook prerouting priority -100 ; }
|
|
add rule ip6 cni_hostport hostip_hostports ip6 daddr 2001:db8:a::1 tcp dport 8085 dnat to [2001:db8::2]:85 comment "icee6giejonei6so"
|
|
add rule ip6 cni_hostport hostports tcp dport 8080 dnat to [2001:db8::2]:80 comment "icee6giejonei6so"
|
|
add rule ip6 cni_hostport hostports tcp dport 8081 dnat to [2001:db8::2]:80 comment "icee6giejonei6so"
|
|
add rule ip6 cni_hostport hostports udp dport 8080 dnat to [2001:db8::2]:81 comment "icee6giejonei6so"
|
|
add rule ip6 cni_hostport hostports udp dport 8082 dnat to [2001:db8::2]:82 comment "icee6giejonei6so"
|
|
add rule ip6 cni_hostport hostports tcp dport 8086 dnat to [2001:db8::2]:86 comment "icee6giejonei6so"
|
|
add rule ip6 cni_hostport output c d jump hostip_hostports
|
|
add rule ip6 cni_hostport output c d fib daddr type local jump hostports
|
|
add rule ip6 cni_hostport prerouting c d jump hostip_hostports
|
|
add rule ip6 cni_hostport prerouting c d jump hostports
|
|
`)
|
|
actualRules = strings.TrimSpace(ipv6Fake.Dump())
|
|
Expect(actualRules).To(Equal(expectedRules))
|
|
})
|
|
})
|
|
}
|
|
})
|