Skip to content

Commit

Permalink
add nftables firewall backend
Browse files Browse the repository at this point in the history
  • Loading branch information
greenpau committed Mar 15, 2020
1 parent 47a9fd8 commit a19d16d
Show file tree
Hide file tree
Showing 435 changed files with 23,047 additions and 9,347 deletions.
11 changes: 6 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ require (
github.com/d2g/dhcp4client v1.0.0
github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5
github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4 // indirect
github.com/davecgh/go-spew v1.1.0
github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c
github.com/golang/protobuf v1.3.1 // indirect
github.com/google/nftables v0.0.0-20200309074347-64aca752d17d
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56
github.com/juju/errors v0.0.0-20180806074554-22422dad46e1
github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8 // indirect
Expand All @@ -25,16 +27,15 @@ require (
github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b
github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8
github.com/sirupsen/logrus v1.0.6 // indirect
github.com/sirupsen/logrus v1.0.6
github.com/stretchr/testify v1.3.0 // indirect
github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf
github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc // indirect
golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941 // indirect
golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1 // indirect
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f
golang.org/x/sys v0.0.0-20191029155521-f43be2a4598c
gopkg.in/airbrake/gobrake.v2 v2.0.9 // indirect
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 // indirect
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce // indirect
gopkg.in/yaml.v2 v2.2.2 // indirect
)

replace github.com/coreos/go-iptables => ../../coreos/go-iptables
23 changes: 23 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,31 @@ github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c h1:RBUpb2b14UnmRHNd2uH
github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/nftables v0.0.0-20200309074347-64aca752d17d h1:iF80R3HwzujRiWLD7NMIR1bWUFNN9UgbOMjl8xhrf5k=
github.com/google/nftables v0.0.0-20200309074347-64aca752d17d/go.mod h1:cfspEyr/Ap+JDIITA+N9a0ernqG0qZ4W1aqMRgDZa1g=
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56 h1:742eGXur0715JMq73aD95/FU0XpVKXqNuTnEfXsLOYQ=
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw=
github.com/juju/errors v0.0.0-20180806074554-22422dad46e1 h1:wnhMXidtb70kDZCeLt/EfsVtkXS5c8zLnE9y/6DIRAU=
github.com/juju/errors v0.0.0-20180806074554-22422dad46e1/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q=
github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8 h1:UUHMLvzt/31azWTN/ifGWef4WUqvXk0iRqdhdy/2uzI=
github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U=
github.com/juju/testing v0.0.0-20190613124551-e81189438503 h1:ZUgTbk8oHgP0jpMieifGC9Lv47mHn8Pb3mFX3/Ew4iY=
github.com/juju/testing v0.0.0-20190613124551-e81189438503/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA=
github.com/koneu/natend v0.0.0-20150829182554-ec0926ea948d h1:MFX8DxRnKMY/2M3H61iSsVbo/n3h0MWGmWNN1UViOU0=
github.com/koneu/natend v0.0.0-20150829182554-ec0926ea948d/go.mod h1:QHb4k4cr1fQikUahfcRVPcEXiUgFsdIstGqlurL0XL4=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mattn/go-shellwords v1.0.3 h1:K/VxK7SZ+cvuPgFSLKi5QPI9Vr/ipOf4C1gN+ntueUk=
github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA=
github.com/mdlayher/netlink v0.0.0-20191009155606-de872b0d824b h1:W3er9pI7mt2gOqOWzwvx20iJ8Akiqz1mUMTxU6wdvl8=
github.com/mdlayher/netlink v0.0.0-20191009155606-de872b0d824b/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M=
github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b h1:Ey6yH0acn50T/v6CB75bGP4EMJqnv9WvnjN7oZaj+xE=
github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a h1:KfNOeFvoAssuZLT7IntKZElKwi/5LRuxY71k+t6rfaM=
Expand All @@ -64,10 +74,23 @@ github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc h1:R83G5ikgLMxrB
github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI=
golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941 h1:qBTHLajHecfu+xzRI9PqVDcqx7SdHj9d4B+EzSn3tAc=
golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1 h1:Y/KGZSOdz/2r0WJ9Mkmz6NJBusp0kiNx1Cn82lzJQ6w=
golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191028085509-fe3aa8a45271 h1:N66aaryRB3Ax92gH0v3hp1QYZ3zWWCCUR/j8Ifh45Ss=
golang.org/x/net v0.0.0-20191028085509-fe3aa8a45271/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f h1:25KHgbfyiSm6vwQLbM3zZIe1v9p/3ea4Rz+nnM5K/i4=
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191029155521-f43be2a4598c h1:S/FtSvpNLtFBgjTqcKsRpsa6aVsI6iztaz1bQd9BJwE=
golang.org/x/sys v0.0.0-20191029155521-f43be2a4598c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/airbrake/gobrake.v2 v2.0.9 h1:7z2uVWwn7oVeeugY1DtlPAy5H+KYgB1KeKTnqjNatLo=
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Expand Down
5 changes: 5 additions & 0 deletions pkg/ip/ipmasq_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,18 @@ import (
"net"

"github.com/coreos/go-iptables/iptables"

"github.com/davecgh/go-spew/spew"
"github.com/sirupsen/logrus"
)

// SetupIPMasq installs iptables rules to masquerade traffic
// coming from ip of ipn and going outside of ipn
func SetupIPMasq(ipn *net.IPNet, chain string, comment string) error {
isV6 := ipn.IP.To4() == nil

logrus.Errorf("SetupIPMasq() chain: %s", spew.Sdump(chain))

var ipt *iptables.IPTables
var err error
var multicastNet string
Expand Down
11 changes: 11 additions & 0 deletions pkg/utils/iptables.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,21 @@ import (
"fmt"

"github.com/coreos/go-iptables/iptables"

"github.com/davecgh/go-spew/spew"
"github.com/sirupsen/logrus"
)

const statusChainExists = 1

// EnsureChain idempotently creates the iptables chain. It does not
// return an error if the chain already exists.
func EnsureChain(ipt *iptables.IPTables, table, chain string) error {

logrus.Errorf("EnsureChain() ipt: %s", spew.Sdump(ipt))
logrus.Errorf("EnsureChain() table: %s", spew.Sdump(table))
logrus.Errorf("EnsureChain() chain: %s", spew.Sdump(chain))

if ipt == nil {
return errors.New("failed to ensure iptable chain: IPTables was nil")
}
Expand Down Expand Up @@ -106,6 +114,9 @@ func DeleteChain(ipt *iptables.IPTables, table, chain string) error {
// ClearChain idempotently clear the iptables rules in the specified table/chain.
// If the chain does not exist, a new one will be created
func ClearChain(ipt *iptables.IPTables, table, chain string) error {
logrus.Errorf("ClearChain() ipt: %s", spew.Sdump(ipt))
logrus.Errorf("ClearChain() table: %s", spew.Sdump(table))
logrus.Errorf("ClearChain() chain: %s", spew.Sdump(chain))
if ipt == nil {
return errors.New("failed to ensure iptable chain: IPTables was nil")
}
Expand Down
6 changes: 6 additions & 0 deletions plugins/meta/firewall/firewall.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import (
"github.com/containernetworking/cni/pkg/version"

bv "github.com/containernetworking/plugins/pkg/utils/buildversion"
//"github.com/davecgh/go-spew/spew"
//"github.com/sirupsen/logrus"
)

// FirewallNetConf represents the firewall configuration.
Expand Down Expand Up @@ -97,6 +99,8 @@ func getBackend(conf *FirewallNetConf) (FirewallBackend, error) {
switch conf.Backend {
case "iptables":
return newIptablesBackend(conf)
case "nftables":
return newNftablesBackend(conf)
case "firewalld":
return newFirewalldBackend(conf)
}
Expand All @@ -120,6 +124,8 @@ func cmdAdd(args *skel.CmdArgs) error {
return fmt.Errorf("missing prevResult from earlier plugin")
}

//logrus.Errorf("cmdAdd() conf: %s", spew.Sdump(conf))

backend, err := getBackend(conf)
if err != nil {
return err
Expand Down
8 changes: 8 additions & 0 deletions plugins/meta/firewall/iptables.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ import (
"github.com/containernetworking/cni/pkg/types/current"
"github.com/containernetworking/plugins/pkg/utils"
"github.com/coreos/go-iptables/iptables"

"github.com/davecgh/go-spew/spew"
"github.com/sirupsen/logrus"
)

func getPrivChainRules(ip string) [][]string {
Expand Down Expand Up @@ -59,6 +62,9 @@ func (ib *iptablesBackend) setupChains(ipt *iptables.IPTables) error {
privRule := generateFilterRule(ib.privChainName)
adminRule := generateFilterRule(ib.adminChainName)

logrus.Errorf("setupChains()")
logrus.Errorf("setupChains() ib: %s", spew.Sdump(ib))

// Ensure our private chains exist
if err := utils.EnsureChain(ipt, "filter", ib.privChainName); err != nil {
return err
Expand Down Expand Up @@ -146,6 +152,8 @@ func (ib *iptablesBackend) checkRules(conf *FirewallNetConf, result *current.Res
return nil
}

logrus.Errorf("checkRules()")

// Ensure our private chains exist
if err := utils.EnsureChain(ipt, "filter", ib.privChainName); err != nil {
return err
Expand Down
203 changes: 203 additions & 0 deletions plugins/meta/firewall/nftables.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
// Copyright 2018 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"
"github.com/containernetworking/cni/pkg/types/current"
"github.com/davecgh/go-spew/spew"
"github.com/google/nftables"
"github.com/sirupsen/logrus"
"net"
)

// Only used for testcases to override the D-Bus connection
var testNftConn *nftables.Conn

type nftBackend struct {
conn *nftables.Conn
tables []*nftables.Table
chains []*nftables.Chain
targetTable *nftables.Table
targetChain *nftables.Chain
targetHandle uint64
targetInterface string
targetNetwork *net.IPNet
}

// nftBackend implements the FirewallBackend interface
var _ FirewallBackend = &nftBackend{}

func getNftConn() (*nftables.Conn, error) {
if testNftConn != nil {
return testNftConn, nil
}
return &nftables.Conn{}, nil
}

func newNftablesBackend(conf *FirewallNetConf) (FirewallBackend, error) {
conn, err := getNftConn()
if err != nil {
return nil, err
}

backend := &nftBackend{
conn: conn,
}
return backend, nil
}

func (nb *nftBackend) isFilterTableExists() error {
isTableFound := false
tables, err := nb.conn.ListTables()
if err != nil {
return fmt.Errorf("isFilterTableExists(): %s", err)
}
for _, table := range tables {
if table.Name == "filter" && table.Family == 2 {
nb.targetTable = table
isTableFound = true
break
}
}
if !isTableFound {
return fmt.Errorf("isFilterTableExists(): the IPv4 filter table does not exist")
}
nb.tables = tables
return nil
}

func (nb *nftBackend) isForwardChainExists() error {
isChainFound := false
chains, err := nb.conn.ListChains()
if err != nil {
return fmt.Errorf("isForwardChainExists(): %s", err)
}
for _, chain := range chains {
if chain.Name != "FORWARD" {
continue
}
if chain.Type != "filter" {
continue
}
if chain.Table.Name != "filter" {
continue
}
if chain.Table.Family != 2 {
continue
}
nb.targetChain = chain
isChainFound = true
break
}
if !isChainFound {
return fmt.Errorf("isForwardChainExists(): the FORWARD chain in IPv4 filter table does not exist")
}
nb.chains = chains
return nil
}

func (nb *nftBackend) isValidInput(result *current.Result) error {
if len(result.Interfaces) == 0 {
return fmt.Errorf("the data passed to firewall plugin did not contain network interfaces")
}

if result.Interfaces[0].Name == "" {
return fmt.Errorf("the data passed to firewall plugin has no bridge name, e.g. cnibr0")
}

nb.targetInterface = result.Interfaces[0].Name

logrus.Errorf("nftBackend.Add() target interface: %s", spew.Sdump(nb.targetInterface))

if len(result.IPs) == 0 {
return fmt.Errorf("the data passed to firewall plugin has no IP addresses")
}

if len(result.IPs) != 1 {
return fmt.Errorf("the data passed to firewall plugin has more than one IP address")
}

addr := result.IPs[0].Address

if addr.String() == "" {
return fmt.Errorf("the data passed to firewall plugin has empty IP address")
}

if addr.IP.To4() == nil {
return fmt.Errorf("the data passed to firewall plugin has non-IPv4 address")
}

_, netAddr, err := net.ParseCIDR(addr.String())
if err != nil {
return fmt.Errorf("the data passed to firewall plugin has invalid IPv4 address")
}

nb.targetNetwork = netAddr

return nil
}

func (nb *nftBackend) Add(conf *FirewallNetConf, result *current.Result) error {
if err := nb.isValidInput(result); err != nil {
return fmt.Errorf("nftBackend.Add() %s", err)
}

if err := nb.isFilterTableExists(); err != nil {
return fmt.Errorf("nftBackend.Add() %s", err)
}

if err := nb.isForwardChainExists(); err != nil {
return fmt.Errorf("nftBackend.Add() %s", err)
}

rules, err := nb.conn.GetRule(nb.targetTable, nb.targetChain)
if err != nil {
return fmt.Errorf("nftBackend.Add() GetRule failed: %s", err)
}

return fmt.Errorf("nftBackend.Add is not supported")

if len(rules) > 0 {
nb.targetHandle = rules[0].Handle
for _, rule := range rules {
logrus.Errorf("nftBackend.Add() rule: %s", spew.Sdump(rule.Handle))
//logrus.Errorf("nftBackend.Add() rule: %s", spew.Sdump(rule))
}
}

if nb.targetHandle == 0 {
// TODO: add rules as opposed to insert
} else {
// TODO: insert the rules
}

return fmt.Errorf("nftBackend.Add is not supported")
//return nil
}

func (nb *nftBackend) Del(conf *FirewallNetConf, result *current.Result) error {
logrus.Errorf("nftBackend.Del() conf: %s", spew.Sdump(conf))
logrus.Errorf("nftBackend.Del() result: %s", spew.Sdump(result))
// TODO
return nil
}

func (nb *nftBackend) Check(conf *FirewallNetConf, result *current.Result) error {
// TODO
logrus.Errorf("nftBackend.Check() conf: %s", spew.Sdump(conf))
logrus.Errorf("nftBackend.Check() result: %s", spew.Sdump(result))
return nil
}
Loading

0 comments on commit a19d16d

Please sign in to comment.