分享

Neutron 系列 (14): Neutron 是如何实现虚机防火墙的 【下】

本帖最后由 eying 于 2016-1-13 16:57 编辑
问题导读:



1.Neutron 安全组的各部分介绍?
2.
Neutron 安全组驱动是什么?
3.Kilo 版本是如何允许 port 不使用安全组的?










3. Neutron 安全组

    我们知道,每个网桥(bridge)都有若干个端口(port)连接到它。从一个 port 进来的数据包都根据其目的 MAC 地址会被转发到其他端口,或者被丢弃。同样地,nova-compute 节点(计算节点)也充当两个角色:数据网络的转发器(bridge)(它使用 qbr bridge 将外部访问虚机的流量转发到虚机。当然了,在进入 qbr 桥之前,OVS 需要对 traffic 做一些操作)和 终端机(这个节点往往会配置多块网卡,一块用于数据网络,一块用于管理网络,这样,别的计算机通过管理网络来访问该计算机,比如配置 nova-compute 等)。跟上面例子区别的是,qbr 网桥并没有设置 IP 地址,因此需要别的网卡。而 qbr 桥是一个简单的网桥,它一头连接的是虚机网卡 eth0 的 tap 设备(比如 tap59cfa0b8-2f),另一头连接 veth pari 的一端(比如qvb59cfa0b8-2f),该 veth 设备的另一端是 OVS 上的端口 qvo59cfa0b8-2f。可见,qbr bridge 连接了虚机的网卡和 OVS 桥。使用 qbr 后,进入 qvo 的网络包都将被 qbr 转发到 tap 设备,而离开 tap 设备的网络包都将被转发到 qvo 上。 Neutron 安全组就是作用在 qbr 桥上。

1.jpg

    至于为什么不将虚机的网卡直接连接到 OVS 桥 br-int,官方说法是:“理想地,TAP 设备最好能直接挂在 br-int 上。不幸的是,因为 OpenStack Security Group 的实现方式,这种挂载是不可能实现的。OpenStack 使用 TAP 设备上的 iptables 规则来实现 Security Group,而 open vswitch 不支持在直接连到其网桥上的 TAP 设备上使用 iptables。因此,不得不增加 Linux bridge qbr 来将 TAP 设备连到 OVS bridge 上。”。简单地说,OpenStack 需要在 qbr 桥上使用 iptables 过滤进出虚机的数据包,而 br-int 上无法做到这一点。

3.1 配置

节点配置文件配置项说明
controller /etc/nova/nova.confsecurity_group_api = neutron 使得 nova secgroup* 命令使用的是
neutron 安全组的 API
/etc/neutron/plugins/ml2/ml2_conf.inienable_security_group = True
firewall_driver = neutron.agent.linux.iptables_firewall.
OVSHybridIptablesFirewallDriver
启用 Neutron 安全组并指定驱动
nova-compute /etc/nova/nova.conffirewall_driver = nova.virt.firewall.NoopFirewallDriver禁用 nova 安全组
/etc/neutron/plugins/ml2/ml2_conf.inienable_security_group = True
enable_ipset = True
firewall_driver = neutron.agent.linux.iptables_firewall.
OVSHybridIptablesFirewallDriver
启用 Neutron 安全组并指定驱动
network/etc/neutron/plugins/ml2/ml2_conf.inienable_security_group = True
enable_ipset = True
firewall_driver = neutron.agent.linux.iptables_firewall.
OVSHybridIptablesFirewallDriver
启用 Neutron 安全组并指定驱动

neutron 也提供两种安全组的实现:IptablesFirewallDriver 和 OVSHybridIptablesFirewallDriver

  • neutron.agent.linux.iptables_firewall.IptablesFirewallDriver : iptables-based FirewallDriver implementation
  • neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver: subclass of IptablesFirewallDriver with additional bridge

默认值是 neutron.agent.firewall.NoopFirewallDriver,表示不使用 neutron security group。

3.2 CLI 示例

列表 安全组:

s1@controller:~$ neutron security-group-list
+--------------------------------------+------------+-------------+
| id                                   | name       | description |
+--------------------------------------+------------+-------------+
| 0aff643b-7b34-4384-b482-f37eccef5b90 | sg-all-ssh | allow ssh   |
| c98a2a3f-1b06-429d-b419-aa862662f116 | default    | default     |
| f5377a66-803d-481b-b4c3-a6631e8ab456 | default    | default     |
+--------------------------------------+------------+-------------+

列表配置了某安全组的所有 port:

s1@controller:~$ neutron port-list -c security_groups -c id -c mac_address -c fixed_ips -c device_id | grep c98a2a3f-1b06-429d-b419-aa862662f116
| [u'c98a2a3f-1b06-429d-b419-aa862662f116'] | 29eaea66-6614-47e3-b251-0104ff9f12e2 | fa:16:3e:bc:52:eb | {"subnet_id": "d803eaa3-63c9-4c2b-834a-9780db31df70", "ip_address": "100.1.250.1"}   | 1214b1b4-7c3a-41ad-ad8e-1e520b9c2830                                          |
| [u'c98a2a3f-1b06-429d-b419-aa862662f116'] | a7e26c3e-c1ae-4c65-a0e4-2d81266a11b3 | fa:16:3e:b8:f9:ad | {"subnet_id": "4ac56c61-84f3-4d00-b87a-1ab2441e8437", "ip_address": "100.1.150.1"}   | 1214b1b4-7c3a-41ad-ad8e-1e520b9c2830

s1@controller:~$ neutron port-list -c security_groups -c id -c mac_address -c fixed_ips -c device_id | grep 29eaea66-6614-47e3-b251-0104ff9f12e2
| [u'0aff643b-7b34-4384-b482-f37eccef5b90'] | 29eaea66-6614-47e3-b251-0104ff9f12e2 | fa:16:3e:bc:52:eb | {"subnet_id": "d803eaa3-63c9-4c2b-834a-9780db31df70", "ip_address": "100.1.250.1"}   | 1214b1b4-7c3a-41ad-ad8e-1e520b9c2830                                          |


删除指定 port 的安全组:
s1@controller:~$ neutron port-update --no-security-groups 29eaea66-6614-47e3-b251-0104ff9f12e2
Updated port: 29eaea66-6614-47e3-b251-0104ff9f12e2

删除后查看:

s1@controller:~$ neutron port-list -c security_groups -c id -c mac_address -c fixed_ips -c device_id | grep 29eaea66-6614-47e3-b251-0104ff9f12e2
| []                                        | 29eaea66-6614-47e3-b251-0104ff9f12e2 | fa:16:3e:bc:52:eb | {"subnet_id": "d803eaa3-63c9-4c2b-834a-9780db31df70", "ip_address": "100.1.250.1"}   | 1214b1b4-7c3a-41ad-ad8e-1e520b9c2830                                          |


设置指定 port 的安全组:

s1@controller:~$ neutron port-update --security-group 0aff643b-7b34-4384-b482-f37eccef5b90 29eaea66-6614-47e3-b251-0104ff9f12e2              
Updated port: 29eaea66-6614-47e3-b251-0104ff9f12e2


设置后查看

s1@controller:~$ neutron port-list -c security_groups -c id -c mac_address -c fixed_ips -c device_id | grep 29eaea66-6614-47e3-b251-0104ff9f12e2
| [u'0aff643b-7b34-4384-b482-f37eccef5b90'] | 29eaea66-6614-47e3-b251-0104ff9f12e2 | fa:16:3e:bc:52:eb | {"subnet_id": "d803eaa3-63c9-4c2b-834a-9780db31df70", "ip_address": "100.1.250.1"}   | 1214b1b4-7c3a-41ad-ad8e-1e520b9c2830

3.3 Neutron 安全组驱动    

如上所述,Neutron 安全组提供两种驱动,[size=1em]OVSHybridIptablesFirewallDriver 和 IptablesFirewallDriver。不幸的是,在 Juno 版本上使用 IptablesFirewallDriver 遇到下面的 bug 而无法使用:

[mw_shl_code=applescript,true]Command: ['sudo', '/usr/bin/neutron-rootwrap', '/etc/neutron/rootwrap.conf', 'iptables-restore', '-c']
Exit code: 2
Stdout: ''
Stderr: "iptables-restore v1.4.21: interface name `406e066f-5d2a-4df9-b763-2bff230738cb' must be shorter than IFNAMSIZ (15)\nError occurred at line: 96\nTry `iptables-restore -h' or 'iptables-restore --help' for more information.\n"
2015-07-13 23:30:54.312 9389 ERROR neutron.agent.linux.iptables_manager [req-63695db6-6bdf-4ec0-8186-55218a076ab5 None] IPTablesManager.apply failed to apply the following set of iptables rules。[/mw_shl_code]

下面的分析是基于 OVSHybridIptablesFirewallDriver 的。

3.3.1 Neuron 安全组使用的 iptables 链和规则

    理论上,qbr 桥只负责在虚机和 br-int 之间转发网络帧,因此 bridge 代码应该是用 filter 表的 FORWARD 链来处理这些网络帧。但是,基于还没有被找到的原因,Neutron 还是对 filter 表的 INPUT 链进行了处理。根据上面基础知识部分的描述,只有当 qbr 承担路由器功能时(达到的网络帧的目的 MAC 是它自己但是目的 IP 地址不是它自己时)才会调用 LOCAL_IN hook,从而走到 filter 的 INPUT 链。但是很明显,目前的 Neutron 中 qbr 只是 bridge,不承担 router 任务。这篇文章 也认为大多数经过 qbr 进出虚机的网络包会被 FORWARD 链处理,还是有网络包会被 INPUT 或者 OUTPUT 链处理。幸运的是,INPUT 和 OUTPUT 链的规则和 FORWARD 链的规则完全相同。这一块还会继续摸索,有大牛知晓还请不吝告知。

    Neutron L2 Agent 承担使用 iptables 维护链和规则的任务。它为虚机的每块网卡的 tap 设备建立 i(进)、o(出) 和 s(防IP欺骗)链和规则,来实现:

  • prepares, updates, removes firewall filters (准备、更新和删除防火墙过滤器)
  • drops all packets by default (默认丢弃所有包)
  • prevents IP spoofing based on port's mac address (compatible with allowed_address_pairs extension) (防 IP 欺骗)
  • allows incoming DHCP and ICMPv6 RA (允许进入虚机的 DHCP 包和 ICMPV6 RA)
  • blocks outgoing DHCP (禁止出虚机的 DHCP 包)
  • drops INVALID packets (丢弃无效状态的包)
  • allows stateful, established connections (允许有状态的并且已建立的连接,比如允许进来的 ICMP 的时候,从外面 ping 虚机时虚机的响应包是可以返回的)
  • converts security group rules to iptables rules (IPv4, IPv6, TCP, UDP, ICMP, ICMPv6) (将用户配置的规则转化为 iptables 规则)
  • multiple TCP/UDP ports per iptables rule using multiport module
  • 支持 IPV4 和 IPV6

来看看 Neutron 为了实现这些功能添加的 iptables 链:

[mw_shl_code=applescript,true]-N neutron-filter-top
-N neutron-openvswi-FORWARD #neutorn 定义的 FORWARD 链
-N neutron-openvswi-INPUT   #Neutron 定义的 INPUT 链
-N neutron-openvswi-OUTPUT  #Neutron 定义的 OUTPUT 链
-N neutron-openvswi-i6e3f2eda-3 #处理进入该虚机的网络包
-N neutron-openvswi-local
-N neutron-openvswi-o6e3f2eda-3 #处理出该虚机的网络包
-N neutron-openvswi-s6e3f2eda-3 #处理出该虚机的网络包的防IP欺骗
-N neutron-openvswi-sg-chain   
-N neutron-openvswi-sg-fallback
-A INPUT -j neutron-openvswi-INPUT #将 INPUT 链转到 neutron 的 INPUT 链
-A FORWARD -j neutron-filter-top
-A FORWARD -j neutron-openvswi-FORWARD #将 FORWARD 链转到 neutorn 的 forward 链
-A OUTPUT -j neutron-filter-top
-A OUTPUT -j neutron-openvswi-OUTPUT   #将 OUTPUT 链转到 neutron 的 output 链
-A neutron-filter-top -j neutron-openvswi-local[/mw_shl_code]

这些链之间的关系:

2.jpg

3.3.2 当在 port 上不应用安全组时:只允许虚机访问 DHCP 服务器和 DHCP 服务器给虚机的返回包,禁止其余所有的网络访问。

     先补充两个iptabels 的知识点:

  • -j RETURN:退出当前CHIAN,如果当前CHIAN是别的CHAIN调用的子CHIAN,那么返回到调用点下一条规则处开始执行,如果当前CHIAN不是子CHAIN,那么就以默认策略执行。
  • -m state:匹配连接的状态。Linux 网络连接的状态包括:

状态说明
NEWNEW 说明这个包是我们看到的第一个包。意思就是,这是 conntrack 模块看到的某个连接第一个包,它即将被匹配了。比如,我们看到一个SYN 包,是我们所留意的连接的第一个包,就要匹配它。第一个包也可能不是SYN包,但它仍会被认为是NEW状态。这样做有时会导致一些问题,但对某些情况是有非常大的帮助的。例如,在我们想恢复某条从其他的防火墙丢失的连接时,或者某个连接已经超时,但实际上并未关闭时。
ESTABLISHED                                                ESTABLISHED 已经注意到两个方向上的数据传输,而且会继续匹配这个连接的包。处于 ESTABLISHED 状态的连接是非常容易理解的。只要发送并接到应答,连接就是ESTABLISHED的了。一个连接要从NEW变为ESTABLISHED,只需要接到应答包即可,不管这个包是发往防火墙的,还是要由防火墙转发的。ICMP的错误和重定向等信息包也被看作是ESTABLISHED,只要它们是我们所发出的信息的应答。
RELATEDRELATED 是个比较麻烦的状态。当一个连接和某个已处于 ESTABLISHED 状态的连接有关系时,就被认为是 RELATED 的了。换句话说,一个连接要想是 RELATED的,首先要有一个ESTABLISHED的连接。这个ESTABLISHED连接再产生一个主连接之外的连接,这个新的连接就是 RELATED的了,当然前提是conntrack模块要能理解RELATED。ftp是个很好的例子,FTP-data 连接就是和 FTP-control 有 RELATED 的。还有其他的例子,比如,通过IRC的DCC连接。有了这个状态,ICMP应答、FTP传输、DCC 等才能穿过防火墙正常工作。注意,大部分还有一些UDP协议都依赖这个机制。这些协议是很复杂的,它们把连接信息放在数据包里,并且要求这些信息能被正确 理解。
INVALIDINVALID说明数据包不能被识别属于哪个连接或没有任何状态。有几个原因可以产生这种情况,比如,内存溢出,收到不知属于哪个连接的ICMP 错误信息。一般地,我们DROP这个状态的任何东西。

[mw_shl_code=applescript,true]-A neutron-openvswi-FORWARD -m physdev --physdev-out tap6e3f2eda-32 --physdev-is-bridged -j neutron-openvswi-sg-chain #处理进入虚机的数据包
-A neutron-openvswi-FORWARD -m physdev --physdev-in tap6e3f2eda-32 --physdev-is-bridged -j neutron-openvswi-sg-chain  #处理出虚机的数据包
-A neutron-openvswi-INPUT -m physdev --physdev-in tap6e3f2eda-32 --physdev-is-bridged -j neutron-openvswi-o6e3f2eda-3 #处理出虚机的数据包

#处理进虚机的包
-A neutron-openvswi-i6e3f2eda-3 -m state --state INVALID -j DROP                               #丢弃无效连接
-A neutron-openvswi-i6e3f2eda-3 -m state --state RELATED,ESTABLISHED -j RETURN                 #允许已建立的连接  
-A neutron-openvswi-i6e3f2eda-3 -s 90.1.180.3/32 -p udp -m udp --sport 67 --dport 68 -j RETURN #允许 DHCP 服务器 91.1.180.3 的返回包
-A neutron-openvswi-i6e3f2eda-3 -s 91.1.180.2/32 -p udp -m udp --sport 67 --dport 68 -j RETURN #允许 DHCP 服务器 91.1.180.2 的返回包
-A neutron-openvswi-i6e3f2eda-3 -j neutron-openvswi-sg-fallback                                #其余包交给 fallback 链处理     

#处理出虚机的包
-A neutron-openvswi-o6e3f2eda-3 -p udp -m udp --sport 68 --dport 67 -j RETURN   #允许 DHCP 访问
-A neutron-openvswi-o6e3f2eda-3 -j neutron-openvswi-s6e3f2eda-3                 #防止 IP 欺骗
-A neutron-openvswi-o6e3f2eda-3 -p udp -m udp --sport 67 --dport 68 -j DROP     #不允许对外提供 DHCP 服务
-A neutron-openvswi-o6e3f2eda-3 -m state --state INVALID -j DROP                #禁止无效连接
-A neutron-openvswi-o6e3f2eda-3 -m state --state RELATED,ESTABLISHED -j RETURN  #允许已建立的连接
-A neutron-openvswi-o6e3f2eda-3 -j neutron-openvswi-sg-fallback                 #其余交给 fallback 链处理

#防 IP 欺骗规则:防止该虚机被利用来做 IP 欺骗攻击。
-A neutron-openvswi-s6e3f2eda-3 -s 91.1.180.14/32 -m mac --mac-source FA:16:3E:F3:1E:C0 -j RETURN #允许从虚机发出的MAC 和IP 同虚机的 MAC 和 IP 的包
-A neutron-openvswi-s6e3f2eda-3 -j DROP                                                           #禁止其余包

-A neutron-openvswi-sg-chain -m physdev --physdev-out tap6e3f2eda-32 --physdev-is-bridged -j neutron-openvswi-i6e3f2eda-3 #处理进入虚机的包
-A neutron-openvswi-sg-chain -m physdev --physdev-in tap6e3f2eda-32 --physdev-is-bridged -j neutron-openvswi-o6e3f2eda-3  #处理出虚机的包

-A neutron-openvswi-sg-chain -j ACCEPT
-A neutron-openvswi-sg-fallback -j DROP #丢弃其它包
复制代码[/mw_shl_code]

可见,此时,虚机的网络访问能力 = 基本网络能力(DHCP访问、允许已建立的连接、防 IP 欺骗)。也就是说虚机此时是无法网络访问和被网络访问,比如 ping,ssh 都无法连接。

3.3.3 当在 port 上应用安全组时:只允许用户规则制定的网络访问。

(1)创建如下的安全组规则

3.jpg

各条规则:

  • 允许 ping 别的机器
  • 允许别的机器 ping 它
  • 允许访问别的机器 22 端口上的 tcp 服务 (ssh)
  • 允许 别的机器访问它的80 端口上的 tcp 服务 (http)
  • 允许访问别的机器的 80 端口上的 tcp 服务 (http)
  • 允许 15.5.0.0/16 网段的机器访问它 110 端口上的 TCP 服务(pop3)
  • 允许 100.1.100.0/24 网段上的机器访问它的 53 端口上的 UDP 服务 (DNS 服务器)

(2)将安全组绑定到 port

[mw_shl_code=applescript,true]s1@controller:~$ neutron port-update --security-group  0aff643b-7b34-4384-b482-f37eccef5b90 6e3f2eda-3230-45e8-9be5-f382af5b83ea
Updated port: 6e3f2eda-3230-45e8-9be5-f382af5b83ea[/mw_shl_code]

(3)看看此时的 iptables filter 表的规则

[mw_shl_code=applescript,true]-A neutron-openvswi-FORWARD -m physdev --physdev-out tap6e3f2eda-32 --physdev-is-bridged -j neutron-openvswi-sg-chain
-A neutron-openvswi-FORWARD -m physdev --physdev-in tap6e3f2eda-32 --physdev-is-bridged -j neutron-openvswi-sg-chain
-A neutron-openvswi-INPUT -m physdev --physdev-in tap6e3f2eda-32 --physdev-is-bridged -j neutron-openvswi-o6e3f2eda-3

#适用于进入虚机的网络包
-A neutron-openvswi-i6e3f2eda-3 -m state --state INVALID -j DROP
-A neutron-openvswi-i6e3f2eda-3 -m state --state RELATED,ESTABLISHED -j RETURN
-A neutron-openvswi-i6e3f2eda-3 -s 90.1.180.3/32 -p udp -m udp --sport 67 --dport 68 -j RETURN #DHCP server 1
-A neutron-openvswi-i6e3f2eda-3 -s 91.1.180.2/32 -p udp -m udp --sport 67 --dport 68 -j RETURN #DHCP Server 2
-A neutron-openvswi-i6e3f2eda-3 -s 15.5.0.0/16 -p tcp -m tcp --dport 110 -j RETURN             #第 6 条自定义rule
-A neutron-openvswi-i6e3f2eda-3 -p tcp -m tcp --dport 80 -j RETURN                             #第 4 条自定义 rule
-A neutron-openvswi-i6e3f2eda-3 -s 100.1.100.0/24 -p udp -m udp --dport 53 -j RETURN           #第 7 条自定义 rule
-A neutron-openvswi-i6e3f2eda-3 -p icmp -j RETURN                                              #第 2 条自定义 rule
-A neutron-openvswi-i6e3f2eda-3 -j neutron-openvswi-sg-fallback                                #处理不满足以上 rule 的包,默认是丢弃

#处理出虚机的网络包
-A neutron-openvswi-o6e3f2eda-3 -p udp -m udp --sport 68 --dport 67 -j RETURN                 #允许访问 DHCP server
-A neutron-openvswi-o6e3f2eda-3 -j neutron-openvswi-s6e3f2eda-3                               #转防 IP 欺骗链
-A neutron-openvswi-o6e3f2eda-3 -p udp -m udp --sport 67 --dport 68 -j DROP                   #禁止提供 DHCP 服务
-A neutron-openvswi-o6e3f2eda-3 -m state --state INVALID -j DROP                              #禁止无效连接
-A neutron-openvswi-o6e3f2eda-3 -m state --state RELATED,ESTABLISHED -j RETURN                #允许已建立连接
-A neutron-openvswi-o6e3f2eda-3 -p tcp -m tcp --dport 22 -j RETURN                            #自定义第 3 条规则
-A neutron-openvswi-o6e3f2eda-3 -p icmp -j RETURN                                             #自定义第 1 条规则
-A neutron-openvswi-o6e3f2eda-3 -p tcp -m tcp --dport 80 -j RETURN                            #自定义第 5 条规则
-A neutron-openvswi-o6e3f2eda-3 -j neutron-openvswi-sg-fallback                               #处理不满足以上规则的数据包

#防 IP 欺骗规则
-A neutron-openvswi-s6e3f2eda-3 -s 91.1.180.14/32 -m mac --mac-source FA:16:3E:F3:1E:C0 -j RETURN
-A neutron-openvswi-s6e3f2eda-3 -j DROP

#继续链转发
-A neutron-openvswi-sg-chain -m physdev --physdev-out tap6e3f2eda-32 --physdev-is-bridged -j neutron-openvswi-i6e3f2eda-3 #处理经过 qbr 进入虚机的网络包
-A neutron-openvswi-sg-chain -m physdev --physdev-in tap6e3f2eda-32 --physdev-is-bridged -j neutron-openvswi-o6e3f2eda-3  #处理经过 qbr 桥出虚机的包
-A neutron-openvswi-sg-chain -j ACCEPT #接受不经过 qbr 桥的网络包
-A neutron-openvswi-sg-fallback -j DROP #丢弃
复制代码[/mw_shl_code]

结论:

此时,虚机的网络访问能力 = 基本网络能力(DHCP访问、允许已建立的连接、防 IP 欺骗)+ 用户自定义的规则允许的网络能力。

3.3.4 ipset

根据 官方文档 描述,每当有新的port被创建后,L2 Agent 会增加新的 ipset set 到 iptable 链之中(在我的测试中,如果没有后面的条件,ipset 是不会被创建的);如果该 port 所属的安全组有与别的组共享的规则,那么别的安全组的成员就会被加入到该组中。

neutron 的 security-group-rule-create CLI 支持以两种形式指定允许(被)访问的对象:

  • CIDR:待被匹配的网段,使用 remote-ip-prefix 参数指定
  • Remote security group id 或者 name:表示允许所有使用该 security group 的 port 的 IP,使用 remote-group-id 参数。

[mw_shl_code=applescript,true]--remote-ip-prefix REMOTE_IP_PREFIX          CIDR to match on.
--remote-group-id REMOTE_GROUP               Remote security group name or ID to apply rule.[/mw_shl_code]

比如下面的命令指定 remote security group 为 “default” security group:

[mw_shl_code=applescript,true]s1@controller:~$ neutron security-group-rule-create  --direction ingress --ethertype IPv4 --protocol tcp --port-range-min 22 --port-range-max 22 --remote-group-id f5377a66-803d-481b-b4c3-a6631e8ab456 0aff643b-7b34-4384-b482-f37eccef5b90
Created a new security_group_rule:
+-------------------+--------------------------------------+
| Field             | Value                                |
+-------------------+--------------------------------------+
| direction         | ingress                              |
| ethertype         | IPv4                                 |
| id                | 3340b429-22dc-4176-b5c0-01a4f449e812 |
| port_range_max    | 22                                   |
| port_range_min    | 22                                   |
| protocol          | tcp                                  |
| remote_group_id   | f5377a66-803d-481b-b4c3-a6631e8ab456 |
| remote_ip_prefix  |                                      |
| security_group_id | 0aff643b-7b34-4384-b482-f37eccef5b90 |
| tenant_id         | 74c8ada23a3449f888d9e19b76d13aab     |
+-------------------+--------------------------------------+
复制代码[/mw_shl_code]

这时候在 port 所在的计算节点上,有个新的 ipset set 被创建了。其命名规则为 protocol + remote-group-id 的一部分:

[mw_shl_code=applescript,true]root@compute1:/home/s1# ipset list
Name: IPv4f5377a66-803d-481b-b
Type: hash:ip
Revision: 2
Header: family inet hashsize 1024 maxelem 65536
Size in memory: 16536
References: 1
Members:
91.1.180.5
81.1.180.13[/mw_shl_code]

其 members 是应用了该规则的所有 port 的 IP:

[mw_shl_code=applescript,true]s1@controller:~$ neutron port-list -c security_groups -c id -c mac_address -c fixed_ips -c device_id | grep f5377a66-803d-481b-b4c3-a6631e8ab456
| [u'f5377a66-803d-481b-b4c3-a6631e8ab456'] | 402fe6b1-7670-4b6b-84a3-097beed64015 | fa:16:3e:45:6b:8b | {"subnet_id": "13888749-12b3-462e-9afe-c527bd0a297e", "ip_address": "91.1.180.5"}    |                                                                               |
| [u'f5377a66-803d-481b-b4c3-a6631e8ab456'] | 617d20fb-a635-4a03-95b1-bc15093fe32f | fa:16:3e:d8:29:9e | {"subnet_id": "4ec65731-35a5-4637-a59b-a9f2932099f1", "ip_address": "81.1.180.13"}   |[/mw_shl_code]

然后该 port 所在的计算节点上的 iptables 中增加了一项:

[mw_shl_code=applescript,true]-A neutron-openvswi-i6e3f2eda-3 -p tcp -m tcp --dport 22 -m set --match-set IPv4f5377a66-803d-481b-b src -j RETURN[/mw_shl_code]

这意味着该虚机允许上述 ipset chain 的members 访问。使用 “src” 是因为那条 rule 的方向是 “ingress”。

如果不使用 ipset 的话(设置 enable_ipset = False),iptables 规则为:

[mw_shl_code=applescript,true]-A neutron-openvswi-i6e3f2eda-3 -s 91.1.180.5/32 -p tcp -m tcp --dport 22 -j RETURN
-A neutron-openvswi-i6e3f2eda-3 -s 81.1.180.13/32 -p tcp -m tcp --dport 22 -j RETURN[/mw_shl_code]

这就可以看出使用 ipset 的价值:

  • 提高 neutron 操作 iptables 的性能
  • 提高 linux 内核管理 iptables 规则的性能

3.4 Kilo 版本允许 port 不使用安全组 <更新于 2015/11/27>

出发点:Kilo 版本之前,安全组是必须应用于整个network的,包括防欺骗规则,而这个在保证安全的同时也限制了在虚机上运行某些网络服务。

变化:增加 ML2PortSecurityExtensionDriver,应有该externsion dirver 后,可以指定某个 port 不使用安全组

[mw_shl_code=applescript,true]neutron port-update  c080dbeb-491e-46e2-ab7e-192e7627d050 ---port-security-enabled=False[/mw_shl_code]

效果图:(在作为 router 的虚机 R1 和 R1 的端口上禁止安全组)

4.jpg

详情可参考 https://wiki.openstack.org/wiki/Neutron/ML2PortSecurityExtensionDriver


4. 示例分析

4.1 计算机 192.168.1.15 ping 虚机 91.1.180.14

[mw_shl_code=applescript,true]root@compute1:/home/s1# ping 192.168.1.104
PING 192.168.1.104 (192.168.1.104) 56(84) bytes of data.
64 bytes from 192.168.1.104: icmp_seq=1 ttl=63 time=8.76 ms
64 bytes from 192.168.1.104: icmp_seq=2 ttl=63 time=2.41 ms
64 bytes from 192.168.1.104: icmp_seq=3 ttl=63 time=2.07 ms
64 bytes from 192.168.1.104: icmp_seq=4 ttl=63 time=1.23 ms[/mw_shl_code]

4.1.1 经过 qbr bridge 的网络包

这种数据包来回共 4 次,seq 1 ~ 4。可以看到,达到 qbr 的网络包已经经过了 DNAT。

[mw_shl_code=applescript,true]09:29:28.718256 fa:16:3e:90:e5:50 > fa:16:3e:f3:1e:c0, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 63, id 49778, offset 0, flags [DF], proto ICMP (1), length 84)
    192.168.1.15 > 91.1.180.14: ICMP echo request, id 15849, seq 3, length 64
09:29:28.718670 fa:16:3e:f3:1e:c0 > fa:16:3e:90:e5:50, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 53018, offset 0, flags [none], proto ICMP (1), length 84)
    91.1.180.14 > 192.168.1.15: ICMP echo reply, id 15849, seq 3, length 64[/mw_shl_code]

4.2.2 被 iptables filter 表各链处理的数据包的数目

(1)被 Forward 链处理的包进出各4个

5.jpg

(2)被 neutron-openvswi-i6e3f2eda-3 处理的进入虚机的 4 个包:第一各包被匹配到符合要求的 icmp 协议类型,以后三个是匹配到连接状态是 ESTABLISHED。

6.jpg

(3)被 neutron-openvswi-o6e3f2eda-3 处理出虚机的 4 各网络包:4 各皆通过 IP Spoofing 链的处理,然后被匹配到连接状态是 ESTABLISHED (连接应该是第一次有 icmp 包进来时被建立好的)

7.jpg

(4)没有经过 qbr 的网络包被 INPUT 链处理

8.jpg

4.2 虚机 91.1.180.14 ping 192.168.1.115

4.2.1 同样是有 8 个网络包被 FORWARD 链处理

9.jpg

4.2.2 网络包顺序是出、 进、出、进、出、进、出、进,因此第一个包被匹配到 icmp,后面的包就是被匹配到 ESTABLISHED。
(1)4个从虚机出去的包

10.jpg

(2)4个进入到虚机的包

11.jpg

5. 代码分析

注:以下材料引用自 这里,与最新的实现可能有些出入,仅供参考。

(1)neutron server 和 ML2 Agent

12.jpg

(2)neutron server 在 DB 操作后通过 RPC 调用 ML2 Agent

13.jpg

(3)当 ML2 Agent 检测到有新的虚机的 port 被 plug 到 OVS 后,它增加该 tap 设备的 iptables 链和规则

14.jpg

(4)当 ML2 Agent 监测到有虚机的 port 已经被从 OVS plug out 时,它删除对应的 tap 设备的 iptables 链和规则

15.jpg

(5)当安全组有更新的时候,Neutron Server 通过 RPC 通知 ML2 Agent 去更新 iptables rules

16.jpg

(6)当有安全组成员(policy)变更的时候,Neutron Server 通过 RPC 通知 ML2 Agent 去更新 iptables rules

17.jpg



相关内容:


neutron系列:Neutron 所实现的虚拟化网络(1)


neutron系列:Neutron 所实现的虚拟化网络(2)

neutron系列:使用 Open vSwitch + VLAN 组网(3)

neutron系列:使用 Open vSwitch + VLAN 组网(4)

Neutron系列 : 使用Open vSwitch + GRE/VxLAN 组网 (5)

Neutron系列 : 使用Open vSwitch + GRE/VxLAN 组网(6)

Neutron系列 : Neutron OVS OpenFlow 流表 和 L2 Population(7)

Neutron系列 : Neutron OVS OpenFlow 流表 和 L2 Population(8)

Neutron系列 : Neutron 是如何向 Nova 虚机分配固定IP地址的(9)

Neutron系列 : Neutron 是如何向 Nova 虚机分配固定IP地址的(10)

Neutron 系列 (11): Neutron 是如何实现负载均衡器虚拟化的【基础篇】

Neutron 系列 (12): Neutron 是如何实现负载均衡器虚拟化的【提高篇】

Neutron 系列 (13): Neutron 是如何实现虚机防火墙的 【上】

Neutron 系列 (14): Neutron 是如何实现虚机防火墙的 【下】

Neutron 系列 (15): OpenStack 是如何实现 Neutron 网络 和 Nova虚机 防火墙的

Neutron 系列(16):虚拟专用网(VPN)虚拟化

Neutron 系列 (17): Neutron 分布式虚拟路由【上】

Neutron 系列 (18): Neutron 分布式虚拟路由【下】

Neutron系列(19):Neutron L3 Agent HA 之 虚拟路由冗余协议(VRRP)【上】

Neutron系列(20):Neutron L3 Agent HA 之 虚拟路由冗余协议(VRRP)【下】

Neutron系列(21):OpenStack 高可用和灾备方案 [OpenStack HA and DR]【上】

Neutron系列(22):OpenStack 高可用和灾备方案 [OpenStack HA and DR]【下】






没找到任何评论,期待你打破沉寂

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条