Skip to content

Commit f1f128e

Browse files
authored
Merge pull request containernetworking#639 from EdDev/bridge-macspoofchk
bridge: Add macspoofchk support
2 parents 2a9114d + 081ed44 commit f1f128e

File tree

24 files changed

+2132
-14
lines changed

24 files changed

+2132
-14
lines changed

.github/workflows/test.yaml

+3
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ jobs:
3535
run: |
3636
sudo apt-get update
3737
sudo apt-get install linux-modules-extra-$(uname -r)
38+
- name: Install nftables
39+
run: sudo apt-get install nftables
40+
3841
- name: setup go
3942
uses: actions/setup-go@v2
4043
with:

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ require (
1515
github.com/godbus/dbus/v5 v5.0.4
1616
github.com/j-keck/arping v1.0.2
1717
github.com/mattn/go-shellwords v1.0.12
18+
github.com/networkplumbing/go-nft v0.2.0
1819
github.com/onsi/ginkgo v1.16.4
1920
github.com/onsi/gomega v1.15.0
2021
github.com/safchain/ethtool v0.0.0-20210803160452-9aa261dae9b1

go.sum

+11-1
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m
438438
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
439439
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
440440
github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
441+
github.com/networkplumbing/go-nft v0.2.0 h1:eKapmyVUt/3VGfhYaDos5yeprm+LPt881UeksmKKZHY=
442+
github.com/networkplumbing/go-nft v0.2.0/go.mod h1:HnnM+tYvlGAsMU7yoYwXEVLLiDW9gdMmb5HoGcwpuQs=
441443
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
442444
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
443445
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
@@ -567,8 +569,9 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
567569
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
568570
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
569571
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
570-
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
571572
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
573+
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
574+
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
572575
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
573576
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
574577
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
@@ -599,6 +602,7 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q
599602
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
600603
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
601604
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
605+
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
602606
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
603607
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
604608
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
@@ -659,6 +663,7 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
659663
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
660664
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
661665
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
666+
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
662667
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
663668
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
664669
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -694,6 +699,7 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
694699
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
695700
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
696701
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
702+
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
697703
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0=
698704
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
699705
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -710,6 +716,7 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ
710716
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
711717
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
712718
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
719+
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
713720
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
714721
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
715722
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -771,7 +778,9 @@ golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7w
771778
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
772779
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
773780
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
781+
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
774782
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
783+
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
775784
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e h1:WUoyKPm6nCo1BnNUvPGnFG3T5DUVem42yDJZZ4CNxMA=
776785
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
777786
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
@@ -826,6 +835,7 @@ golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjs
826835
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
827836
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
828837
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
838+
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
829839
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
830840
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
831841
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

pkg/link/link_suite_test.go

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright 2021 CNI authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package link_test
16+
17+
import (
18+
"testing"
19+
20+
. "github.com/onsi/ginkgo"
21+
. "github.com/onsi/gomega"
22+
)
23+
24+
func TestIp(t *testing.T) {
25+
RegisterFailHandler(Fail)
26+
RunSpecs(t, "pkg/link")
27+
}

pkg/link/spoofcheck.go

+245
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
// Copyright 2021 CNI authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package link
16+
17+
import (
18+
"fmt"
19+
"os"
20+
21+
"github.com/networkplumbing/go-nft/nft"
22+
"github.com/networkplumbing/go-nft/nft/schema"
23+
)
24+
25+
const (
26+
natTableName = "nat"
27+
preRoutingBaseChainName = "PREROUTING"
28+
)
29+
30+
type NftConfigurer interface {
31+
Apply(*nft.Config) error
32+
Read() (*nft.Config, error)
33+
}
34+
35+
type SpoofChecker struct {
36+
iface string
37+
macAddress string
38+
refID string
39+
configurer NftConfigurer
40+
}
41+
42+
type defaultNftConfigurer struct{}
43+
44+
func (_ defaultNftConfigurer) Apply(cfg *nft.Config) error {
45+
return nft.ApplyConfig(cfg)
46+
}
47+
48+
func (_ defaultNftConfigurer) Read() (*nft.Config, error) {
49+
return nft.ReadConfig()
50+
}
51+
52+
func NewSpoofChecker(iface, macAddress, refID string) *SpoofChecker {
53+
return NewSpoofCheckerWithConfigurer(iface, macAddress, refID, defaultNftConfigurer{})
54+
}
55+
56+
func NewSpoofCheckerWithConfigurer(iface, macAddress, refID string, configurer NftConfigurer) *SpoofChecker {
57+
return &SpoofChecker{iface, macAddress, refID, configurer}
58+
}
59+
60+
// Setup applies nftables configuration to restrict traffic
61+
// from the provided interface. Only traffic with the mentioned mac address
62+
// is allowed to pass, all others are blocked.
63+
// The configuration follows the format libvirt and ebtables implemented, allowing
64+
// extensions to the rules in the future.
65+
// refID is used to label the rules with a unique comment, identifying the rule-set.
66+
//
67+
// In order to take advantage of the nftables configuration change atomicity, the
68+
// following steps are taken to apply the configuration:
69+
// - Declare the table and chains (they will be created in case not present).
70+
// - Apply the rules, while first flushing the iface/mac specific regular chain rules.
71+
// Two transactions are used because the flush succeeds only if the table/chain it targets
72+
// exists. This avoids the need to query the existing state and acting upon it (a raceful pattern).
73+
// Although two transactions are taken place, only the 2nd one where the rules
74+
// are added has a real impact on the system.
75+
func (sc *SpoofChecker) Setup() error {
76+
baseConfig := nft.NewConfig()
77+
78+
baseConfig.AddTable(&schema.Table{Family: schema.FamilyBridge, Name: natTableName})
79+
80+
baseConfig.AddChain(sc.baseChain())
81+
ifaceChain := sc.ifaceChain()
82+
baseConfig.AddChain(ifaceChain)
83+
macChain := sc.macChain(ifaceChain.Name)
84+
baseConfig.AddChain(macChain)
85+
86+
if err := sc.configurer.Apply(baseConfig); err != nil {
87+
return fmt.Errorf("failed to setup spoof-check: %v", err)
88+
}
89+
90+
rulesConfig := nft.NewConfig()
91+
92+
rulesConfig.FlushChain(ifaceChain)
93+
rulesConfig.FlushChain(macChain)
94+
95+
rulesConfig.AddRule(sc.matchIfaceJumpToChainRule(preRoutingBaseChainName, ifaceChain.Name))
96+
rulesConfig.AddRule(sc.jumpToChainRule(ifaceChain.Name, macChain.Name))
97+
rulesConfig.AddRule(sc.matchMacRule(macChain.Name))
98+
rulesConfig.AddRule(sc.dropRule(macChain.Name))
99+
100+
if err := sc.configurer.Apply(rulesConfig); err != nil {
101+
return fmt.Errorf("failed to setup spoof-check: %v", err)
102+
}
103+
104+
return nil
105+
}
106+
107+
// Teardown removes the interface and mac-address specific chains and their rules.
108+
// The table and base-chain are expected to survive while the base-chain rule that matches the
109+
// interface is removed.
110+
func (sc *SpoofChecker) Teardown() error {
111+
ifaceChain := sc.ifaceChain()
112+
currentConfig, ifaceMatchRuleErr := sc.configurer.Read()
113+
if ifaceMatchRuleErr == nil {
114+
expectedRuleToFind := sc.matchIfaceJumpToChainRule(preRoutingBaseChainName, ifaceChain.Name)
115+
// It is safer to exclude the statement matching, avoiding cases where a current statement includes
116+
// additional default entries (e.g. counters).
117+
ruleToFindExcludingStatements := *expectedRuleToFind
118+
ruleToFindExcludingStatements.Expr = nil
119+
rules := currentConfig.LookupRule(&ruleToFindExcludingStatements)
120+
if len(rules) > 0 {
121+
c := nft.NewConfig()
122+
for _, rule := range rules {
123+
c.DeleteRule(rule)
124+
}
125+
if err := sc.configurer.Apply(c); err != nil {
126+
ifaceMatchRuleErr = fmt.Errorf("failed to delete iface match rule: %v", err)
127+
}
128+
} else {
129+
fmt.Fprintf(os.Stderr, "spoofcheck/teardown: unable to detect iface match rule for deletion: %+v", expectedRuleToFind)
130+
}
131+
}
132+
133+
regularChainsConfig := nft.NewConfig()
134+
regularChainsConfig.DeleteChain(ifaceChain)
135+
regularChainsConfig.DeleteChain(sc.macChain(ifaceChain.Name))
136+
137+
var regularChainsErr error
138+
if err := sc.configurer.Apply(regularChainsConfig); err != nil {
139+
regularChainsErr = fmt.Errorf("failed to delete regular chains: %v", err)
140+
}
141+
142+
if ifaceMatchRuleErr != nil || regularChainsErr != nil {
143+
return fmt.Errorf("failed to teardown spoof-check: %v, %v", ifaceMatchRuleErr, regularChainsErr)
144+
}
145+
return nil
146+
}
147+
148+
func (sc *SpoofChecker) matchIfaceJumpToChainRule(chain, toChain string) *schema.Rule {
149+
return &schema.Rule{
150+
Family: schema.FamilyBridge,
151+
Table: natTableName,
152+
Chain: chain,
153+
Expr: []schema.Statement{
154+
{Match: &schema.Match{
155+
Op: schema.OperEQ,
156+
Left: schema.Expression{RowData: []byte(`{"meta":{"key":"iifname"}}`)},
157+
Right: schema.Expression{String: &sc.iface},
158+
}},
159+
{Verdict: schema.Verdict{Jump: &schema.ToTarget{Target: toChain}}},
160+
},
161+
Comment: ruleComment(sc.refID),
162+
}
163+
}
164+
165+
func (sc *SpoofChecker) jumpToChainRule(chain, toChain string) *schema.Rule {
166+
return &schema.Rule{
167+
Family: schema.FamilyBridge,
168+
Table: natTableName,
169+
Chain: chain,
170+
Expr: []schema.Statement{
171+
{Verdict: schema.Verdict{Jump: &schema.ToTarget{Target: toChain}}},
172+
},
173+
Comment: ruleComment(sc.refID),
174+
}
175+
}
176+
177+
func (sc *SpoofChecker) matchMacRule(chain string) *schema.Rule {
178+
return &schema.Rule{
179+
Family: schema.FamilyBridge,
180+
Table: natTableName,
181+
Chain: chain,
182+
Expr: []schema.Statement{
183+
{Match: &schema.Match{
184+
Op: schema.OperEQ,
185+
Left: schema.Expression{Payload: &schema.Payload{
186+
Protocol: schema.PayloadProtocolEther,
187+
Field: schema.PayloadFieldEtherSAddr,
188+
}},
189+
Right: schema.Expression{String: &sc.macAddress},
190+
}},
191+
{Verdict: schema.Verdict{SimpleVerdict: schema.SimpleVerdict{Return: true}}},
192+
},
193+
Comment: ruleComment(sc.refID),
194+
}
195+
}
196+
197+
func (sc *SpoofChecker) dropRule(chain string) *schema.Rule {
198+
macRulesIndex := nft.NewRuleIndex()
199+
return &schema.Rule{
200+
Family: schema.FamilyBridge,
201+
Table: natTableName,
202+
Chain: chain,
203+
Index: macRulesIndex.Next(),
204+
Expr: []schema.Statement{
205+
{Verdict: schema.Verdict{SimpleVerdict: schema.SimpleVerdict{Drop: true}}},
206+
},
207+
Comment: ruleComment(sc.refID),
208+
}
209+
}
210+
211+
func (_ *SpoofChecker) baseChain() *schema.Chain {
212+
chainPriority := -300
213+
return &schema.Chain{
214+
Family: schema.FamilyBridge,
215+
Table: natTableName,
216+
Name: preRoutingBaseChainName,
217+
Type: schema.TypeFilter,
218+
Hook: schema.HookPreRouting,
219+
Prio: &chainPriority,
220+
Policy: schema.PolicyAccept,
221+
}
222+
}
223+
224+
func (sc *SpoofChecker) ifaceChain() *schema.Chain {
225+
ifaceChainName := "cni-br-iface-" + sc.refID
226+
return &schema.Chain{
227+
Family: schema.FamilyBridge,
228+
Table: natTableName,
229+
Name: ifaceChainName,
230+
}
231+
}
232+
233+
func (_ *SpoofChecker) macChain(ifaceChainName string) *schema.Chain {
234+
macChainName := ifaceChainName + "-mac"
235+
return &schema.Chain{
236+
Family: schema.FamilyBridge,
237+
Table: natTableName,
238+
Name: macChainName,
239+
}
240+
}
241+
242+
func ruleComment(id string) string {
243+
const refIDPrefix = "macspoofchk-"
244+
return refIDPrefix + id
245+
}

0 commit comments

Comments
 (0)