From 965eda3b9a02f5eeeb5c17e81dbc4f8cca029b7c Mon Sep 17 00:00:00 2001 From: Cory Snider Date: Wed, 22 Mar 2023 20:25:32 -0400 Subject: [PATCH] libnet/d/overlay: insert the input-drop rule FirewallD creates the root INPUT chain with a default-accept policy and a terminal rule which rejects all packets not accepted by any prior rule. Any subsequent rules appended to the chain are therefore inert. The administrator would have to open the VXLAN UDP port to make overlay networks work at all, which would result in all VXLAN traffic being accepted and defeating our attempts to enforce encryption on encrypted overlay networks. Insert the rule to drop unencrypted VXLAN packets tagged for encrypted overlay networks at the top of the INPUT chain so that enforcement of mandatory encryption takes precedence over any accept rules configured by the administrator. Continue to append the accept rule to the bottom of the chain so as not to override any administrator-configured drop rules. Signed-off-by: Cory Snider --- libnetwork/drivers/overlay/encryption.go | 25 +++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/libnetwork/drivers/overlay/encryption.go b/libnetwork/drivers/overlay/encryption.go index 81b978cef5..5b76f7793d 100644 --- a/libnetwork/drivers/overlay/encryption.go +++ b/libnetwork/drivers/overlay/encryption.go @@ -277,29 +277,40 @@ var programMangle = programVXLANRuleFunc(func(matchVXLAN matchVXLANFunc, vni uin var programInput = programVXLANRuleFunc(func(matchVXLAN matchVXLANFunc, vni uint32, add bool) error { var ( plainVxlan = matchVXLAN(overlayutils.VXLANUDPPort(), vni) - ipsecVxlan = append([]string{"-m", "policy", "--dir", "in", "--pol", "ipsec"}, plainVxlan...) - block = append(plainVxlan, "-j", "DROP") - accept = append(ipsecVxlan, "-j", "ACCEPT") chain = "INPUT" - action = iptables.Append msg = "add" ) + rule := func(policy, jump string) []string { + args := append([]string{"-m", "policy", "--dir", "in", "--pol", policy}, plainVxlan...) + return append(args, "-j", jump) + } + // TODO IPv6 support iptable := iptables.GetIptable(iptables.IPv4) if !add { - action = iptables.Delete msg = "remove" } + action := func(a iptables.Action) iptables.Action { + if !add { + return iptables.Delete + } + return a + } + // Accept incoming VXLAN datagrams for the VNI which were subjected to IPSec processing. - if err := iptable.ProgramRule(iptables.Filter, chain, action, accept); err != nil { + // Append to the bottom of the chain to give administrator-configured rules precedence. + if err := iptable.ProgramRule(iptables.Filter, chain, action(iptables.Append), rule("ipsec", "ACCEPT")); err != nil { return fmt.Errorf("could not %s input accept rule: %w", msg, err) } // Drop incoming VXLAN datagrams for the VNI which were received in cleartext. - if err := iptable.ProgramRule(iptables.Filter, chain, action, block); err != nil { + // Insert at the top of the chain so the packets are dropped even if an + // administrator-configured rule exists which would otherwise unconditionally + // accept incoming VXLAN traffic. + if err := iptable.ProgramRule(iptables.Filter, chain, action(iptables.Insert), rule("none", "DROP")); err != nil { return fmt.Errorf("could not %s input drop rule: %w", msg, err) }