kubelet, kube-proxy: unmark packets before masquerading them

It seems that if you set the packet mark on a packet and then route
that packet through a kernel VXLAN interface, the VXLAN-encapsulated
packet will still have the mark from the original packet. Since our
NAT rules are based on the packet mark, this was causing us to
double-NAT some packets, which then triggered a kernel checksumming
bug. But even without the checksum bug, there are reasons to avoid
double-NATting, so fix the rules to unmark the packets before
masquerading them.
This commit is contained in:
Dan Winship
2020-06-11 09:11:03 -04:00
parent 2930723a25
commit c12534d8b4
5 changed files with 56 additions and 19 deletions

View File

@@ -418,7 +418,7 @@ func NewProxier(ipt utiliptables.Interface,
// Generate the masquerade mark to use for SNAT rules.
masqueradeValue := 1 << uint(masqueradeBit)
masqueradeMark := fmt.Sprintf("%#08x/%#08x", masqueradeValue, masqueradeValue)
masqueradeMark := fmt.Sprintf("%#08x", masqueradeValue)
isIPv6 := utilnet.IsIPv6(nodeIP)
@@ -1758,7 +1758,7 @@ func (proxier *Proxier) writeIptablesRules() {
writeLine(proxier.filterRules,
"-A", string(KubeForwardChain),
"-m", "comment", "--comment", `"kubernetes forwarding rules"`,
"-m", "mark", "--mark", proxier.masqueradeMark,
"-m", "mark", "--mark", fmt.Sprintf("%s/%s", proxier.masqueradeMark, proxier.masqueradeMark),
"-j", "ACCEPT",
)
@@ -1842,10 +1842,20 @@ func (proxier *Proxier) createAndLinkeKubeChain() {
// this so that it is easier to flush and change, for example if the mark
// value should ever change.
// NB: THIS MUST MATCH the corresponding code in the kubelet
writeLine(proxier.natRules, []string{
"-A", string(kubePostroutingChain),
"-m", "mark", "!", "--mark", fmt.Sprintf("%s/%s", proxier.masqueradeMark, proxier.masqueradeMark),
"-j", "RETURN",
}...)
// Clear the mark to avoid re-masquerading if the packet re-traverses the network stack.
writeLine(proxier.natRules, []string{
"-A", string(kubePostroutingChain),
// XOR proxier.masqueradeMark to unset it
"-j", "MARK", "--xor-mark", proxier.masqueradeMark,
}...)
masqRule := []string{
"-A", string(kubePostroutingChain),
"-m", "comment", "--comment", `"kubernetes service traffic requiring SNAT"`,
"-m", "mark", "--mark", proxier.masqueradeMark,
"-j", "MASQUERADE",
}
if proxier.iptables.HasRandomFully() {
@@ -1858,7 +1868,7 @@ func (proxier *Proxier) createAndLinkeKubeChain() {
// value should ever change.
writeLine(proxier.natRules, []string{
"-A", string(KubeMarkMasqChain),
"-j", "MARK", "--set-xmark", proxier.masqueradeMark,
"-j", "MARK", "--or-mark", proxier.masqueradeMark,
}...)
}