本帖最后由 eying 于 2016-1-13 16:57 编辑
问题导读:
1.防火墙有什么用?
2.什么是IP地址欺骗?
3.Neutron 防火墙的相关说明?
1. 基础知识
1.1 防火墙(firewall)
防火墙是依照特定的规则来控制进出它的网络流量的网络安全系统。一个典型的场景是在一个受信任的内网和不受信任的外网比如 Internet 之间建立一个屏障。防火墙可以是电脑上运行的软件,也可以是独立的硬件设备。
与负载均衡器类似,按照其工作的网络层次,防火墙可以分为:
- 网络层防火墙(四层):网络层防火墙可视为一种 IP 封包过滤器,运作在底层的TCP/IP协议堆栈上。我们可以以枚举的方式,只允许符合特定规则的封包通过,其余的一概禁止穿越防火墙(病毒除外,防火墙不能防止病毒侵入)。这些规则通常可以经由管理员定义或修改,不过某些防火墙设备可能只能套用内置的规则。 我们也能以另一种较宽松的角度来制定防火墙规则,只要封包不符合任何一项“否定规则”就予以放行。操作系统及网络设备大多已内置防火墙功能。较新的防火墙能利用封包的多样属性来进行过滤,例如:来源 IP地址、来源端口号、目的 IP 地址或端口号、服务类型(如 HTTP 或是 FTP)。也能经由通信协议、TTL 值、来源的网域名称或网段...等属性来进行过滤。
- 应用层防火墙(七层):应用层防火墙是在 TCP/IP 堆栈的“应用层”上运作,您使用浏览器时所产生的数据流或是使用 FTP 时的数据流都是属于这一层。应用层防火墙可以拦截进出某应用程序的所有封包,并且封锁其他的封包(通常是直接将封包丢弃)。理论上,这一类的防火墙可以完全阻绝外部的数据流进到受保护的机器里。
按照防火墙的位置,可以分为:
- 主防火墙:如上面图1所示,主防火墙位于网络边界,控制进出网络的网络包。Neutron FWaas 是一种主防火墙,安装在网络节点上。
- 分布式防火墙:分布式防火墙位于内部网络节点上,比如终端计算机上,控制进出该计算机的网络包。Neutron 安全组(Security Group)是一种分布式防火墙,安装在计算节点上。
主防火墙的特点:
防火墙的主要概念:
- 规则:只有符合所制定的规则的网络包才能通过防火墙。
1.2 IP 地址欺骗 (IP Spoofing)
正常情况下,二层数据帧的源IP 地址就是发出数据的机器的 IP 地址,对方计算机接收到以后,向该 IP 地址发出回复数据帧:
(该例子中,node1 发往 node2 的帧的 IP 地址就是 node1 的地址,因此 node2 能够通过 ARP 获取 node1 的 MAC,并将回复将发回到它)
如果源计算机的数据帧的源 IP 地址不是它自己的IP地址而是一个不存在的地址或者另外一台机器的地址,目的计算机接受到数据帧后,它就会一直不停的发出 ARP 广播,最终也无法获取到MAC地址,或者发送返回帧到另一台的计算机。这就是所谓的(源) IP 地址欺骗。
(该例子中,node1 将它发往 node2 的数据帧的源IP设置为 node3 的IP,导致 node2 的回复发到了node3)
如果大量的计算机使用另外一台计算机的 IP 作为源 IP 向很多的计算机发出 ping 命令,那么那一台计算机将会收到很多的 ping 回复。这将导致它的网络带宽被塞满而不能对外提供网络服务。
常见的防止IP地址欺骗的方法:
- 任何进入网络的数据包不能把网络内部的地址作为源地址。
- 任何进入网络的数据包必须把网络内部的地址作为目的地址。
- 任何离开网络的数据包必须把网络内部的地址作为源地址。
- 任何离开网络的数据包不能把网络内部的地址作为目的地址。
- 任何进入或离开网络的数据包不能把一个私有地址(Private Address)或在RFC1918中列出的属于保留空间(包括10.x.x.x/8、172.16.x.x/12 或192.168.x.x/16 和网络回送地址127.0.0.0/8.)的地址作为源或目的地址。
- 阻塞任意源路由包或任何设置了IP选项的包。
Neutron 安全组针对 IP 地址欺骗,特别设置了相应的防火墙规则。
1.3 iptables bridge (在 linux 桥上做防火墙)
首先说说 bridge。这篇文章 详细解释了 bridge 的工作原理。简单地说,brige 是 linux 上的一个虚机(逻辑)设备,它依赖于从设备,并将从设备虚拟化为端口(port),从设备的 IP 及 MAC 都不再可用,且被设置为接收任何包,最终由 bridge 设备来决定数据包的去向:接收到本机、转发、丢弃。
上一篇文章 介绍了 iptables 是如何处理三层网络包的。显然,普通的 Linux 内核 IP 栈代码和 netfilter 无法处理经过网桥的数据包,因为网桥是属于网络二层,对于 IP 栈来说是透明的。因此,Linux 内核和 iptables 增加了处理经过二层网桥的数据包的功能。下面是增加了网桥处理能力的 netfilter 的数据包处理过程:
(引用自 https://upload.wikimedia.org/wikipedia/commons/3/37/Netfilter-packet-flow.svg)
bridge/netfilter 在内核(代码模块成为 br-nf,在这里 可以看到代码)被启用后,iptables 链的 Hook 函数也被注册到桥处理代码(bridging code)中。然而,这并不意味着它们不再被注册到标准的 IP协议栈代码中。对于被桥代码处理的网络包来说,br-nf 会判断 iptables 哪些链会在网络栈的什么位置被遍历。显然,它会保证同一个包不会被链处理两次,因此所有没有被桥代码处理的包会被标准的IP包处理方式来处理。但是,如果一个计算机既有 bridge 也有 router,那么进入该计算机的网络包,有些会被 bridge code 中 netfiler Hook 方法处理,有些会被 IP code 中的 netfilter hook 方法处理,这点需要在定义 iptables rules 时加以注意。
再来谈谈关键的 ”Bridging Decision“ 部分,其代码在(http://lxr.free-electrons.com/source/net/bridge/br_input.c#L226 rx_handler_result_t br_handle_frame(struct sk_buff **pskb))。它会基于目的MAC地址做出如下判断:
- bridge 网络帧,如果帧的目的 MAC 地址是在桥的另一侧的某个网络设备上。
- 泛洪该网络帧,如果帧的目的 MAC 对网桥是不认识的。
- 转到更高一层的三层IP协议栈代码处理,如果帧的目的地址是桥本身的或者它的某个端口的。
- 忽略它,如果帧的目的地址是位于它来自的桥的方向的同一侧。
对 (1)和 (2)来说,接下来该数据帧被 filter 的 FORWARD 链处理。对(3)来说,它会被 filter 的 INPUT 链处理。发生这种情况时,该 bridge 其实是被用作一个路由器(一个对比例子是现实世界中的带路由的交换机设备)。包含 IP 包的以太帧的目的 MAC 地址是桥的MAC地址,但是目的 IP 地址不是桥的IP地址。 这篇文章 ebtables/iptables interaction on a Linux-based bridge 详细分析了其处理过程。
要在 Linux bridge 上做防火墙(firewall packets as they are being bridged,或者说在 linux bridge 上应用 iptables 规则),必须满足以下条件:
Linux 内核支持 bridge (CONFIG_BRIDGE=m or CONFIG_BRIDGE=y). Linux 内核支持 bridge/netfilter (CONFIG_BRIDGE_NETFILTER=y). Linux 内核需要包含 Netfilter physdev match 支持 (CONFIG_IP_NF_MATCH_PHYSDEV=m or CONFIG_IP_NF_MATCH_PHYSDEV=y). 它在 2.6 版本的内核中开始作为标准模块。 你的 iptables 工具需要支持 physdev match,以及支持在一条规则中使用多个 '-m physdev'. iptables 从 1.3.6 版本开始支持。 你需要安装 bridge-utils 包。
需要注意的,各个 Linux 发行版并不是都默认启用了 netfilter for bridge,比如 Ubuntu 默认启用了, 而 RedHat 默认没启用。Neutron 会执行下面的命令来启用它:
[mw_shl_code=applescript,true]sysctl -w net.bridge.bridge-nf-call-arptables=1
sysctl -w net.bridge.bridge-nf-call-iptables=1[/mw_shl_code]
从Linux 2.6 内核版本上,iptables 1.3.6 版本以后就能够过滤 Linux bridge 上的网络包了。它使用如下参数:
参数 | 说明 | -m physdev | 匹配桥端口的进入和出去的设备。这只在内核版本 2.5.44 以上有效 (This module matches on the bridge port input and output devices enslaved to a bridge device. This module is a part of the infrastructure that enables a transparent bridging IP firewall and is only useful for kernel versions above version 2.5.44.) | --physdev-in [!] name | Name of a bridge port via which a packet is received。(收到数据包的 bridge port 的名字,只对 INPUT, FORWARD and PREROUTING 链有效)。可以添加 ”+“ 来做头部部分匹配。如果数据包不是从桥设备接收到的,则匹配不成功。 | --physdev-out [!] name | Name of a bridge port via which a packet is going to be sent.(数据包要发到的 bridge port name,只对 FORWARD, OUTPUT and POSTROUTING 有效) | [!] --physdev-is-in | Matches if the packet has entered through a bridge interface (在数据包是通过一个桥interface进入的时候会匹配成功) | [!] --physdev-is-out | Matches if the packet will leave through a bridge interface. (在数据包将要通过一个桥的interface出去时匹配成功) | [!] --physdev-is-bridged | Matches if the packet is being bridged and therefore is not being routed (在数据包是正被桥接的而不是正被路由时匹配成功。它只对 FORWARD and POSTROUTING 有效。) |
举例:
在一台 linux 机器上创建 linux bridge br0,连接 eth0 和 eth1.其中 eth0 是内网端口,eth1和 eth2是外网端口。 [mw_shl_code=applescript,true]# brctl addbr br0
# brctl addif br0 eth0
# brctl addif br0 eth1
# ifconfig br0 netmask 255.255.255.0 192.168.32.1 up [/mw_shl_code]
实际上,在将 eth1 的 IP 设置给 br0 以后,该机器可以通过 br0/eth1 访问外网(这篇文章 详细地阐述了该原理),这样,该 linux 机器是同时作为一台路由器和一台终端机:
- 作为内网和外网之间的路由器,这些数据包经过 br0 时会被 iptables 的 filter 表的 FORWARD 链处理;
- 作为可以访问外网的终端机,外网的数据包通过 eth1 直接进出该计算机,进来的包会被 iptables 的 filter 表的 INPUT 链过滤,出去的包被 OUTPUT 链过滤。
可以创建如下的 iptables 规则来实现经过 br0 的网络包:
[mw_shl_code=applescript,true]#允许本机通过访问外网,但是将进来的 udp,tcp 和 icmp 的网络包写日志(INPUT 规则的 physdev-in 肯定是 eth1 了)
iptables -A INPUT -p udp -m physdev --physdev-in eth1 -j LOG
iptables -A INPUT -p tcp -m physdev --physdev-in eth1 -j LOG
iptables -A INPUT -p icmp -m physdev --physdev-in eth1 -j LOG
# 允许 ssh, smtp and http 到 br0(INPUT!)
iptables -A INPUT -p tcp --dport 22 -m physdev --physdev-in eth1 -j ACCEPT
iptables -A INPUT -p tcp --dport 25 -m physdev --physdev-in eth1 -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -m physdev --physdev-in eth1 -j ACCEPT
# 拒绝到 br0 的别的网络包
iptables -A INPUT -p tcp --syn -m physdev --physdev-in eth1 -J REJECT
# 允许通过 tcp 端口 22(ssh),25 (smtp),80(http)到内网
iptables -A FORWARD -p tcp --dport 22 -m physdev --physdev-in eth1 --physdev-out eth0 -j ACCEPT
iptables -A FORWARD -p tcp --dport 25 -m physdev --physdev-in eth1 --physdev-out eth0 -j ACCEPT
iptables -A FORWARD -p tcp --dport 80 -m physdev --physdev-in eth1 --physdev-out eth0 -j ACCEPT
# 禁止 tcp 端口 6667 (IRC)
iptables -A FORWARD -p tcp --dport 6667 -m physdev --physdev-in eth1 -j REJECT
# 禁止其它连接到内网
iptables -A FORWARD -p tcp --syn -m physdev --physdev-in eth1 --physdev-out eth0 -j REJECT[/mw_shl_code]
1.4 ipset 和在 iptables 规则中使用 ipset
在 iptables 中,如果去匹配多个 IP 地址的话,就会写入多条 iptables 的规则(这些 IP 都是无规律性的),当如果需要匹配几百甚至上千个 IP 地址的话,那么性能就会受到严重的影响。使用 ipset 的话,这种情况可以有很大的改善,其最主要是的在结构和规则的查找上面做了很大的改善。当出现上面的情况的时候,ipset 对性能就始终稳定在一个相对值上。根据提供的测试结果表明,当规则在300-1500之间的时候其对性能的影响基本是水平线。所以当你的防火墙规则过多的时候不妨试试看。
安装:http://ipset.netfilter.org/下载然后安装。
使用:
(1). 首先 ipset 里面好多的命令是和 iptables 一样的,比如 -F ,-X, -A, -nL等等。
(2). 用户如果什么都没有添加的话,这个时候 ipset list 就会发现都是空的。
(3) 这个时候我们试着添加一个 set,如:ipset -N test_policy ipmap --network 192.168.100.1/24。该命令:
- test_policy:自定义set;
- ipmap:自定义set的类型,表示是 IP 地址; bitmap:ip,mac 表示是 IP 或者 MAC 地址。
- network 192.168.100.1/24:代表一个网段
(4) 自定义 set 创建好了后就需要在上面添加一些IP了,如:
- ipset -A test_policy 192.168.100.1
- ipset -A test_policy 192.168.100.2
- ipset -A test_policy 192.168.100.3
- ipset -A test_policy 192.168.100.4
(5)这个时候你ipset -nL就会看到该 set 以及它的 members: [mw_shl_code=applescript,true]root@compute1:/home/s1# ipset list
Name: test_policy
Type: bitmap:ip
Revision: 2
Header: range 192.168.100.0-192.168.100.255
Size in memory: 160
References: 0
Members:
192.168.100.1
192.168.100.2
192.168.100.3
192.168.100.4[/mw_shl_code]
(6)把它加到 iptables 链里面,比如说加到 FORWARD 链里面。比如要拒绝该 ipset 中计算机的访问,则添加规则 iptables -A FORWARD -m set --match-set test_policy src -j DROP。其中:
- src:也就是只是匹配的源地址,如果你需要匹配目的地址的话那么就写成 dst
以上部分资料来自 来源。更详细的信息,请 man ipset。
2. Neutron 防火墙和安全组概述
为了虚机和网络安全,Neutron 提供安全组和 FWaas(firewall-as-a-service)。两者的概念非常类似。一个安全组定义了哪些进入的网络流量能被转发给虚机。安全组包含一组防火墙策略,称为安全组规则(Security Group Rule)。可以定义n个安全组,每个安全组可以有n个规则,可以给每个实例绑定n个安全组。FWaas 则作用于虚拟路由器上,对进出租户网络的网络流量进行过滤。OpenStack 的相关的组件为:
- Nova Security Group:Nova 项目提供给虚机的安全组。
- Neutron Security Group:Neutorn 项目提供给虚机的安全组。
- Neutron FWaas:基于 Neutron L3 Agent 实现的虚机防火墙的一个参考实现。
这三个组件底层都通过控制 Linux iptables 来控制进出虚机或者租户网络的网络包,但是在不同的位置使用不同的方法来实现不同的目的。三者之间的比较如下:
| Nova Security Group | Neutron Security Group | Neutron FWaas | 作用 | 控制进入虚机的网络包 | 控制进出虚机的网络包 | 控制进出租户网络的网络包。对不经过 Virutal Router 的网络包不起作用。 | 防火墙节点 | Nova 计算节点 | Nova 计算节点(L2 Agent 节点) | L3 Agent 节点上该 firewall 所在的租户的所有 router 的 namespace 中 | IPV6 支持 | 支持。通过配置项 use_ipv6 来指定是否使用 IPV6,默认值为 false。 | 判断 /proc/sys/net/ipv6/conf/default/disable_ipv6 文件的内容。如果是 ”0“,表示支持 ipv6,否则不支持。如果支持的话,则同时往 iptables 和 ip6tables 中添加链和规则。 | 支持,同时往 iptables 和 ip6tables 中添加链和规则,但是似乎没有判断系统是否支持 IPV6. | 控制粒度 | 虚机 | Neutron port | 租户的所有 virtual router 的所有 Interface | 控制实施者 | Nova 计算节点的 IP 栈 | Nova 计算节点的 qbr 桥 | router 的 namespace 的 IP 栈 | 控制的网络流量方向 | ingress only (进入虚机的网络包) | ingress 和 egress (进出虚机的网络包) | ingress 和 egress (进出租户网络的网络包) | 匹配的数据项 | 协议、源 IP 网段、目的端口号 | 协议、端口、网段、方向 | 协议、源端口、目的端口、源 IP 网段、目的 IP、方向 | 匹配的结果行为 | 允许(allow) | 允许(allow) | 允许(allow)和拒绝(deny) | 使用 | 启动虚机时指定安全组,不指定的话使用默认安全组。虚机启动后,对所使用的安全组的变更会实时应用到虚机。可以向虚机添加和删除安全组。 | 动态(随时,启动虚机时和启动后)使用 neutron port-update 命令更新指定 port 的安全组。 | 动态(随时)应用到租户的所有虚拟路由器。 | 没有显式配置安全组时的默认行为 | 使用默认安全组(Default Security Group ),它允许使用同一个安全组的虚机访问该虚机 | 禁止该机器的网络访问,除了允许它访问 DHCP 服务 | 没有默认防火墙,防火墙没有默认规则。配置了 firewall 但是没添加规则的话,禁止所有网络进出数据网络。 | 允许的数目 | 多个,Security Group 数目(默认10)和 Security Group Rules 数目(默认100)受租户的 quota 限制 | 最多一个,不允许多个。 | CLI | #列表,增加,删除 虚机的安全组 add-secgroup: Add a Security Group to a server
list-secgroup: List Security Group(s) of a server.
remove-secgroup: Remove a Security Group from a server. #操作安全组
secgroup-add-group-rule
secgroup-add-rule
secgroup-create
secgroup-delete
secgroup-delete-group-rule
secgroup-delete-rule
secgroup-list
secgroup-list-rules
secgroup-update #启动虚机时指定安全组 nova boot --flavor FLAVOR_ID --image IMAGE_ID --security-groups SEC_GROUP | #操作安全组 neutron security-group-create
neutron security-group-list
neutron security-group-rule-create
neutron security-group-rule-list
neutron security-group-rule-delete
neutron security-group-delete #创建 port 时指定安全组:
neutron port-create --security-group SECURITY_GROUP_ID1 --security-group SECURITY_GROUP_ID2 NETWORK_ID #显示 port 的安全组
neutron port-list -c security_groups -c id -c mac_address -c fixed_ips -c device_id #删除 port 的安全组
neutron port-update --no-security-groups PORT_ID #使用带安全组的 port 启动虚机
nova boot vm1 --flavor 6 --nic port-id= | #防火墙操作 firewall-create
firewall-delete
firewall-list
firewall-show
firewall-update
#防火墙策略操作
firewall-policy-create
firewall-policy-delete
firewall-policy-insert-rule
firewall-policy-list
firewall-policy-remove-rule
firewall-policy-show
firewall-policy-update
#防火墙规则操作
firewall-rule-create
firewall-rule-delete
firewall-rule-list
firewall-rule-show
firewall-rule-update
| 配置 | 见下文 | 底层实现 | 见下文 |
相关内容:
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]【下】
|