From 3690c46a3291b174e816212c5b83b8165450f24f Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 10 May 2019 17:52:15 -0400 Subject: [PATCH] Restrict access to EC2 metadata IP --- cmd/sdn-cni-plugin/openshift-sdn_linux.go | 7 +++- .../restrictedendpoints/endpoint_admission.go | 32 ++++++++++++------- pkg/network/node/ovscontroller.go | 3 ++ 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/cmd/sdn-cni-plugin/openshift-sdn_linux.go b/cmd/sdn-cni-plugin/openshift-sdn_linux.go index 4dd6b919dba8..6c6f8c974c46 100644 --- a/cmd/sdn-cni-plugin/openshift-sdn_linux.go +++ b/cmd/sdn-cni-plugin/openshift-sdn_linux.go @@ -120,10 +120,15 @@ func (p *cniPlugin) testCmdAdd(args *skel.CmdArgs) (types.Result, error) { } var iptablesCommands = [][]string{ + // Block MCS {"-A", "OUTPUT", "-p", "tcp", "-m", "tcp", "--dport", "22623", "-j", "REJECT"}, {"-A", "OUTPUT", "-p", "tcp", "-m", "tcp", "--dport", "22624", "-j", "REJECT"}, {"-A", "FORWARD", "-p", "tcp", "-m", "tcp", "--dport", "22623", "-j", "REJECT"}, {"-A", "FORWARD", "-p", "tcp", "-m", "tcp", "--dport", "22624", "-j", "REJECT"}, + + // Block cloud metadata IP + {"-A", "OUTPUT", "-d", "169.254.169.254", "-j", "REJECT"}, + {"-A", "FORWARD", "-d", "169.254.169.254", "-j", "REJECT"}, } func (p *cniPlugin) CmdAdd(args *skel.CmdArgs) error { @@ -234,7 +239,7 @@ func (p *cniPlugin) CmdAdd(args *skel.CmdArgs) error { } } - // HACK: block access to MCS until we can secure it properly + // Block access to certain things for _, args := range iptablesCommands { out, err := exec.Command("iptables", args...).CombinedOutput() if err != nil { diff --git a/pkg/network/admission/restrictedendpoints/endpoint_admission.go b/pkg/network/admission/restrictedendpoints/endpoint_admission.go index 91e8fa2bfc23..92c665cf99dd 100644 --- a/pkg/network/admission/restrictedendpoints/endpoint_admission.go +++ b/pkg/network/admission/restrictedendpoints/endpoint_admission.go @@ -64,7 +64,6 @@ type restrictedEndpointsAdmission struct { authorizer authorizer.Authorizer restrictedNetworks []*net.IPNet - restrictedPorts []kapi.EndpointPort } var _ = initializer.WantsAuthorizer(&restrictedEndpointsAdmission{}) @@ -87,10 +86,6 @@ func NewRestrictedEndpointsAdmission(restrictedNetworks []*net.IPNet) *restricte return &restrictedEndpointsAdmission{ Handler: admission.NewHandler(admission.Create, admission.Update), restrictedNetworks: restrictedNetworks, - restrictedPorts: []kapi.EndpointPort{ - {Protocol: kapi.ProtocolTCP, Port: 22623}, - {Protocol: kapi.ProtocolTCP, Port: 22624}, - }, } } @@ -105,14 +100,26 @@ func (r *restrictedEndpointsAdmission) ValidateInitialization() error { return nil } -func (r *restrictedEndpointsAdmission) findRestrictedIP(ep *kapi.Endpoints) error { +var ( + defaultRestrictedPorts = []kapi.EndpointPort{ + // MCS ports + {Protocol: kapi.ProtocolTCP, Port: 22623}, + {Protocol: kapi.ProtocolTCP, Port: 22624}, + } + defaultRestrictedNetworks = []*net.IPNet{ + // IPv4 link-local range 169.254.0.0/16 (including cloud metadata IP) + {IP: net.ParseIP("169.254.0.0"), Mask: net.CIDRMask(16, 32)}, + } +) + +func (r *restrictedEndpointsAdmission) findRestrictedIP(ep *kapi.Endpoints, restricted []*net.IPNet) error { for _, subset := range ep.Subsets { for _, addr := range subset.Addresses { ip := net.ParseIP(addr.IP) if ip == nil { continue } - for _, net := range r.restrictedNetworks { + for _, net := range restricted { if net.Contains(ip) { return fmt.Errorf("endpoint address %s is not allowed", addr.IP) } @@ -122,10 +129,10 @@ func (r *restrictedEndpointsAdmission) findRestrictedIP(ep *kapi.Endpoints) erro return nil } -func (r *restrictedEndpointsAdmission) findRestrictedPort(ep *kapi.Endpoints) error { +func (r *restrictedEndpointsAdmission) findRestrictedPort(ep *kapi.Endpoints, restricted []kapi.EndpointPort) error { for _, subset := range ep.Subsets { for _, port := range subset.Ports { - for _, restricted := range r.restrictedPorts { + for _, restricted := range restricted { if port.Protocol == restricted.Protocol && port.Port == restricted.Port { return fmt.Errorf("endpoint port %s:%d is not allowed", string(port.Protocol), port.Port) } @@ -164,9 +171,12 @@ func (r *restrictedEndpointsAdmission) Validate(a admission.Attributes) error { return nil } - restrictedErr := r.findRestrictedIP(ep) + restrictedErr := r.findRestrictedIP(ep, r.restrictedNetworks) + if restrictedErr == nil { + restrictedErr = r.findRestrictedIP(ep, defaultRestrictedNetworks) + } if restrictedErr == nil { - restrictedErr = r.findRestrictedPort(ep) + restrictedErr = r.findRestrictedPort(ep, defaultRestrictedPorts) } if restrictedErr == nil { return nil diff --git a/pkg/network/node/ovscontroller.go b/pkg/network/node/ovscontroller.go index d31ea8927e4e..db3da7a1a3eb 100644 --- a/pkg/network/node/ovscontroller.go +++ b/pkg/network/node/ovscontroller.go @@ -160,6 +160,9 @@ func (oc *ovsController) SetupOVS(clusterNetworkCIDR []string, serviceNetworkCID otx.AddFlow("table=30, priority=100, ip, nw_dst=%s, actions=goto_table:90", clusterCIDR) } + // Link-local traffic + otx.AddFlow("table=30, priority=75, ip, nw_dst=169.254.0.0/16, actions=drop") + // Multicast coming from the VXLAN otx.AddFlow("table=30, priority=50, in_port=1, ip, nw_dst=224.0.0.0/4, actions=goto_table:120") // Multicast coming from local pods