From d38f76e68a814d99597bebb9bc60ce8a76ee4af7 Mon Sep 17 00:00:00 2001 From: Nguyen Phuong An Date: Mon, 11 Jun 2018 10:45:10 +0700 Subject: [PATCH] Introduce accepted/dropped/rejected chains for future processing This patch introduces new neutron-l3-agent-accepted/dropped/rejected chains. These chains are used for future processing like Firewall logging. Co-Authored-By: Kim Bao Long Partial-Bug: #1720727 Change-Id: Iecc5f3a9e32c7b17848e2ed89d9bcbd85900ed5a --- .../agents/drivers/linux/iptables_fwaas_v2.py | 83 +++++++++++++++++-- .../drivers/linux/test_iptables_fwaas_v2.py | 40 +++++---- 2 files changed, 101 insertions(+), 22 deletions(-) diff --git a/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/iptables_fwaas_v2.py b/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/iptables_fwaas_v2.py index 4f2bf578c..d7b85f17a 100644 --- a/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/iptables_fwaas_v2.py +++ b/neutron_fwaas/services/firewall/service_drivers/agents/drivers/linux/iptables_fwaas_v2.py @@ -28,9 +28,16 @@ LOG = logging.getLogger(__name__) FWAAS_DRIVER_NAME = 'Fwaas iptables driver' FWAAS_DEFAULT_CHAIN = 'fwaas-default-policy' -FWAAS_TO_IPTABLE_ACTION_MAP = {'allow': 'ACCEPT', - 'deny': 'DROP', - 'reject': 'REJECT'} +# Introduce these chain for future processing like firewall logging +ACCEPTED_CHAIN = 'accepted' +DROPPED_CHAIN = 'dropped' +REJECTED_CHAIN = 'rejected' + +FWAAS_TO_IPTABLE_ACTION_MAP = { + 'allow': ACCEPTED_CHAIN, + 'deny': DROPPED_CHAIN, + 'reject': REJECTED_CHAIN +} CHAIN_NAME_PREFIX = {constants.INGRESS_DIRECTION: 'i', constants.EGRESS_DIRECTION: 'o'} @@ -160,6 +167,11 @@ class IptablesFwaasDriver(fwaas_base_v2.FwaasDriverBase): self._remove_chains(fwid, ipt_mgr) self._remove_default_chains(ipt_mgr) + # Create accepted/dropped/rejected chain + self._add_accepted_chain_v4v6(ipt_mgr) + self._add_dropped_chain_v4v6(ipt_mgr) + self._add_rejected_chain_v4v6(ipt_mgr) + # create default 'DROP ALL' policy chain self._add_default_policy_chain_v4v6(ipt_mgr) self._enable_policy_chain(fwid, ipt_if_prefix, @@ -184,6 +196,11 @@ class IptablesFwaasDriver(fwaas_base_v2.FwaasDriverBase): self._remove_chains(fwid, ipt_mgr) self._remove_default_chains(ipt_mgr) + # Create accepted/dropped/rejected chain + self._add_accepted_chain_v4v6(ipt_mgr) + self._add_dropped_chain_v4v6(ipt_mgr) + self._add_rejected_chain_v4v6(ipt_mgr) + # create default 'DROP ALL' policy chain self._add_default_policy_chain_v4v6(ipt_mgr) # create chain based on configured policy @@ -323,10 +340,52 @@ class IptablesFwaasDriver(fwaas_base_v2.FwaasDriverBase): self._remove_chain_by_name(ver, chain_name, ipt_mgr) def _add_default_policy_chain_v4v6(self, ipt_mgr): + dropped_chain = self._get_action_chain(DROPPED_CHAIN) ipt_mgr.ipv4['filter'].add_chain(FWAAS_DEFAULT_CHAIN) - ipt_mgr.ipv4['filter'].add_rule(FWAAS_DEFAULT_CHAIN, '-j DROP') + ipt_mgr.ipv4['filter'].add_rule( + FWAAS_DEFAULT_CHAIN, '-j %s' % dropped_chain) ipt_mgr.ipv6['filter'].add_chain(FWAAS_DEFAULT_CHAIN) - ipt_mgr.ipv6['filter'].add_rule(FWAAS_DEFAULT_CHAIN, '-j DROP') + ipt_mgr.ipv6['filter'].add_rule( + FWAAS_DEFAULT_CHAIN, '-j %s' % dropped_chain) + + def _add_accepted_chain_v4v6(self, ipt_mgr): + v4rules_in_chain = \ + ipt_mgr.get_chain("filter", ACCEPTED_CHAIN, ip_version=4) + if not v4rules_in_chain: + ipt_mgr.ipv4['filter'].add_chain(ACCEPTED_CHAIN) + ipt_mgr.ipv4['filter'].add_rule(ACCEPTED_CHAIN, '-j ACCEPT') + + v6rules_in_chain = \ + ipt_mgr.get_chain("filter", ACCEPTED_CHAIN, ip_version=6) + if not v6rules_in_chain: + ipt_mgr.ipv6['filter'].add_chain(ACCEPTED_CHAIN) + ipt_mgr.ipv6['filter'].add_rule(ACCEPTED_CHAIN, '-j ACCEPT') + + def _add_dropped_chain_v4v6(self, ipt_mgr): + v4rules_in_chain = \ + ipt_mgr.get_chain("filter", DROPPED_CHAIN, ip_version=4) + if not v4rules_in_chain: + ipt_mgr.ipv4['filter'].add_chain(DROPPED_CHAIN) + ipt_mgr.ipv4['filter'].add_rule(DROPPED_CHAIN, '-j DROP') + + v6rules_in_chain = \ + ipt_mgr.get_chain("filter", DROPPED_CHAIN, ip_version=6) + if not v6rules_in_chain: + ipt_mgr.ipv6['filter'].add_chain(DROPPED_CHAIN) + ipt_mgr.ipv6['filter'].add_rule(DROPPED_CHAIN, '-j DROP') + + def _add_rejected_chain_v4v6(self, ipt_mgr): + v4rules_in_chain = \ + ipt_mgr.get_chain("filter", REJECTED_CHAIN, ip_version=4) + if not v4rules_in_chain: + ipt_mgr.ipv4['filter'].add_chain(REJECTED_CHAIN) + ipt_mgr.ipv4['filter'].add_rule(REJECTED_CHAIN, '-j REJECT') + + v6rules_in_chain = \ + ipt_mgr.get_chain("filter", REJECTED_CHAIN, ip_version=6) + if not v6rules_in_chain: + ipt_mgr.ipv6['filter'].add_chain(REJECTED_CHAIN) + ipt_mgr.ipv6['filter'].add_rule(REJECTED_CHAIN, '-j REJECT') def _remove_chain_by_name(self, ver, chain_name, ipt_mgr): if ver == IPV4: @@ -334,6 +393,10 @@ class IptablesFwaasDriver(fwaas_base_v2.FwaasDriverBase): else: ipt_mgr.ipv6['filter'].remove_chain(chain_name) + def _remove_chain_by_name_v4v6(self, chain_name, ipt_mgr): + ipt_mgr.ipv4['filter'].remove_chain(chain_name) + ipt_mgr.ipv6['filter'].remove_chain(chain_name) + def _add_rules_to_chain(self, ipt_mgr, ver, chain_name, rules): if ver == IPV4: table = ipt_mgr.ipv4['filter'] @@ -342,6 +405,11 @@ class IptablesFwaasDriver(fwaas_base_v2.FwaasDriverBase): for rule in rules: table.add_rule(chain_name, rule) + def _get_action_chain(self, name): + binary_name = iptables_manager.binary_name + chain_name = iptables_manager.get_chain_name(name) + return '%s-%s' % (binary_name, chain_name) + def _enable_policy_chain(self, fwid, ipt_if_prefix, router_fw_ports): bname = iptables_manager.binary_name ipt_mgr = ipt_if_prefix['ipt'] @@ -414,7 +482,8 @@ class IptablesFwaasDriver(fwaas_base_v2.FwaasDriverBase): return iptables_rule def _drop_invalid_packets_rule(self): - return '-m state --state INVALID -j DROP' + dropped_chain = self._get_action_chain(DROPPED_CHAIN) + return '-m state --state INVALID -j %s' % dropped_chain def _allow_established_rule(self): return '-m state --state RELATED,ESTABLISHED -j ACCEPT' @@ -423,7 +492,7 @@ class IptablesFwaasDriver(fwaas_base_v2.FwaasDriverBase): if not action: return [] - args = ['-j', action] + args = ['-j', self._get_action_chain(action)] return args diff --git a/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/drivers/linux/test_iptables_fwaas_v2.py b/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/drivers/linux/test_iptables_fwaas_v2.py index 61caae69c..86af75ea2 100644 --- a/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/drivers/linux/test_iptables_fwaas_v2.py +++ b/neutron_fwaas/tests/unit/services/firewall/service_drivers/agents/drivers/linux/test_iptables_fwaas_v2.py @@ -149,23 +149,27 @@ class IptablesFwaasTestCase(base.BaseTestCase): if_prefix = 'qr-' distributed_mode = 'legacy' func(distributed_mode, apply_list, firewall) - invalid_rule = '-m state --state INVALID -j DROP' + binary_name = fwaas.iptables_manager.binary_name + dropped = '%s-dropped' % binary_name + accepted = '%s-accepted' % binary_name + rejected = '%s-rejected' % binary_name + invalid_rule = '-m state --state INVALID -j %s' % dropped est_rule = '-m state --state RELATED,ESTABLISHED -j ACCEPT' - rule1 = '-p tcp -s 10.24.4.2/32 -m tcp --dport 80 -j ACCEPT' - rule2 = '-p tcp -m tcp --dport 22 -j DROP' - rule3 = '-p tcp -m tcp --dport 23 -j REJECT' + rule1 = '-p tcp -s 10.24.4.2/32 -m tcp --dport 80 -j %s' % accepted + rule2 = '-p tcp -m tcp --dport 22 -j %s' % dropped + rule3 = '-p tcp -m tcp --dport 23 -j %s' % rejected ingress_chain = 'iv4%s' % firewall['id'] egress_chain = 'ov4%s' % firewall['id'] - bname = fwaas.iptables_manager.binary_name - ipt_mgr_ichain = '%s-%s' % (bname, ingress_chain[:11]) - ipt_mgr_echain = '%s-%s' % (bname, egress_chain[:11]) + ipt_mgr_ichain = '%s-%s' % (binary_name, ingress_chain[:11]) + ipt_mgr_echain = '%s-%s' % (binary_name, egress_chain[:11]) for router_info_inst, port_ids in apply_list: v4filter_inst = router_info_inst.iptables_manager.ipv4['filter'] calls = [mock.call.remove_chain('iv4fake-fw-uuid'), mock.call.remove_chain('ov4fake-fw-uuid'), mock.call.remove_chain('fwaas-default-policy'), mock.call.add_chain('fwaas-default-policy'), - mock.call.add_rule('fwaas-default-policy', '-j DROP'), + mock.call.add_rule( + 'fwaas-default-policy', '-j %s' % dropped), mock.call.add_chain(ingress_chain), mock.call.add_rule(ingress_chain, invalid_rule), mock.call.add_rule(ingress_chain, est_rule), @@ -177,7 +181,8 @@ class IptablesFwaasTestCase(base.BaseTestCase): mock.call.add_rule(ingress_chain, rule3), mock.call.add_rule(egress_chain, rule1), mock.call.add_rule(egress_chain, rule2), - mock.call.add_rule(egress_chain, rule3)] + mock.call.add_rule(egress_chain, rule3) + ] for port in FAKE_PORT_IDS: intf_name = self._get_intf_name(if_prefix, port) @@ -193,7 +198,7 @@ class IptablesFwaasTestCase(base.BaseTestCase): intf_name = self._get_intf_name(if_prefix, port_id) calls.append(mock.call.add_rule('FORWARD', '-%s %s -j %s-fwaas-defau' % (direction, - intf_name, bname))) + intf_name, binary_name))) v4filter_inst.assert_has_calls(calls) def test_create_firewall_group_no_rules(self): @@ -201,9 +206,10 @@ class IptablesFwaasTestCase(base.BaseTestCase): first_ri = apply_list[0][0] firewall = self._fake_firewall_no_rule() self.firewall.create_firewall_group('legacy', apply_list, firewall) - invalid_rule = '-m state --state INVALID -j DROP' + binary_name = fwaas.iptables_manager.binary_name + dropped = '%s-dropped' % binary_name + invalid_rule = '-m state --state INVALID -j %s' % dropped est_rule = '-m state --state RELATED,ESTABLISHED -j ACCEPT' - bname = fwaas.iptables_manager.binary_name for ip_version in (4, 6): ingress_chain = ('iv%s%s' % (ip_version, firewall['id'])) egress_chain = ('ov%s%s' % (ip_version, firewall['id'])) @@ -213,19 +219,21 @@ class IptablesFwaasTestCase(base.BaseTestCase): 'ov%sfake-fw-uuid' % ip_version), mock.call.remove_chain('fwaas-default-policy'), mock.call.add_chain('fwaas-default-policy'), - mock.call.add_rule('fwaas-default-policy', '-j DROP'), + mock.call.add_rule( + 'fwaas-default-policy', '-j %s' % dropped), mock.call.add_chain(ingress_chain), mock.call.add_rule(ingress_chain, invalid_rule), mock.call.add_rule(ingress_chain, est_rule), mock.call.add_chain(egress_chain), mock.call.add_rule(egress_chain, invalid_rule), mock.call.add_rule(egress_chain, est_rule)] + for port_id in FAKE_PORT_IDS: for direction in ['o', 'i']: mock.call.add_rule('FORWARD', '-%s qr-%s -j %s-fwaas-defau' % (port_id, direction, - bname)) + binary_name)) if ip_version == 4: v4filter_inst = first_ri.iptables_manager.ipv4['filter'] v4filter_inst.assert_has_calls(calls) @@ -274,12 +282,14 @@ class IptablesFwaasTestCase(base.BaseTestCase): first_ri = apply_list[0][0] rule_list = self._fake_rules_v4(FAKE_FW_ID, apply_list) firewall = self._fake_firewall_with_admin_down(rule_list) + binary_name = fwaas.iptables_manager.binary_name + dropped = '%s-dropped' % binary_name self.firewall.create_firewall_group('legacy', apply_list, firewall) calls = [mock.call.remove_chain('iv4fake-fw-uuid'), mock.call.remove_chain('ov4fake-fw-uuid'), mock.call.remove_chain('fwaas-default-policy'), mock.call.add_chain('fwaas-default-policy'), - mock.call.add_rule('fwaas-default-policy', '-j DROP')] + mock.call.add_rule('fwaas-default-policy', '-j %s' % dropped)] first_ri.iptables_manager.ipv4['filter'].assert_has_calls(calls) def test_create_firewall_group_with_rules_dvr_snat(self):