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

felix: ensure vxlan udp flows are not tracked in conntrack #8977

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
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
1 change: 1 addition & 0 deletions felix/generictables/match_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ type MatchCriteria interface {
IPSetNames() (ipSetNames []string)
SourcePorts(ports ...uint16) MatchCriteria
NotSourcePorts(ports ...uint16) MatchCriteria
DestPort(port uint16) MatchCriteria
DestPorts(ports ...uint16) MatchCriteria
NotDestPorts(ports ...uint16) MatchCriteria
SourcePortRanges(ports []*proto.PortRange) MatchCriteria
Expand Down
4 changes: 4 additions & 0 deletions felix/iptables/match_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,10 @@ func (m matchCriteria) NotSourcePorts(ports ...uint16) generictables.MatchCriter
return append(m, fmt.Sprintf("-m multiport ! --source-ports %s", portsString))
}

func (m matchCriteria) DestPort(port uint16) generictables.MatchCriteria {
return append(m, fmt.Sprintf("--dport %v", port))
}

func (m matchCriteria) DestPorts(ports ...uint16) generictables.MatchCriteria {
portsString := PortsToMultiport(ports)
return append(m, fmt.Sprintf("-m multiport --destination-ports %s", portsString))
Expand Down
5 changes: 5 additions & 0 deletions felix/nftables/match_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,11 @@ func (m nftMatch) NotSourcePorts(ports ...uint16) generictables.MatchCriteria {
return m
}

func (m nftMatch) DestPort(port uint16) generictables.MatchCriteria {
m.clauses = append(m.clauses, fmt.Sprintf("%s dport %v", m.transportProto(), port))
return m
}

func (m nftMatch) DestPorts(ports ...uint16) generictables.MatchCriteria {
m.clauses = append(m.clauses, fmt.Sprintf("%s dport %s", m.transportProto(), PortsToMultiport(ports)))
return m
Expand Down
21 changes: 21 additions & 0 deletions felix/rules/static.go
Original file line number Diff line number Diff line change
Expand Up @@ -1293,6 +1293,17 @@ func (r *DefaultRuleRenderer) StaticRawPreroutingChain(ipVersion uint8) *generic
})
}

// Ensure VXLAN UDP Flows are not tracked in conntrack.
// VXLAN uses different source ports in each direction so
// tracking results in unreplied flows.
if r.VXLANEnabled || r.VXLANEnabledV6 {
log.Debug("Adding VXLAN NOTRACK iptables rule to PREROUTING chain")
rules = append(rules, generictables.Rule{
Match: r.NewMatch().Protocol("udp").DestPort(uint16(r.VXLANPort)),
Action: r.NoTrack(),
})
}

// Set a mark on the packet if it's from a workload interface.
markFromWorkload := r.IptablesMarkScratch0
for _, ifacePrefix := range r.WorkloadIfacePrefixes {
Expand Down Expand Up @@ -1429,6 +1440,16 @@ func (r *DefaultRuleRenderer) StaticRawOutputChain(tcBypassMark uint32) *generic
// return here without the mark bit set if the interface wasn't one that
// we're policing.
}

// Ensure VXLAN UDP Flows are not tracked in conntrack.
if r.VXLANEnabled || r.VXLANEnabledV6 {
log.Debug("Adding VXLAN NOTRACK iptables rule")
rules = append(rules, generictables.Rule{
Match: r.NewMatch().Protocol("udp").DestPort(uint16(r.VXLANPort)),
Action: r.NoTrack(),
})
}

if tcBypassMark == 0 {
rules = append(rules, []generictables.Rule{
{
Expand Down
101 changes: 101 additions & 0 deletions felix/rules/static_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1073,6 +1073,66 @@ var _ = Describe("Static", func() {
}))
})

It("IPv4: Should return expected VXLAN notrack PREROUTING chain", func() {
allCalicoMarkBits := rr.IptablesMarkAccept |
rr.IptablesMarkPass |
rr.IptablesMarkScratch0 |
rr.IptablesMarkScratch1
markFromWorkload := rr.IptablesMarkScratch0

chain := &generictables.Chain{
Name: "cali-PREROUTING",
Rules: []generictables.Rule{
{Action: ClearMarkAction{Mark: allCalicoMarkBits}},
{Match: Match().Protocol("udp").DestPort(uint16(rr.VXLANPort)),
Action: NoTrackAction{},
},
},
}

for _, ifacePrefix := range rr.WorkloadIfacePrefixes {
chain.Rules = append(chain.Rules, generictables.Rule{
Match: Match().InInterface(ifacePrefix + "+"),
Action: SetMarkAction{Mark: markFromWorkload},
})
}

chain.Rules = append(chain.Rules, generictables.Rule{
Match: Match().MarkMatchesWithMask(markFromWorkload, markFromWorkload),
Action: JumpAction{Target: ChainRpfSkip},
})

chain.Rules = append(chain.Rules, rr.RPFilter(4, markFromWorkload, markFromWorkload, rr.OpenStackSpecialCasesEnabled, rr.IptablesFilterDenyAction())...)
chain.Rules = append(chain.Rules, generictables.Rule{
Match: Match().MarkClear(markFromWorkload),
Action: JumpAction{Target: ChainDispatchFromHostEndpoint},
}, generictables.Rule{
Match: Match().MarkSingleBitSet(rr.IptablesMarkAccept),
Action: AcceptAction{},
})

Expect(rr.StaticRawPreroutingChain(4)).To(Equal(chain))
})

It("IPv4: Should return expected VXLAN notrack OUTPUT chain", func() {
allCalicoMarkBits := rr.IptablesMarkAccept |
rr.IptablesMarkPass |
rr.IptablesMarkScratch0 |
rr.IptablesMarkScratch1
Expect(rr.StaticRawOutputChain(0)).To(Equal(&generictables.Chain{
Name: "cali-OUTPUT",
Rules: []generictables.Rule{
{Action: ClearMarkAction{Mark: allCalicoMarkBits}},
{Action: JumpAction{Target: ChainDispatchToHostEndpoint}},
{Match: Match().Protocol("udp").DestPort(uint16(rr.VXLANPort)),
Action: NoTrackAction{}},
{Match: Match().MarkSingleBitSet(rr.IptablesMarkAccept),
Action: AcceptAction{}},
},
},
))
})

Describe("and IPv4 tunnel IP", func() {
BeforeEach(func() {
conf.VXLANTunnelAddress = net.IP{10, 0, 0, 1}
Expand Down Expand Up @@ -1125,6 +1185,47 @@ var _ = Describe("Static", func() {
}))
})

It("IPv6: Should return expected VXLAN notrack PREROUTING chain", func() {
allCalicoMarkBits := rr.IptablesMarkAccept |
rr.IptablesMarkPass |
rr.IptablesMarkScratch0 |
rr.IptablesMarkScratch1
markFromWorkload := rr.IptablesMarkScratch0

chain := &generictables.Chain{
Name: "cali-PREROUTING",
Rules: []generictables.Rule{
{Action: ClearMarkAction{Mark: allCalicoMarkBits}},
{Match: Match().Protocol("udp").DestPort(uint16(rr.VXLANPort)),
Action: NoTrackAction{},
},
},
}

for _, ifacePrefix := range rr.WorkloadIfacePrefixes {
chain.Rules = append(chain.Rules, generictables.Rule{
Match: Match().InInterface(ifacePrefix + "+"),
Action: SetMarkAction{Mark: markFromWorkload},
})
}

chain.Rules = append(chain.Rules, generictables.Rule{
Match: Match().MarkMatchesWithMask(markFromWorkload, markFromWorkload),
Action: JumpAction{Target: ChainRpfSkip},
})

chain.Rules = append(chain.Rules, rr.RPFilter(6, markFromWorkload, markFromWorkload, rr.OpenStackSpecialCasesEnabled, rr.IptablesFilterDenyAction())...)
chain.Rules = append(chain.Rules, generictables.Rule{
Match: Match().MarkClear(markFromWorkload),
Action: JumpAction{Target: ChainDispatchFromHostEndpoint},
}, generictables.Rule{
Match: Match().MarkSingleBitSet(rr.IptablesMarkAccept),
Action: AcceptAction{},
})

Expect(rr.StaticRawPreroutingChain(6)).To(Equal(chain))
})

Describe("and IPv6 tunnel IP", func() {
BeforeEach(func() {
conf.VXLANTunnelAddressV6 = net.ParseIP("dead:beef::1")
Expand Down