OpenStack防火墙功能实现介绍

防火墙功能介绍

OpenStack防火墙的核心是防火墙策略和防火墙规则,策略是一组防火墙规则集合,规则是由一组匹配条件(如端口范围、协议、IP地址),以及对匹配流量采取的操作(allow、deny);
策略可以设置成public,跨project使用;
防火墙的功能实现有很多方式,取决于driver的选用;例如:iptables driver使用iptables rule来实现,OVS driver使用流表,Cisco防火墙driver使用NSX设备;

OpenStack现有FWaaS v1和FWaaS v2,本文介绍v1

FWaaS v1

OpenStack Rocky版本
FWaaS v1提供针对路由的保护,当防火墙关联到一个路由上,那么所有的内部port都是受该防火墙保护的;

防火墙driver

[firewall_drivers]
iptables = neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.iptables_fwaas:IptablesFwaasDriver

创建防火墙

neutron_fwaas.services.firewall.service_drivers.agents.drivers.linux.iptables_fwaas
class IptablesFwaasDriver():
	# apply_list: router_info_list _get_router_info_list_for_tenant
	# firewall: fw_with_rules _make_firewall_dict_with_rules
	def create_firewall(self, agent_mode, apply_list, firewall):
		if firewall['admin_state_up']:
			# setup操作如下:
			# 1. 生成名称i,o(ingress, egress) + v4(ip版本) + fwid 取前11位;尝试删除对应链
			# 2. 尝试删除名为fwaas-default-policy的链
			# 3. 创建名为fwaas-default-policy的链,并加入drop all的规则
			# 4. 增加规则:增加第一步中删除的链,在每个链中(1)drop所有无效包(2)allow已建立链接的包(3)根据firewall_rule里的规则加入
			# 5. 将第4步中生成的链链接到Forward,将第3步生成的链链接到Forward
            self._setup_firewall(agent_mode, apply_list, firewall)
			# 生效            
            self._remove_conntrack_new_firewall(agent_mode,
                                                    apply_list, firewall)
            # 设置pre_firewall为当前firewall
            self.pre_firewall = dict(firewall)
        else:
        	# 如果firewall的admin_state_up为False,即只添加default DROP ALL的规则
            self.apply_default_policy(agent_mode, apply_list, firewall)

更新防火墙

更新防火墙从agent的看起

neutron_fwaas.services.firewall.service_drivers.agents.l3reference.firewall_l3_agent
class FWaaSL3AgentExtension():
	def update_firewall():
		# L320 先调用driver的删除
		self.fwaas_driver.delete_firewall(
                        self.conf.agent_mode,
                        router_info_list,
                        firewall)
        # L348 再调用driver的update
        self.fwaas_driver.update_firewall(
                        self.conf.agent_mode,
                        router_info_list,
                        firewall)
	def delete_firewall(self, agent_mode, apply_list, firewall):
	    fwid = firewall['id']
        try:
            for router_info in apply_list:
                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']
                    # 删除创建过程中3,4步骤的生成的链
                    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()
            self.pre_firewall = None

    def update_firewall(self, agent_mode, apply_list, firewall):
        try:
            if firewall['admin_state_up']:
            	# 详见创建防火墙的创建过程
                self._setup_firewall(agent_mode, apply_list, firewall)
                if self.pre_firewall:
					# 如果已有防火墙,作比较,获取需要增加和删除的规则                    
                    self._remove_conntrack_updated_firewall(agent_mode,
                                    apply_list, self.pre_firewall, firewall)
                else:
                    self._remove_conntrack_new_firewall(agent_mode,
                                                    apply_list, firewall)
            else:
                self.apply_default_policy(agent_mode, apply_list, firewall)
            # 更新当前防火墙
            self.pre_firewall = dict(firewall)
        ......

删除防火墙

在更新防火墙中已提及

其他操作

在针对防火墙的操作中,还有insert_rule和remove_rule等操作;

neutron_fwaas.services.firewall.fwaas_plugin
class FirewallPlugin():
    def insert_rule(self, context, id, rule_info):
    	# 判断防火墙是否可以更新
        self._ensure_update_firewall_policy(context, id)
        fwp = super(FirewallPlugin,
                    self).insert_rule(context, id, rule_info)
        # 调用agent做update_firewall
        self._rpc_update_firewall_policy(context, id)
        resource = 'firewall_policy.update.insert_rule'
        self._notify_firewall_updates(context, resource, rule_info)
        return fwp

    def remove_rule(self, context, id, rule_info):
        self._ensure_update_firewall_policy(context, id)
        fwp = super(FirewallPlugin,
                    self).remove_rule(context, id, rule_info)
        # 调用agent做update_firewall
        self._rpc_update_firewall_policy(context, id)
        resource = 'firewall_policy.update.remove_rule'
        self._notify_firewall_updates(context, resource, rule_info)
        return fwp

总结

防火墙工作原理是在关联router后,针对该router对应的namespace做iptables的规则添加。而且在FWaaS v1中是默认default都DROP,然后加ALLOW的规则。

后记
后续会接着介绍一下FWaaS v2的功能。


版权声明:本文为mr1jie原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
THE END
< <上一篇
下一篇>>