声明:
本博客欢迎转发,但请保留原作者信息!
新浪微博:@孔令贤HW;
博客地址:http://blog.csdn.net/lynn_kong
内容系本人学习、研究和总结,如有雷同,实属荣幸!
更新记录:
2013.06.27 增加在ovs plugin使用安全组以及在Nova使用Neutron安全组时需要的配置说明
在Grizzly版中,安全组从Nova移植到了Quantum。有几个特性:
1. 后向兼容。从F版升级到G版,仍然可以用F版Nova的API进行安全组的操作。
2. 同时支持ingress和egress(即入口和出口规则),但通过Nova API仅支持ingress规则。
3. 安全组作用于Quantum中的Port,而不再是原来Nova中的虚拟机。
4. 允许在虚拟机运行期修改安全组
5. 每个租户(tenant, 在G版的Keystone中又叫project)都有默认的安全组
安全组行为:
1. 如果没有指定ingress规则,则不允许任何数据包进入;
2. 如果没有指定egress规则,则不允许任何数据包出去;
3. 新建一个安全组时,会自动增加一条规则,允许所有的数据包出去
4. 每个租户的默认安全组,允许租户的虚拟机之间内部通信;允许租户虚拟机对外通信;不允许外界数据流进入租户的虚拟机。
1. Quantum
a. 创建一个port
b. 给port关联一个安全组
c. 如果要创建的虚拟机有多个网卡,那么可以重复a,b
d. 创建虚拟机,指定上面创建的port
e. 现在,你有了一个虚拟机,并且虚拟机上的网卡通信受安全组规则的约束
2. Nova
a. 用户要通过Nova的API创建一个虚拟机,并且为虚拟机关联安全组
b. Nova调用Quantum创建port,为port关联安全组
c. Nova使用port的信息创建虚拟机
其实,Quantum的安全组实现(在LinuxBridge和OVS上),与F版的实现基本一样,都是通过iptables。
G版中为安全组增加了两个新的资源:security_group和security_group_rule,同时为Port增加一个新的属性:security_group。为了保证兼容,在创建network、创建port、创建安全组时都会先看租户是否有默认的安全组,如果没有则新建,并且在新建的默认安全组中同时会新建两条规则:允许同一个安全组内的成员通信;允许安全组内的成员对外通信。对于租户新创建的安全组也会做同样的事情。
先来看下安全组相关的类的设计,以OVS安全组实现为例:
server端有三个主要的类:
OVSBridgePluginV2:接口业务处理
AgentNotifierApi:是plugin与agent通信的帮助类
OVSRpcCallbacks:负责处理agent的请求
而蓝色的框是上述三个类为了实现安全组功能需要继承的父类。
agent端有两个主要的类:
OVSQuantumAgent:处理server端发来的请求
OVSPluginApi:是agent与plugin通信的帮助类
同样,蓝色的框是上述两个类为了实现安全组功能需要实现的父类。SecurityGroupAgentRpcMixin是SecurityGroupAgentRpcCallbackMixin类需要调用的类,它又会调用SecurityGroupServerRpcApiMixin类向server端发送消息。
对于创建安全组以及创建安全组规则来说,server端只是在数据库中记录数据而已,不涉及与agent的通信。真正涉及plugin与agent通信的操作有以下几个:
这里要注意的是,如果指定port,同时又指定了安全组,那么只会使用port上的安全组规则,而忽略用户指定的安全组。也就是说,如果指定了安全组创建虚拟机,那么就不要指定port。
创建虚拟机,如果不指定port,那么Nova会自动调用Quantum的创建Port接口,在指定的network上(如果不指定network,则在租户的所有network上,包括共享network)创建port,同时指定安全组信息。这样Quantum在创建port时就会记录port与安全组的关联关系。同时,调用上面server端蓝色框SecurityGroupAgentRpcApiMixin类的security_groups_member_updated方法,向名为“q-agent-notifier-security_group-update”,类型为fanout的exchange上发送消息,消息的参数就是安全组标识。
所有的quantum l2 agent都会收到该消息,是在上图agent端蓝色框SecurityGroupAgentRpcCallbackMixin类中处理,该类又调用了SecurityGroupAgentRpcMixin对象进行处理。处理逻辑是这样的:如果该节点上所有port都没有引用入参中的安全组,不处理;否则,就要重新刷新本节点的iptables规则。那么,根据什么刷新呢?
其实,agent又会调用上述agent端蓝色框SecurityGroupServerRpcApiMixin对象的security_group_rules_for_devices方法,向server端获取本机ports最新的安全组规则信息,即由上述server端蓝色框SecurityGroupServerRpcCallbackMixin对象处理。
整个处理流程就是按照上图的箭头指示进行。
其实上述创建虚拟机的流程中已经包含了创建port的过程。而删除port的过程与创建port是一样的。流程图如下:
更新port与port的创建和删除走的不是一个通道。更新port走的是server与agent的port_update接口(而不是security_groups_member_updated)。而在agent端的port_update方法中,其实还是调用agent端蓝色框SecurityGroupServerRpcApiMixin对象的security_group_rules_for_devices方法更新本机的iptables规则。
当agent发现本节点有新的device出现时,也会调用agent端蓝色框SecurityGroupServerRpcApiMixin对象的security_group_rules_for_devices方法更新本机的iptables规则。流程图如下:
添加/删除安全组规则时,调用上面server端蓝色框SecurityGroupAgentRpcApiMixin类的security_groups_rule_updated方法,向名为“q-agent-notifier-security_group-update”,类型为fanout的exchange上发送消息,消息的参数就是安全组标识。agent的处理参见创建虚拟机时的处理,只是判断条件略有不同,具体请自行阅读代码。
使用ovs plugin时,要想安全组功能生效,需要在plugin的配置文件中配置:
[SECURITYGROUP] firewall_driver=quantum.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver
否则,ovs plugin不会支持security-group extension的(默认的配置是quantum.agent.firewall.NoopFirewallDriver)。
在Nova中要使用Neutron的安全组功能,也需要在nova.conf中配置:
[DEFAULT] security_group_api=quantum
同时,在Nova中要配置:firewall_driver = nova.virt.firewall.NoopFirewallDriver(默认配置:firewall_driver=nova.virt.libvirt.firewall.IptablesFirewallDriver)
使用Amazon的VPC功能,当把虚拟机加入一个VPC时,可以指定虚拟机所属的安全组(最多指定5个,注意区分安全组规则与子网规则)。如果不指定,虚拟机会关联一个默认的安全组。
简单说一下安全组规则和子网规则的区别:
安全组规则 |
Network ACL |
作用在虚拟机层面(第一层防护) |
作用在子网(subnet)层面(第二层防护) |
只能设置“允许”规则 |
支持“允许”规则和“禁止”规则 |
允许返回的数据包,无视规则 |
仅允许返回规则允许的数据包 |
在允许数据包通过之前会检测全部规则 |
在允许数据包通过之前会按顺序检测规则 |
在创建虚拟机阶段指定安全组,或在虚拟机运行时动态关联安全组 |
自动作用在子网中的虚拟机上 |
以一个图示可能会表达得更清楚:
VPC中安全组的约束:
1. 在一个VPC中可以创建最多100个安全组,每一个安全组中可以添加最多50条规则。如果你想为虚拟机添加超过50条的安全组,那么只能为虚拟机关联最多不超过5个安全组;
2. 只能指定“允许通过(allow)”的规则
3. 支持ingress和egress
4. 默认情况下,安全组不允许进入数据包
5. 默认情况下,安全组允许所有数据包出去
6. 同一个安全组中的虚拟机之间默认相互不能通信(而默认安全组除外,因为默认安全组中有相应的允许规则)
7. 虚拟机创建之后,可以动态的修改其所属的安全组
8. 每个VPC中都有一个默认的安全组,而这个默认安全组的行为是:a. 不允许外来数据包进入(本安全组内虚拟机之间通信除外);b. 允许出去的数据包;c. 安全组内虚拟机之间互通。当然,可以通过接口改变默认安全组的行为。
说了这么多,这里说的安全组是指VPC内的安全组,与普通EC2场景中使用的安全组是不同的概念,而且相互之间也不能引用。它们之间的区别:
EC2场景 |
VPC场景 |
每个用户在每一个region下可以创建最多500个安全组 |
每个用户在每个VPC中可以创建最多100个安全组 |
每个安全组最多有100条规则 |
每个安全组最多有50条规则 |
仅支持ingress规则 |
同时支持ingress和egress规则 |
虚拟机关联的安全组数目无上限 |
每个虚拟机最多关联5个安全组 |
可以引用其他帐户的安全组 |
只能引用你VPC中的安全组 |
虚拟机创建后,不能修改它的安全组 |
可动态修改 |
增加规则时,不必指定协议(协议仅支持TCP,UDP,ICMP) |
增加规则时,协议是必选的,且支持标准协议端口 |
VPC中安全组命令和API:
描述 |
命令 |
API |
创建安全组 |
ec2-create-group |
CreateSecurityGroup |
添加安全组规则 |
ec2-authorize |
AuthorizeSecurityGroupIngress |
查询安全组 |
ec2-describe-group |
DescribeSecurityGroups |
修改虚拟机所属的安全组 |
ec2-modify-instance-attribute |
ModifyInstanceAttribute |
删除安全组规则 |
ec2-revoke |
RevokeSecurityGroupIngress |
删除安全组 |
ec2-delete-group |
DeleteSecurityGroup |
在CloudStack 3.0.3 -3.0.5中,安全组只能使用在basicnetworking中,后续的版本中才能在advancednetworking中使用。其实在advancednetworking中,可以通过创建不同的guest network来达到网络隔离的目的。
租户的默认安全组的规则:1. 允许所有数据包出去;2. 不允许任何数据包进入。默认安全组的行为也可以修改。
租户创建的安全组数量无上限,安全组的规则数目无上限,虚拟机关联的安全组数量也无上限。
虚拟机关联安全组后,不能退出该安全组。
可以在虚拟机运行或停止状态修改安全组规则,即时生效。