diff --git a/libnetwork/drivers/overlay/encryption.go b/libnetwork/drivers/overlay/encryption.go index 519f6250ae..91800e99a9 100644 --- a/libnetwork/drivers/overlay/encryption.go +++ b/libnetwork/drivers/overlay/encryption.go @@ -227,11 +227,9 @@ func removeEncryption(localIP, remoteIP net.IP, em *encrMap) error { func programMangle(vni uint32, add bool) error { var ( - p = strconv.FormatUint(uint64(overlayutils.VXLANUDPPort()), 10) - c = fmt.Sprintf("0>>22&0x3C@12&0xFFFFFF00=%d", int(vni)<<8) m = strconv.FormatUint(mark, 10) chain = "OUTPUT" - rule = []string{"-p", "udp", "--dport", p, "-m", "u32", "--u32", c, "-j", "MARK", "--set-mark", m} + rule = append(matchVXLAN(overlayutils.VXLANUDPPort(), vni), "-j", "MARK", "--set-mark", m) a = iptables.Append action = "install" ) @@ -253,12 +251,10 @@ func programMangle(vni uint32, add bool) error { func programInput(vni uint32, add bool) error { var ( - port = strconv.FormatUint(uint64(overlayutils.VXLANUDPPort()), 10) - vniMatch = fmt.Sprintf("0>>22&0x3C@12&0xFFFFFF00=%d", int(vni)<<8) - plainVxlan = []string{"-p", "udp", "--dport", port, "-m", "u32", "--u32", vniMatch, "-j"} + plainVxlan = matchVXLAN(overlayutils.VXLANUDPPort(), vni) ipsecVxlan = append([]string{"-m", "policy", "--dir", "in", "--pol", "ipsec"}, plainVxlan...) - block = append(plainVxlan, "DROP") - accept = append(ipsecVxlan, "ACCEPT") + block = append(plainVxlan, "-j", "DROP") + accept = append(ipsecVxlan, "-j", "ACCEPT") chain = "INPUT" action = iptables.Append msg = "add" diff --git a/libnetwork/drivers/overlay/encryption_u32.go b/libnetwork/drivers/overlay/encryption_u32.go new file mode 100644 index 0000000000..c93f7c96fc --- /dev/null +++ b/libnetwork/drivers/overlay/encryption_u32.go @@ -0,0 +1,30 @@ +package overlay + +import ( + "fmt" + "strconv" +) + +// matchVXLAN returns an iptables rule fragment which matches VXLAN datagrams +// with the given destination port and VXLAN Network ID utilizing the xt_u32 +// netfilter kernel module. The returned slice's backing array is guaranteed not +// to alias any other slice's. +func matchVXLAN(port, vni uint32) []string { + dport := strconv.FormatUint(uint64(port), 10) + + // The u32 expression language is documented in iptables-extensions(8). + // https://ipset.netfilter.org/iptables-extensions.man.html#lbCK + // + // 0>>22&0x3C ; Compute number of octets in IPv4 header + // @ ; Make this the new offset into the packet + // ; (jump to start of UDP header) + // 12&0xFFFFFF00 ; Read 32-bit value at offset 12 and mask off the bottom octet + // = ; Test whether the value is equal to a constant + // + // A UDP header is eight octets long so offset 12 from the start of the + // UDP header is four octets into the payload: the VNI field of the + // VXLAN header. + vniMatch := fmt.Sprintf("0>>22&0x3C@12&0xFFFFFF00=%d", int(vni)<<8) + + return []string{"-p", "udp", "--dport", dport, "-m", "u32", "--u32", vniMatch} +}