问题导读:
1.Nova安全组是什么?
2.Nova的是如何配置的?
3.FWaas是什么?
1. Nova 安全组
1.1 配置
节点 | 配置文件 | 配置项 | 说明 |
controller | /etc/nova/nova.conf | security_group_api = nova | 是的 nova secgroup* 命令使用的是 nova 安全组的 API |
/etc/neutron/plugins/ml2/ml2_conf.ini | enable_security_group = False | 禁止 Neutron 安全组 | |
nova-compute | /etc/nova/nova.conf /etc/nova/nova-compute.conf | firewall_driver = nova.virt.firewall.IptablesFirewallDriver | 指定 Nova 安全组的驱动,可以是IptablesFirewallDriver 或者 NWFilterFirewall。默认是 IptablesFirewallDriver。见下面的说明。 |
/etc/neutron/plugins/ml2/ml2_conf.ini | enable_security_group = False | 禁止 Neutron 安全组 | |
network | /etc/neutron/plugins/ml2/ml2_conf.ini | enable_security_group = False | 禁止 Neutron 安全组 |
nova 提供两种实现方式:使用 libvirt's nwfilter 的实现以及使用 linux iptables 的实现,默认的方式是使用 linux iptables。可以通过设置配置项 firewall_driver 的值指定。需要注意的是,即使使用 iptables,依然使用了部分 nwfilter 功能。参见
https://ask.openstack.org/en/question/19456/how-security-group-is-implemented/
- firewall_driver=nova.virt.libvirt.firewall.IptablesFirewallDriver
- firewall_driver=nova.virt.libvirt.firewall.NWFilterFirewall
1.2 CLI
[AppleScript] 纯文本查看 复制代码
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | 列表安全组: s 1 @controller : ~$ nova secgroup - list - rules novasg 1 + -------------+-----------+---------+-----------+--------------+ | IP Protocol | From Port | To Port | IP Range | Source Group | + -------------+-----------+---------+-----------+--------------+ | tcp | 22 | 22 | 0.0 . 0.0 / 0 | | + -------------+-----------+---------+-----------+--------------+ 创建一个安全组规则: s 1 @controller : ~$ nova secgroup - add - rule novasg 1 udp 53 53 100.1 . 100.0 / 24 + -------------+-----------+---------+----------------+--------------+ | IP Protocol | From Port | To Port | IP Range | Source Group | + -------------+-----------+---------+----------------+--------------+ | udp | 53 | 53 | 100.1 . 100.0 / 24 | | + -------------+-----------+---------+----------------+--------------+ 删除虚机的安全组: s 1 @controller : ~$ nova remove - secgroup 2 c 59 a 875 - bc 23 -4605 - ad 70 -5315 d 7 a 3 f 8 e 2 novasg 1 添加安全组到虚机: s 1 @controller : ~$ nova add - secgroup 2 c 59 a 875 - bc 23 -4605 - ad 70 -5315 d 7 a 3 f 8 e 2 novasg 1 创建第二个安全组: s 1 @controller : ~$ nova secgroup - add - rule novasg 2 添加规则: s 1 @controller : ~$ nova secgroup - add - rule novasg 2 icmp -1 -1 0.0 . 0.0 / 0 + -------------+-----------+---------+-----------+--------------+ | IP Protocol | From Port | To Port | IP Range | Source Group | + -------------+-----------+---------+-----------+--------------+ | icmp | -1 | -1 | 0.0 . 0.0 / 0 | | + -------------+-----------+---------+-----------+--------------+ 再添加安全组到虚机: s 1 @controller : ~$ nova add - secgroup 2 c 59 a 875 - bc 23 -4605 - ad 70 -5315 d 7 a 3 f 8 e 2 novasg 2 |
1.3 iptables 链
Nova-compute 增加了 filter 表的 INPUT,OUTPUT 和 FORWARD 链:
<ignore_js_op>
[AppleScript] 纯文本查看 复制代码
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | - N nova - compute - FORWARD - N nova - compute - INPUT - N nova - compute - OUTPUT - N nova - compute - inst -122 #每个虚机一个链,命名规则是 ”inst“-<instance 在数据库中的 id> - N nova - compute - local - N nova - compute - provider - N nova - compute - sg - fallback - N nova - filter - top - A INPUT - j nova - compute - INPUT - A FORWARD - j nova - filter - top - A FORWARD - j nova - compute - FORWARD - A OUTPUT - j nova - filter - top - A OUTPUT - j nova - compute - OUTPUT - A nova - compute - FORWARD - s 0.0 . 0.0 / 32 - d 255.2 55.2 55.2 55 / 32 - p udp - m udp --sport 68 --dport 67 -j ACCEPT #允许本机上的虚机发出 DHCP 广播 - A nova - compute - INPUT - s 0.0 . 0.0 / 32 - d 255.2 55.2 55.2 55 / 32 - p udp - m udp --sport 68 --dport 67 -j ACCEPT #允许本机接受 DHCP 广播包 - A nova - compute - inst -122 - m state --state INVALID -j DROP - A nova - compute - inst -122 - m state --state RELATED,ESTABLISHED -j ACCEPT - A nova - compute - inst -122 - j nova - compute - provider - A nova - compute - inst -122 - s 91.1 . 180.2 / 32 - p udp - m udp --sport 67 --dport 68 -j ACCEPT #接受该虚机所在子网的 DHCP Server 返回的包 - A nova - compute - inst -122 - s 91.1 . 180.0 / 24 - j ACCEPT #在配置项 allow_same_net_traffic = true 的情况下接受同网段虚机的来访包 - A nova - compute - inst -122 - p tcp - m tcp --dport 22 -j ACCEPT #用户安全组规则指定的来访包 - A nova - compute - inst -122 - s 100.1 . 100.0 / 24 - p udp - m udp --dport 53 -j ACCEPT #用户安全组规则指定的来访包 - A nova - compute - inst -122 - p icmp - j ACCEPT #用户安全组规则指定的来防爆 - A nova - compute - inst -122 - j nova - compute - sg - fallback #没被上面规则处理的其它来访包 - A nova - compute - local - d 91.1 . 180.1 4 / 32 - j nova - compute - inst -122 # “-d“ 决定了 nova 安全组只检查进入虚机的网络包 - A nova - compute - sg - fallback - j DROP #丢弃其它包,只允许上述规则指定的网络访问 - A nova - filter - top - j nova - compute - local |
2. FWaas
2.1 概念
从 Havana 版本开始,Neutron 提供一种基于 Neutron L3 Agent 的一种网络四层防火墙虚拟化参考实现 Firewall-as-a-service,简称 FWaas。本文的分析是基于 OpenStack Juno 版本进行的。Juno 版本中,FWaas 是分租户的,但是可以在多个租户之间共享。每个租户只允许一个防火墙。与物理的防火墙类似,FWaas 也有三个主要概念:
(1)规则(Rule):允许用户指定所要匹配的名称,描述,针对的协议(TCP, UDP, ICMP, ANY),行为(Allow,Deny),源/目的 IP 地址/子网 和 端口号/端口号区间。
<ignore_js_op>
与 neutron 安全组中的规则的区别是,这里需要指定被匹配到的数据包的处理行为是通过(ALLOW)和不通过(DENY),但是不能指定网络方向。FWaas 会将规则同时应用到进出网络的网络包上。
(2)策略(Policy):规则的逻辑集合。Policy 可以是共享的 和 被审计的(Audited)。目前,FWaas 只是把 “audited” 保存到 DB 中,并没有对它做任何处理。
<ignore_js_op>
(3)防火墙(Firewall):策略的逻辑集合。见上面右图。Juno 版本中,每个租户只能拥有最多一个 Firewall。防火墙可以是共享的。
这里需要说明的是 FWaas 和 Security Group (安全组) 的区别。安全组规则在连接到一个实例的计算节点上的Linux桥 qbr 上实施,FWaaS 创建的防火墙规则在租户网络边缘实现的虚拟路由器上实施。 FWaaS 并不旨在取代安全组的功能,并且它提供更为补充安全组,特别是在其当前实现状态下。 FWaaS 目前缺乏安全组提供的一些功能,包括无法指定通信的方向等。与此相反,安全组,也因为他们缺乏创建特定规则拒绝所有流量的能力,因此需要 FWaas 作为补充。
2.2 配置
节点 | 配置和操作 |
控制节点上 | 修改 /etc/neutron/neutron.conf: [default] service_plugins = router,lbaas,firewall [service_providers] service_provider = FIREWALL:Iptables:neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver:default service neutron-server restart 修改 /usr/share/openstack-dashboard/openstack_dashboard/local/local_settings.py:'enable_firewall': True |
网络节点上 | 修改 /etc/neutron/fwaas_driver.ini: [fwaas] driver = neutron.services.firewall.drivers.linux.iptables_fwaas.IptablesFwaasDriver enabled = True service neutron-l3-agent restart |
2.3 实现
目前的实现中,FWaas 是通过在其所在 tenant 中的所有 Virtual Router 上添加 iptbales 规则来实现对进出数据网络的网络包进行控制的。
代码实现:
控制节点上(class FirewallPlugin):
(1)create rule:纯数据库操作,将 rule 保存到数据中。
(2)create policy:纯数据库操作,将 policy 保存到数据中。
(3)如果将 rule 添加到一个已经添加到 firwall 的 policy,或者将一个 policy 加入一个存在的 firewall,在数据库操作后,通过 RPC fanout 到所有的 L3 Agent host:
{'args': {'firewall': {'status': 'PENDING_UPDATE', 'name': u'fw-for-tcp', 'shared': None, 'firewall_policy_id': u'd14e23a3-2ee6-411d-b678-e6db3dac45f5', 'tenant_id': u'74c8ada23a3449f888d9e19b76d13aab', 'admin_state_up': True, 'id': u'aa85bd66-dc4c-4d1b-909e-6f5736c279c7', 'firewall_rule_list': [{'protocol': u'icmp', 'description': u'', 'source_port': None, 'source_ip_address': None, 'destination_ip_address': None, 'firewall_policy_id': u'd14e23a3-2ee6-411d-b678-e6db3dac45f5', 'position': 1, 'destination_port': None, 'id': u'8658229d-6e34-4069-b091-e560f9e54dc9', 'name': u'rule-allow-icmp', 'tenant_id': u'74c8ada23a3449f888d9e19b76d13aab', 'enabled': True, 'action': u'allow', 'ip_version': 4L, 'shared': False}, {'protocol': u'tcp', 'description': u'', 'source_port': None, 'source_ip_address': None, 'destination_ip_address': None, 'firewall_policy_id': u'd14e23a3-2ee6-411d-b678-e6db3dac45f5', 'position': 2, 'destination_port': '80', 'id': u'00b5bad2-dd14-48d6-9a5c-7b65e6e8c480', 'name': u'fule-allow-tcp-80', 'tenant_id': u'74c8ada23a3449f888d9e19b76d13aab', 'enabled': True, 'action': u'allow', 'ip_version': 4L, 'shared': False}], 'description': u''}, 'host': 'controller'}, 'namespace': None, 'method': 'update_firewall'}
- insert_rule/remove_rule/update_firewall_rule/update_firewall_policy -> Firewall_db_mixin.insert_rule/remove_rule/update_firewall_rule/update_firewall_policy -> _rpc_update_firewall_policy -> _rpc_update_firewall -> (if policy has a firewall) FirewallAgentApi.update_firewall
- create_firewall -> Firewall_db_mixin.create_firewall -> FirewallAgentApi.create_firewall
- update_firewall -> Firewall_db_mixin.update_firewall -> FirewallAgentApi.update_firewall
- delete_firewall -> Firewall_db_mixin.delete_firewall -> FirewallAgentApi.delete_firewall
- FirewallAgentApi.create/update/delete_firewall -> fanout_cast ("create/update/delete_firewall", topics.L3_AGENT, "controller", firewall) -----> FWaaSL3AgentRpcCallback.create/update/delete_firewall -> FWaaSL3AgentRpcCallback._invoke_driver_for_plugin_api
网络节点上(class FWaaSL3AgentRpcCallback):
(1) 通过 RPC 获取所有的 router,在获取firewall 所在的 tenant 上的 routers
(2)调用 IptablesFwaasDriver.update_firewall,依次更新每个 router 的 iptables 规则
(3)首先删除已有规则,然后根据配置的 rules 重新生成规则
[AppleScript] 纯文本查看 复制代码
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | root@network : / var / cache # ip netns exec qrouter-e438bebe-6795-4b68-a613-ec0df38d3064 iptables -t filter -S - P INPUT ACCEPT - P FORWARD ACCEPT - P OUTPUT ACCEPT - N neutron - filter - top - N neutron - l 3 - agent - FORWARD - N neutron - l 3 - agent - INPUT - N neutron - l 3 - agent - OUTPUT - N neutron - l 3 - agent - fwaas - defau #新增的 firewall chain - N neutron - l 3 - agent - iv 4 aa 85 bd 66 #新增的 firewall chain - N neutron - l 3 - agent - local - N neutron - l 3 - agent - ov 4 aa 85 bd 66 #for firewall - A INPUT - j neutron - l 3 - agent - INPUT - A FORWARD - j neutron - filter - top - A FORWARD - j neutron - l 3 - agent - FORWARD #将 forward 转到 neutron 的chain - A OUTPUT - j neutron - filter - top - A OUTPUT - j neutron - l 3 - agent - OUTPUT - A neutron - filter - top - j neutron - l 3 - agent - local - A neutron - l 3 - agent - FORWARD - o qr - + - j neutron - l 3 - agent - iv 4 aa 85 bd 66 #进数据网络的包 - A neutron - l 3 - agent - FORWARD - i qr - + - j neutron - l 3 - agent - ov 4 aa 85 bd 66 #出数据网络的包 - A neutron - l 3 - agent - FORWARD - o qr - + - j neutron - l 3 - agent - fwaas - defau #进数据网络的包的默认处理 chain - A neutron - l 3 - agent - FORWARD - i qr - + - j neutron - l 3 - agent - fwaas - defau #出数据网络的包的默认处理 chain - A neutron - l 3 - agent - INPUT - d 127.0 . 0.1 / 32 - p tcp - m tcp --dport 9697 -j ACCEPT - A neutron - l 3 - agent - fwaas - defau - j DROP #默认丢弃没有被以上规则处理的所有包 - A neutron - l 3 - agent - iv 4 aa 85 bd 66 - m state --state INVALID -j DROP - A neutron - l 3 - agent - iv 4 aa 85 bd 66 - m state --state RELATED,ESTABLISHED -j ACCEPT #接受状态为 RELATED, ESTABLISHED (已建立的连接)的包 - A neutron - l 3 - agent - iv 4 aa 85 bd 66 - p tcp - m tcp --dport 80 -j ACCEPT #根据定义的 FWaas rule,接受目的端口为 80 的 tcp 包 - A neutron - l 3 - agent - ov 4 aa 85 bd 66 - m state --state INVALID -j DROP - A neutron - l 3 - agent - ov 4 aa 85 bd 66 - m state --state RELATED,ESTABLISHED -j ACCEPT - A neutron - l 3 - agent - ov 4 aa 85 bd 66 - p tcp - m tcp --dport 80 -j ACCEPT #根据 FWaas rule,接收目的端口为 80 的 tcp 包 |