IP_VER_TAG = {IPV4: 'v4',
IPV6: 'v6'}
+INTERNAL_DEV_PREFIX = 'qr-'
+SNAT_INT_DEV_PREFIX = 'sg-'
+ROUTER_2_FIP_DEV_PREFIX = 'rfp-'
+
class IptablesFwaasDriver(fwaas_base.FwaasDriverBase):
"""IPTables driver for Firewall As A Service."""
def __init__(self):
LOG.debug(_("Initializing fwaas iptables driver"))
- def create_firewall(self, apply_list, firewall):
+ def create_firewall(self, agent_mode, apply_list, firewall):
LOG.debug(_('Creating firewall %(fw_id)s for tenant %(tid)s)'),
{'fw_id': firewall['id'], 'tid': firewall['tenant_id']})
try:
if firewall['admin_state_up']:
- self._setup_firewall(apply_list, firewall)
+ self._setup_firewall(agent_mode, apply_list, firewall)
else:
- self.apply_default_policy(apply_list, firewall)
+ self.apply_default_policy(agent_mode, apply_list, firewall)
except (LookupError, RuntimeError):
# catch known library exceptions and raise Fwaas generic exception
LOG.exception(_("Failed to create firewall: %s"), firewall['id'])
raise fw_ext.FirewallInternalDriverError(driver=FWAAS_DRIVER_NAME)
- def delete_firewall(self, apply_list, firewall):
+ def _get_ipt_mgrs_with_if_prefix(self, agent_mode, router_info):
+ """Gets the iptables manager along with the if prefix to apply rules.
+
+ With DVR we can have differing namespaces depending on which agent
+ (on Network or Compute node). Also, there is an associated i/f for
+ each namespace. The iptables on the relevant namespace and matching
+ i/f are provided. On the Network node we could have both the snat
+ namespace and a fip so this is provided back as a list - so in that
+ scenario rules can be applied on both.
+ """
+ if not router_info.router['distributed']:
+ return [{'ipt': router_info.iptables_manager,
+ 'if_prefix': INTERNAL_DEV_PREFIX}]
+ ipt_mgrs = []
+ # TODO(sridar): refactor to get strings to a common location.
+ if agent_mode == 'dvr_snat':
+ if router_info.snat_iptables_manager:
+ ipt_mgrs.append({'ipt': router_info.snat_iptables_manager,
+ 'if_prefix': SNAT_INT_DEV_PREFIX})
+ if router_info.dist_fip_count:
+ # handle the fip case on n/w or compute node.
+ ipt_mgrs.append({'ipt': router_info.iptables_manager,
+ 'if_prefix': ROUTER_2_FIP_DEV_PREFIX})
+ return ipt_mgrs
+
+ def delete_firewall(self, agent_mode, apply_list, firewall):
LOG.debug(_('Deleting firewall %(fw_id)s for tenant %(tid)s)'),
{'fw_id': firewall['id'], 'tid': firewall['tenant_id']})
fwid = firewall['id']
try:
for router_info in apply_list:
- ipt_mgr = router_info.iptables_manager
- self._remove_chains(fwid, ipt_mgr)
- self._remove_default_chains(ipt_mgr)
- # apply the changes immediately (no defer in firewall path)
- ipt_mgr.defer_apply_off()
+ ipt_if_prefix_list = self._get_ipt_mgrs_with_if_prefix(
+ agent_mode, router_info)
+ for ipt_if_prefix in ipt_if_prefix_list:
+ ipt_mgr = ipt_if_prefix['ipt']
+ self._remove_chains(fwid, ipt_mgr)
+ self._remove_default_chains(ipt_mgr)
+ # apply the changes immediately (no defer in firewall path)
+ ipt_mgr.defer_apply_off()
except (LookupError, RuntimeError):
# catch known library exceptions and raise Fwaas generic exception
LOG.exception(_("Failed to delete firewall: %s"), fwid)
raise fw_ext.FirewallInternalDriverError(driver=FWAAS_DRIVER_NAME)
- def update_firewall(self, apply_list, firewall):
+ def update_firewall(self, agent_mode, apply_list, firewall):
LOG.debug(_('Updating firewall %(fw_id)s for tenant %(tid)s)'),
{'fw_id': firewall['id'], 'tid': firewall['tenant_id']})
try:
if firewall['admin_state_up']:
- self._setup_firewall(apply_list, firewall)
+ self._setup_firewall(agent_mode, apply_list, firewall)
else:
- self.apply_default_policy(apply_list, firewall)
+ self.apply_default_policy(agent_mode, apply_list, firewall)
except (LookupError, RuntimeError):
# catch known library exceptions and raise Fwaas generic exception
LOG.exception(_("Failed to update firewall: %s"), firewall['id'])
raise fw_ext.FirewallInternalDriverError(driver=FWAAS_DRIVER_NAME)
- def apply_default_policy(self, apply_list, firewall):
+ def apply_default_policy(self, agent_mode, apply_list, firewall):
LOG.debug(_('Applying firewall %(fw_id)s for tenant %(tid)s)'),
{'fw_id': firewall['id'], 'tid': firewall['tenant_id']})
fwid = firewall['id']
try:
for router_info in apply_list:
- ipt_mgr = router_info.iptables_manager
-
- # the following only updates local memory; no hole in FW
- self._remove_chains(fwid, ipt_mgr)
- self._remove_default_chains(ipt_mgr)
-
- # create default 'DROP ALL' policy chain
- self._add_default_policy_chain_v4v6(ipt_mgr)
- self._enable_policy_chain(fwid, ipt_mgr)
-
- # apply the changes immediately (no defer in firewall path)
- ipt_mgr.defer_apply_off()
+ ipt_if_prefix_list = self._get_ipt_mgrs_with_if_prefix(
+ agent_mode, router_info)
+ for ipt_if_prefix in ipt_if_prefix_list:
+ # the following only updates local memory; no hole in FW
+ ipt_mgr = ipt_if_prefix['ipt']
+ self._remove_chains(fwid, ipt_mgr)
+ self._remove_default_chains(ipt_mgr)
+
+ # create default 'DROP ALL' policy chain
+ self._add_default_policy_chain_v4v6(ipt_mgr)
+ self._enable_policy_chain(fwid, ipt_if_prefix)
+
+ # apply the changes immediately (no defer in firewall path)
+ ipt_mgr.defer_apply_off()
except (LookupError, RuntimeError):
# catch known library exceptions and raise Fwaas generic exception
LOG.exception(_("Failed to apply default policy on firewall: %s"),
fwid)
raise fw_ext.FirewallInternalDriverError(driver=FWAAS_DRIVER_NAME)
- def _setup_firewall(self, apply_list, firewall):
+ def _setup_firewall(self, agent_mode, apply_list, firewall):
fwid = firewall['id']
for router_info in apply_list:
- ipt_mgr = router_info.iptables_manager
-
- # the following only updates local memory; no hole in FW
- self._remove_chains(fwid, ipt_mgr)
- self._remove_default_chains(ipt_mgr)
+ ipt_if_prefix_list = self._get_ipt_mgrs_with_if_prefix(
+ agent_mode, router_info)
+ for ipt_if_prefix in ipt_if_prefix_list:
+ ipt_mgr = ipt_if_prefix['ipt']
+ # the following only updates local memory; no hole in FW
+ self._remove_chains(fwid, ipt_mgr)
+ self._remove_default_chains(ipt_mgr)
- # create default 'DROP ALL' policy chain
- self._add_default_policy_chain_v4v6(ipt_mgr)
- #create chain based on configured policy
- self._setup_chains(firewall, ipt_mgr)
+ # create default 'DROP ALL' policy chain
+ self._add_default_policy_chain_v4v6(ipt_mgr)
+ #create chain based on configured policy
+ self._setup_chains(firewall, ipt_if_prefix)
- # apply the changes immediately (no defer in firewall path)
- ipt_mgr.defer_apply_off()
+ # apply the changes immediately (no defer in firewall path)
+ ipt_mgr.defer_apply_off()
def _get_chain_name(self, fwid, ver, direction):
return '%s%s%s' % (CHAIN_NAME_PREFIX[direction],
IP_VER_TAG[ver],
fwid)
- def _setup_chains(self, firewall, ipt_mgr):
+ def _setup_chains(self, firewall, ipt_if_prefix):
"""Create Fwaas chain using the rules in the policy
"""
fw_rules_list = firewall['firewall_rule_list']
fwid = firewall['id']
+ ipt_mgr = ipt_if_prefix['ipt']
#default rules for invalid packets and established sessions
invalid_rule = self._drop_invalid_packets_rule()
ochain_name = self._get_chain_name(fwid, ver, EGRESS_DIRECTION)
table.add_rule(ichain_name, iptbl_rule)
table.add_rule(ochain_name, iptbl_rule)
- self._enable_policy_chain(fwid, ipt_mgr)
+ self._enable_policy_chain(fwid, ipt_if_prefix)
def _remove_default_chains(self, nsid):
"""Remove fwaas default policy chain."""
for rule in rules:
table.add_rule(chain_name, rule)
- def _enable_policy_chain(self, fwid, ipt_mgr):
+ def _enable_policy_chain(self, fwid, ipt_if_prefix):
bname = iptables_manager.binary_name
+ ipt_mgr = ipt_if_prefix['ipt']
+ if_prefix = ipt_if_prefix['if_prefix']
for (ver, tbl) in [(IPV4, ipt_mgr.ipv4['filter']),
(IPV6, ipt_mgr.ipv6['filter'])]:
chain_name = self._get_chain_name(fwid, ver, direction)
chain_name = iptables_manager.get_chain_name(chain_name)
if chain_name in tbl.chains:
- jump_rule = ['%s qr-+ -j %s-%s' % (IPTABLES_DIR[direction],
- bname, chain_name)]
- self._add_rules_to_chain(ipt_mgr, ver, 'FORWARD',
- jump_rule)
+ jump_rule = ['%s %s+ -j %s-%s' % (IPTABLES_DIR[direction],
+ if_prefix, bname, chain_name)]
+ self._add_rules_to_chain(ipt_mgr,
+ ver, 'FORWARD', jump_rule)
#jump to DROP_ALL policy
chain_name = iptables_manager.get_chain_name(FWAAS_DEFAULT_CHAIN)
- jump_rule = ['-o qr-+ -j %s-%s' % (bname, chain_name)]
+ jump_rule = ['-o %s+ -j %s-%s' % (if_prefix, bname, chain_name)]
self._add_rules_to_chain(ipt_mgr, IPV4, 'FORWARD', jump_rule)
self._add_rules_to_chain(ipt_mgr, IPV6, 'FORWARD', jump_rule)
#jump to DROP_ALL policy
chain_name = iptables_manager.get_chain_name(FWAAS_DEFAULT_CHAIN)
- jump_rule = ['-i qr-+ -j %s-%s' % (bname, chain_name)]
+ jump_rule = ['-i %s+ -j %s-%s' % (if_prefix, bname, chain_name)]
self._add_rules_to_chain(ipt_mgr, IPV4, 'FORWARD', jump_rule)
self._add_rules_to_chain(ipt_mgr, IPV6, 'FORWARD', jump_rule)
'firewall_rule_list': rule_list}
return fw_inst
- def _fake_apply_list(self, router_count=1):
+ def _fake_apply_list(self, router_count=1, distributed=False,
+ distributed_mode=None):
apply_list = []
while router_count > 0:
iptables_inst = mock.Mock()
+ router_inst = {'distributed': distributed}
v4filter_inst = mock.Mock()
v6filter_inst = mock.Mock()
v4filter_inst.chains = []
iptables_inst.ipv6 = {'filter': v6filter_inst}
router_info_inst = mock.Mock()
router_info_inst.iptables_manager = iptables_inst
+ router_info_inst.snat_iptables_manager = iptables_inst
+ if distributed_mode == 'dvr':
+ router_info_inst.dist_fip_count = 1
+ router_info_inst.router = router_inst
apply_list.append(router_info_inst)
router_count -= 1
return apply_list
- def _setup_firewall_with_rules(self, func, router_count=1):
- apply_list = self._fake_apply_list(router_count=router_count)
+ def _setup_firewall_with_rules(self, func, router_count=1,
+ distributed=False, distributed_mode=None):
+ apply_list = self._fake_apply_list(router_count=router_count,
+ distributed=distributed, distributed_mode=distributed_mode)
rule_list = self._fake_rules_v4(FAKE_FW_ID, apply_list)
firewall = self._fake_firewall(rule_list)
- func(apply_list, firewall)
+ if distributed:
+ if distributed_mode == 'dvr_snat':
+ if_prefix = 'sg-+'
+ if distributed_mode == 'dvr':
+ if_prefix = 'rfp-+'
+ else:
+ if_prefix = 'qr-+'
+ distributed_mode = 'legacy'
+ func(distributed_mode, apply_list, firewall)
invalid_rule = '-m state --state INVALID -j DROP'
est_rule = '-m state --state ESTABLISHED,RELATED -j ACCEPT'
rule1 = '-p tcp --dport 80 -s 10.24.4.2 -j ACCEPT'
mock.call.add_rule(ingress_chain, rule2),
mock.call.add_rule(egress_chain, rule2),
mock.call.add_rule('FORWARD',
- '-o qr-+ -j %s' % ipt_mgr_ichain),
+ '-o %s -j %s' % (if_prefix,
+ ipt_mgr_ichain)),
mock.call.add_rule('FORWARD',
- '-i qr-+ -j %s' % ipt_mgr_echain),
+ '-i %s -j %s' % (if_prefix,
+ ipt_mgr_echain)),
mock.call.add_rule('FORWARD',
- '-o qr-+ -j %s-fwaas-defau' % bname),
+ '-o %s -j %s-fwaas-defau' % (if_prefix,
+ bname)),
mock.call.add_rule('FORWARD',
- '-i qr-+ -j %s-fwaas-defau' % bname)]
+ '-i %s -j %s-fwaas-defau' % (if_prefix,
+ bname))]
v4filter_inst.assert_has_calls(calls)
def test_create_firewall_no_rules(self):
apply_list = self._fake_apply_list()
firewall = self._fake_firewall_no_rule()
- self.firewall.create_firewall(apply_list, firewall)
+ self.firewall.create_firewall('legacy', apply_list, firewall)
invalid_rule = '-m state --state INVALID -j DROP'
est_rule = '-m state --state ESTABLISHED,RELATED -j ACCEPT'
bname = fwaas.iptables_manager.binary_name
def test_delete_firewall(self):
apply_list = self._fake_apply_list()
firewall = self._fake_firewall_no_rule()
- self.firewall.delete_firewall(apply_list, firewall)
+ self.firewall.delete_firewall('legacy', apply_list, firewall)
ingress_chain = 'iv4%s' % firewall['id']
egress_chain = 'ov4%s' % firewall['id']
calls = [mock.call.ensure_remove_chain(ingress_chain),
apply_list = self._fake_apply_list()
rule_list = self._fake_rules_v4(FAKE_FW_ID, apply_list)
firewall = self._fake_firewall_with_admin_down(rule_list)
- self.firewall.create_firewall(apply_list, firewall)
+ self.firewall.create_firewall('legacy', apply_list, firewall)
calls = [mock.call.ensure_remove_chain('iv4fake-fw-uuid'),
mock.call.ensure_remove_chain('ov4fake-fw-uuid'),
mock.call.ensure_remove_chain('fwaas-default-policy'),
mock.call.add_chain('fwaas-default-policy'),
mock.call.add_rule('fwaas-default-policy', '-j DROP')]
apply_list[0].iptables_manager.ipv4['filter'].assert_has_calls(calls)
+
+ def test_create_firewall_with_rules_dvr_snat(self):
+ self._setup_firewall_with_rules(self.firewall.create_firewall,
+ distributed=True, distributed_mode='dvr_snat')
+
+ def test_update_firewall_with_rules_dvr_snat(self):
+ self._setup_firewall_with_rules(self.firewall.update_firewall,
+ distributed=True, distributed_mode='dvr_snat')
+
+ def test_create_firewall_with_rules_dvr(self):
+ self._setup_firewall_with_rules(self.firewall.create_firewall,
+ distributed=True, distributed_mode='dvr')
+
+ def test_update_firewall_with_rules_dvr(self):
+ self._setup_firewall_with_rules(self.firewall.update_firewall,
+ distributed=True, distributed_mode='dvr')