diff --git a/scripts/caclmgrd b/scripts/caclmgrd index 30b166e7..7edaeee4 100755 --- a/scripts/caclmgrd +++ b/scripts/caclmgrd @@ -147,6 +147,7 @@ class ControlPlaneAclManager(daemon_base.DaemonBase): self.namespace_mgmt_ipv6 = self.get_namespace_mgmt_ipv6(self.iptables_cmd_ns_prefix[DEFAULT_NAMESPACE], DEFAULT_NAMESPACE) self.namespace_docker_mgmt_ip = {} self.namespace_docker_mgmt_ipv6 = {} + self.exclude_mgmt_port_rule = [ '!', '-i', 'eth0' ] # Get all features that are present {feature_name : True/False} self.feature_present = {} @@ -179,6 +180,11 @@ class ControlPlaneAclManager(daemon_base.DaemonBase): self.num_changes[fabric_asic_namespace] = 0 self.update_docker_mgmt_ip_acl(fabric_asic_namespace) + def exclude_mgmt_port(self, rule): + # Exclude mgmt port from this rule + rule.extend(self.exclude_mgmt_port_rule) + return rule + def update_docker_mgmt_ip_acl(self, namespace): self.iptables_cmd_ns_prefix[namespace] = ["ip", "netns", "exec", str(namespace)] self.namespace_docker_mgmt_ip[namespace] = self.get_namespace_mgmt_ip(self.iptables_cmd_ns_prefix[namespace], @@ -641,8 +647,8 @@ class ControlPlaneAclManager(daemon_base.DaemonBase): # Add iptables/ip6tables commands to allow all incoming BGP traffic # TODO: Determine BGP ACLs based on configured device sessions, and remove this blanket acceptance - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['iptables', '-A', 'INPUT', '-p', 'tcp', '--dport', '179', '-j', 'ACCEPT']) - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['ip6tables', '-A', 'INPUT', '-p', 'tcp', '--dport', '179', '-j', 'ACCEPT']) + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + self.exclude_mgmt_port(['iptables', '-A', 'INPUT', '-p', 'tcp', '--dport', '179', '-j', 'ACCEPT'])) + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + self.exclude_mgmt_port(['ip6tables', '-A', 'INPUT', '-p', 'tcp', '--dport', '179', '-j', 'ACCEPT'])) # Add ip6tables commands to disable connection tracking for icmpv6 traffic iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['ip6tables', '-t', 'raw', '-A', 'PREROUTING', '-p', 'ipv6-icmp', '-j', 'NOTRACK']) @@ -785,6 +791,11 @@ class ControlPlaneAclManager(daemon_base.DaemonBase): # Append the packet action as the jump target rule_cmd += ["-j", "{}".format(rule_props["PACKET_ACTION"])] + if (dst_port not in self.ACL_SERVICES["NTP"]["dst_ports"] and + dst_port not in self.ACL_SERVICES["SNMP"]["dst_ports"] and + dst_port not in self.ACL_SERVICES["SSH"]["dst_ports"]): + rule_cmd = self.exclude_mgmt_port(rule_cmd) + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + rule_cmd) num_ctrl_plane_acl_rules += 1 @@ -896,8 +907,8 @@ class ControlPlaneAclManager(daemon_base.DaemonBase): def get_bfd_iptable_commands(self, namespace): iptables_cmds = [] # Add iptables/ip6tables commands to allow all BFD singlehop and multihop sessions - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['iptables', '-I', 'INPUT', '2', '-p', 'udp', '-m', 'multiport', '--dports', '3784,4784', '-j', 'ACCEPT']) - iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + ['ip6tables', '-I', 'INPUT', '2', '-p', 'udp', '-m', 'multiport', '--dports', '3784,4784', '-j', 'ACCEPT']) + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + self.exclude_mgmt_port(['iptables', '-I', 'INPUT', '2', '-p', 'udp', '-m', 'multiport', '--dports', '3784,4784', '-j', 'ACCEPT'])) + iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + self.exclude_mgmt_port(['ip6tables', '-I', 'INPUT', '2', '-p', 'udp', '-m', 'multiport', '--dports', '3784,4784', '-j', 'ACCEPT'])) return iptables_cmds def allow_bfd_protocol(self, namespace): @@ -921,10 +932,10 @@ class ControlPlaneAclManager(daemon_base.DaemonBase): ip_addr = ipaddress.ip_address(self.VxlanSrcIP) if isinstance(ip_addr, ipaddress.IPv6Address): iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + - ['ip6tables', '-I', 'INPUT', '2', '-p', 'udp', '-d', self.VxlanSrcIP, '--dport', '4789', '-j', 'ACCEPT']) + self.exclude_mgmt_port(['ip6tables', '-I', 'INPUT', '2', '-p', 'udp', '-d', self.VxlanSrcIP, '--dport', '4789', '-j', 'ACCEPT'])) elif isinstance(ip_addr, ipaddress.IPv4Address): iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + - ['iptables', '-I', 'INPUT', '2', '-p', 'udp', '-d', self.VxlanSrcIP, '--dport', '4789', '-j', 'ACCEPT']) + self.exclude_mgmt_port(['iptables', '-I', 'INPUT', '2', '-p', 'udp', '-d', self.VxlanSrcIP, '--dport', '4789', '-j', 'ACCEPT'])) return iptables_cmds @@ -947,10 +958,10 @@ class ControlPlaneAclManager(daemon_base.DaemonBase): ip_addr = ipaddress.ip_address(self.VxlanSrcIP) if isinstance(ip_addr, ipaddress.IPv6Address): iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + - ['ip6tables', '-D', 'INPUT', '-p', 'udp', '-d', self.VxlanSrcIP, '--dport', '4789', '-j', 'ACCEPT']) + self.exclude_mgmt_port(['ip6tables', '-D', 'INPUT', '-p', 'udp', '-d', self.VxlanSrcIP, '--dport', '4789', '-j', 'ACCEPT'])) elif isinstance(ip_addr, ipaddress.IPv4Address): iptables_cmds.append(self.iptables_cmd_ns_prefix[namespace] + - ['iptables', '-D', 'INPUT', '-p', 'udp', '-d', self.VxlanSrcIP, '--dport', '4789', '-j', 'ACCEPT']) + self.exclude_mgmt_port(['iptables', '-D', 'INPUT', '-p', 'udp', '-d', self.VxlanSrcIP, '--dport', '4789', '-j', 'ACCEPT'])) self.run_commands(iptables_cmds) self.VxlanAllowed = False diff --git a/tests/caclmgrd/test_bfd_vectors.py b/tests/caclmgrd/test_bfd_vectors.py index 9211f35a..82308184 100644 --- a/tests/caclmgrd/test_bfd_vectors.py +++ b/tests/caclmgrd/test_bfd_vectors.py @@ -27,14 +27,14 @@ }, }, "expected_subprocess_calls": [ - call(['iptables', '-I', 'INPUT', '2', '-p', 'udp', '-m', 'multiport', '--dports', '3784,4784', '-j', 'ACCEPT'], universal_newlines=True, stdout=subprocess.PIPE), - call(['ip6tables', '-I', 'INPUT', '2', '-p', 'udp', '-m', 'multiport', '--dports', '3784,4784', '-j', 'ACCEPT'], universal_newlines=True, stdout=subprocess.PIPE), + call(['iptables', '-I', 'INPUT', '2', '-p', 'udp', '-m', 'multiport', '--dports', '3784,4784', '-j', 'ACCEPT', '!', '-i', 'eth0'], universal_newlines=True, stdout=subprocess.PIPE), + call(['ip6tables', '-I', 'INPUT', '2', '-p', 'udp', '-m', 'multiport', '--dports', '3784,4784', '-j', 'ACCEPT', '!', '-i', 'eth0'], universal_newlines=True, stdout=subprocess.PIPE), call(['iptables', '-A', 'INPUT', '-d', '2.2.2.1/32', '-j', 'DROP'],universal_newlines=True, stdout=subprocess.PIPE), call(['ip6tables', '-A', 'INPUT', '-d', '2001:db8:10::/128', '-j', 'DROP'],universal_newlines=True, stdout=subprocess.PIPE) ], "expected_bfd_subprocess_calls": [ - call(['iptables', '-I', 'INPUT', '2', '-p', 'udp', '-m', 'multiport', '--dports', '3784,4784', '-j', 'ACCEPT'], universal_newlines=True, stdout=subprocess.PIPE), - call(['ip6tables', '-I', 'INPUT', '2', '-p', 'udp', '-m', 'multiport', '--dports', '3784,4784', '-j', 'ACCEPT'], universal_newlines=True, stdout=subprocess.PIPE) + call(['iptables', '-I', 'INPUT', '2', '-p', 'udp', '-m', 'multiport', '--dports', '3784,4784', '-j', 'ACCEPT', '!', '-i', 'eth0'], universal_newlines=True, stdout=subprocess.PIPE), + call(['ip6tables', '-I', 'INPUT', '2', '-p', 'udp', '-m', 'multiport', '--dports', '3784,4784', '-j', 'ACCEPT', '!', '-i', 'eth0'], universal_newlines=True, stdout=subprocess.PIPE) ], "popen_attributes": { 'communicate.return_value': ('output', 'error'), diff --git a/tests/caclmgrd/test_external_client_acl_vectors.py b/tests/caclmgrd/test_external_client_acl_vectors.py index 5f9a9a02..55fe80a3 100644 --- a/tests/caclmgrd/test_external_client_acl_vectors.py +++ b/tests/caclmgrd/test_external_client_acl_vectors.py @@ -72,8 +72,8 @@ "FEATURE": {}, }, "return": [ - ['iptables', '-A', 'INPUT', '-p', 'tcp', '-s', '20.0.0.55/32', '--dport', '8081', '-j', 'ACCEPT'], - ['iptables', '-A', 'INPUT', '-p', 'tcp', '--dport', '8081', '-j', 'DROP'] + ['iptables', '-A', 'INPUT', '-p', 'tcp', '-s', '20.0.0.55/32', '--dport', '8081', '-j', 'ACCEPT', '!', '-i', 'eth0'], + ['iptables', '-A', 'INPUT', '-p', 'tcp', '--dport', '8081', '-j', 'DROP', '!', '-i', 'eth0'] ], } ], @@ -110,12 +110,12 @@ "FEATURE": {}, }, "return": [ - ['iptables', '-A', 'INPUT', '-p', 'tcp', '-s', '20.0.0.55/32', '--dport', '8081', '-j', 'ACCEPT'], - ['iptables', '-A', 'INPUT', '-p', 'tcp', '-s', '20.0.0.55/32', '--dport', '8082', '-j', 'ACCEPT'], - ['iptables', '-A', 'INPUT', '-p', 'tcp', '-s', '20.0.0.55/32', '--dport', '8083', '-j', 'ACCEPT'], - ['iptables', '-A', 'INPUT', '-p', 'tcp', '--dport', '8081', '-j', 'DROP'], - ['iptables', '-A', 'INPUT', '-p', 'tcp', '--dport', '8082', '-j', 'DROP'], - ['iptables', '-A', 'INPUT', '-p', 'tcp', '--dport', '8083', '-j', 'DROP'], + ['iptables', '-A', 'INPUT', '-p', 'tcp', '-s', '20.0.0.55/32', '--dport', '8081', '-j', 'ACCEPT', '!', '-i', 'eth0'], + ['iptables', '-A', 'INPUT', '-p', 'tcp', '-s', '20.0.0.55/32', '--dport', '8082', '-j', 'ACCEPT', '!', '-i', 'eth0'], + ['iptables', '-A', 'INPUT', '-p', 'tcp', '-s', '20.0.0.55/32', '--dport', '8083', '-j', 'ACCEPT', '!', '-i', 'eth0'], + ['iptables', '-A', 'INPUT', '-p', 'tcp', '--dport', '8081', '-j', 'DROP', '!', '-i', 'eth0'], + ['iptables', '-A', 'INPUT', '-p', 'tcp', '--dport', '8082', '-j', 'DROP', '!', '-i', 'eth0'], + ['iptables', '-A', 'INPUT', '-p', 'tcp', '--dport', '8083', '-j', 'DROP', '!', '-i', 'eth0'], ], } ], @@ -152,8 +152,8 @@ "FEATURE": {}, }, "return": [ - ['iptables', '-A', 'INPUT', '-p', 'tcp', '-s', '2001::2/128', '--dport', '8081', '-j', 'ACCEPT'], - ['iptables', '-A', 'INPUT', '-p', 'tcp', '--dport', '8081', '-j', 'DROP'] + ['iptables', '-A', 'INPUT', '-p', 'tcp', '-s', '2001::2/128', '--dport', '8081', '-j', 'ACCEPT', '!', '-i', 'eth0'], + ['iptables', '-A', 'INPUT', '-p', 'tcp', '--dport', '8081', '-j', 'DROP', '!', '-i', 'eth0'] ], } ], @@ -190,12 +190,12 @@ "FEATURE": {}, }, "return": [ - ['iptables', '-A', 'INPUT', '-p', 'tcp', '-s', '2001::2/128', '--dport', '8081', '-j', 'ACCEPT'], - ['iptables', '-A', 'INPUT', '-p', 'tcp', '-s', '2001::2/128', '--dport', '8082', '-j', 'ACCEPT'], - ['iptables', '-A', 'INPUT', '-p', 'tcp', '-s', '2001::2/128', '--dport', '8083', '-j', 'ACCEPT'], - ['iptables', '-A', 'INPUT', '-p', 'tcp', '--dport', '8081', '-j', 'DROP'], - ['iptables', '-A', 'INPUT', '-p', 'tcp', '--dport', '8082', '-j', 'DROP'], - ['iptables', '-A', 'INPUT', '-p', 'tcp', '--dport', '8083', '-j', 'DROP'], + ['iptables', '-A', 'INPUT', '-p', 'tcp', '-s', '2001::2/128', '--dport', '8081', '-j', 'ACCEPT', '!', '-i', 'eth0'], + ['iptables', '-A', 'INPUT', '-p', 'tcp', '-s', '2001::2/128', '--dport', '8082', '-j', 'ACCEPT', '!', '-i', 'eth0'], + ['iptables', '-A', 'INPUT', '-p', 'tcp', '-s', '2001::2/128', '--dport', '8083', '-j', 'ACCEPT', '!', '-i', 'eth0'], + ['iptables', '-A', 'INPUT', '-p', 'tcp', '--dport', '8081', '-j', 'DROP', '!', '-i', 'eth0'], + ['iptables', '-A', 'INPUT', '-p', 'tcp', '--dport', '8082', '-j', 'DROP', '!', '-i', 'eth0'], + ['iptables', '-A', 'INPUT', '-p', 'tcp', '--dport', '8083', '-j', 'DROP', '!', '-i', 'eth0'], ], } ] diff --git a/tests/caclmgrd/test_vxlan_vectors.py b/tests/caclmgrd/test_vxlan_vectors.py index 71ef5877..85960f7d 100644 --- a/tests/caclmgrd/test_vxlan_vectors.py +++ b/tests/caclmgrd/test_vxlan_vectors.py @@ -24,9 +24,9 @@ }, "input" : [("src_ip", "10.1.1.1")], "expected_add_subprocess_calls": [ - call(['iptables', '-I', 'INPUT', '2', '-p', 'udp', '-d', '10.1.1.1', '--dport', '4789', '-j', 'ACCEPT'], universal_newlines=True, stdout=subprocess.PIPE)], + call(['iptables', '-I', 'INPUT', '2', '-p', 'udp', '-d', '10.1.1.1', '--dport', '4789', '-j', 'ACCEPT', '!', '-i', 'eth0'], universal_newlines=True, stdout=subprocess.PIPE)], "expected_del_subprocess_calls": [ - call(['iptables', '-D', 'INPUT', '-p', 'udp', '-d', '10.1.1.1', '--dport', '4789', '-j', 'ACCEPT'], universal_newlines=True, stdout=subprocess.PIPE) + call(['iptables', '-D', 'INPUT', '-p', 'udp', '-d', '10.1.1.1', '--dport', '4789', '-j', 'ACCEPT', '!', '-i', 'eth0'], universal_newlines=True, stdout=subprocess.PIPE) ], "popen_attributes": { 'communicate.return_value': ('output', 'error'), @@ -53,9 +53,9 @@ }, "input" : [("src_ip", "2001::1")], "expected_add_subprocess_calls": [ - call(['ip6tables', '-I', 'INPUT', '2', '-p', 'udp', '-d', '2001::1', '--dport', '4789', '-j', 'ACCEPT'], universal_newlines=True, stdout=subprocess.PIPE)], + call(['ip6tables', '-I', 'INPUT', '2', '-p', 'udp', '-d', '2001::1', '--dport', '4789', '-j', 'ACCEPT', '!', '-i', 'eth0'], universal_newlines=True, stdout=subprocess.PIPE)], "expected_del_subprocess_calls": [ - call(['ip6tables', '-D', 'INPUT', '-p', 'udp', '-d', '2001::1', '--dport', '4789', '-j', 'ACCEPT'], universal_newlines=True, stdout=subprocess.PIPE) + call(['ip6tables', '-D', 'INPUT', '-p', 'udp', '-d', '2001::1', '--dport', '4789', '-j', 'ACCEPT', '!', '-i', 'eth0'], universal_newlines=True, stdout=subprocess.PIPE) ], "popen_attributes": { 'communicate.return_value': ('output', 'error'),