Port Security 功能

相关链接

bp:[https://blueprints.launchpad.net/neutron/+spec/ml2-ovs-portsecurity]

code review:[https://review.openstack.org/#/q/topic:bp/ml2-ovs-portsecurity,n,z]

spec:[http://specs.openstack.org/openstack/neutron-specs/specs/kilo/ml2-ovs-portsecurity.html]

main patch:[https://review.openstack.org/#/c/126552/]

问题描述

Neutron 的安全组会向虚拟机默认添加anti-spoof的规则,这个规则将保证虚拟机只能发出/接受以它为原地址或目的地址(IP & MAC)的流量,不过注意的是anti-spoof并不能屏蔽**arp**包,因为anti-spoof是基于 iptables 的,无法识别 arp 包内的信息,社区新实现了一个基于 ovs 的 arp 识别、过滤的功能,见 Commit:aa7356b729f9672855980429677c969b6bab61a1,注意这个 Commit 的实现中考虑到了 Port Security 的影响。

上述这些功能确实有助于提高私有网络的安全性,特别是对于公有云而言,用户除非使用allowed address pair,将无法以非自己绑定的 IP、MAC 来发送或接收包,方便了云中流量的定位、debug 等。但是,对于一些应用,比如**LVS、基于虚拟机的路由器、基于虚拟机的防火墙等**,它们需要在一个**无防火墙、安全组和 anti-spoof 规则**的私有网络(虚拟网卡)下运行,特别是如果保持着 anti-spoof 规则的话,上述的应用很多都完全无法工作。

改进

Port Security 将提供一个新的属性port_security_enablednetworkport,其默认值为True,即与该 Patch 之前的行为相同,可以应用安全组、自动应用anti-spoof规则,当portport_security_enabled被设置为False时,这个port将无法设置和应用安全组,anti-spoof会被关闭,allowed address pair也将无法设置。因为这个属性与安全相关,所以只有网络的owner可以设置这个值。

当给一个网络的port_security_enabled设置为False时,这意味着该网络下建立的port都将默认应用Falseport_security_enabled

实现概述

Port Security 的 Topic 下有 5 个 Patch,此外在 Spec 中还提到另一个比较 general 的 Patch,但实际上主要的实现都在 [https://review.openstack.org/#/c/126552/] 这个 Patch 中,Commit 号为554d266f56862d4f15de104e9199e9149124efbe

因为arp spoof是在这个 Patch 之后提交的,所以其在 Patch 本身中考虑了Port Security,因此该 Patch 主要实现了“关闭”安全组和anti-spoof

其原理很简单,我们知道 Neutron 的安全组被应用在了 qbrxxx 的 Linux 网桥设备中,不同的 driver 可能有所不同,这里均已默认的neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver为例说明。

我们一共有四条 iptables 链实现 neutron 的安全组和anti-spoof

  • sg-chain:安全组的父链,内容为跳转到各个子链
  • e-xxx:过滤 egress 流量
  • i-xxx:过滤 ingress 流量
  • s-xxx:anti-spoof规则

我们只需要在父链上或者三条子链上不要设置规则,或者只设置一个 accept 即可了。

代码实现

核心 Patch 见上面的介绍,其主要的逻辑在neutron.agent.linux.iptables_firewall.IptablesFirewallDriver中实现。

首先在代码中新添加了名为unfiltered_ports的字典,用于存储port_security_enabledFalseport,正常的port还在原来的字典filtered_ports中。

然后我们简单了解一下原本security group的实现逻辑:

当更新port时,将调用SecurityGroupAgentRpcrefresh_firewall,调用到update_port_filter,再调用_set_ports来将port分类,分出来filtered_portsunfiltered_ports

然后调用到_setup_chains函数,它再调用_setup_chains_apply,调用时同时传入filtered_portsfiltered_ports,对于正常的 port,调用_setup_chain,然后调用到_add_rules_by_security_group,添加安全组和anti spoof规则。

那么对于unfiltered_ports,执行的是_add_accept_rule_port_sec,通过_update_port_sec_rules,向FORWARDINPUT链上添加 accept 规则,这样就不会添加安全组和anti-spoof规则,而且即使过去有相关规则也因为执行的顺序而被跳过去了。

(下图非标准 UML 时序图,只用做展示调用关系)

PortSecurity

Comments are closed.

Post Navigation