|
|
1. Nova 安全组
) [& r+ D G$ r* G1.1 配置4 k2 p) M. m0 q
节点 配置文件 配置项 说明
7 Y5 l2 d/ ?0 S# @controller /etc/nova/nova.conf security_group_api = nova 是的 nova secgroup* 命令使用的是 nova 安全组的 API
, z4 w6 S) ?! M2 K. x. C1 G/etc/neutron/plugins/ml2/ml2_conf.ini enable_security_group = False 禁止 Neutron 安全组8 ~& H! P9 s4 p% B `. L
nova-compute 4 t; `1 n$ |5 p
/etc/nova/nova.conf6 X5 T/ G8 X; j/ ?1 F
/etc/nova/nova-compute.conf$ c" N$ v0 c7 ~, L. k
firewall_driver = nova.virt.firewall.IptablesFirewallDriver 指定 Nova 安全组的驱动,可以是IptablesFirewallDriver 或者 NWFilterFirewall。默认是 IptablesFirewallDriver。见下面的说明。
( G# p+ `5 q4 m3 | /etc/neutron/plugins/ml2/ml2_conf.ini enable_security_group = False 禁止 Neutron 安全组4 _" {! u0 G/ q$ F
network /etc/neutron/plugins/ml2/ml2_conf.ini enable_security_group = False 禁止 Neutron 安全组
9 ^0 h8 q# l: B nova 提供两种实现方式:使用 libvirt's nwfilter 的实现以及使用 linux iptables 的实现,默认的方式是使用 linux iptables。可以通过设置配置项 firewall_driver 的值指定。需要注意的是,即使使用 iptables,依然使用了部分 nwfilter 功能。参见 https://ask.openstack.org/en/question/19456/how-security-group-is-implemented/& X3 C" L" o& A. g& m$ n
firewall_driver=nova.virt.libvirt.firewall.IptablesFirewallDriver# x; P* D8 d& p# P2 ~) ?/ r9 l
firewall_driver=nova.virt.libvirt.firewall.NWFilterFirewall% s& U% b! J2 Z& C/ v. K
1.2 CLI
( U x- O0 w' l$ A4 h复制代码, F* [" @+ j- Z' v d' X" b
列表安全组:
% d V: H( h( Ls1@controller:~$ nova secgroup-list-rules novasg1
' S8 c0 L* Y2 P l( I$ t4 H+-------------+-----------+---------+-----------+--------------+
7 {- F4 f/ k' `5 h& ~+ u| IP Protocol | From Port | To Port | IP Range | Source Group |1 l* a" ~: K5 d' A! P7 w! i
+-------------+-----------+---------+-----------+--------------+
; a+ N# J! t' U8 f| tcp | 22 | 22 | 0.0.0.0/0 | |) A: Z m& Q5 b+ Q8 ~) ?$ o
+-------------+-----------+---------+-----------+--------------+0 _: `7 _, G7 \" d! `+ T
创建一个安全组规则:
. c9 u7 ]) L2 A* u) ?+ Ns1@controller:~$ nova secgroup-add-rule novasg1 udp 53 53 100.1.100.0/24
* A2 h# z" e! y9 |% A. Y+-------------+-----------+---------+----------------+--------------+* b2 b4 m+ o: D. R) s. h9 H( c, N
| IP Protocol | From Port | To Port | IP Range | Source Group |8 D* B* ]' Q) R2 O! G7 {1 _
+-------------+-----------+---------+----------------+--------------+
8 h- k8 d0 {8 M2 `! a% A| udp | 53 | 53 | 100.1.100.0/24 | |
% u# }! ?0 X C! m5 Z5 ?5 G% y2 h+-------------+-----------+---------+----------------+--------------+
0 h& |/ y3 |% d( s, h2 N删除虚机的安全组:: I7 O, ]+ d" C. j+ c
s1@controller:~$ nova remove-secgroup 2c59a875-bc23-4605-ad70-5315d7a3f8e2 novasg1
( b! b: Z* y9 Y' k添加安全组到虚机:
9 ?* t/ l1 a) ]6 l: ?s1@controller:~$ nova add-secgroup 2c59a875-bc23-4605-ad70-5315d7a3f8e2 novasg18 I7 t1 Q! p3 W
创建第二个安全组:
) w6 j3 s" ^2 Q% ks1@controller:~$ nova secgroup-add-rule novasg2
8 |" w- p0 X5 x8 q- `1 d* y添加规则:5 O4 I( n7 l1 S4 G5 J8 ]
s1@controller:~$ nova secgroup-add-rule novasg2 icmp -1 -1 0.0.0.0/0
8 a4 D, z. L! c% P. `+-------------+-----------+---------+-----------+--------------+
4 i& ?/ ]0 U' d/ ~& l$ d. w| IP Protocol | From Port | To Port | IP Range | Source Group |; y3 N# x% p+ U- g; T& a
+-------------+-----------+---------+-----------+--------------+
! U* ]! [& F S| icmp | -1 | -1 | 0.0.0.0/0 | |+ g1 j; S- ] V; J
+-------------+-----------+---------+-----------+--------------+) I ?2 D! j7 T" Y( S
再添加安全组到虚机:
/ w8 f! ]% z+ }2 g% cs1@controller:~$ nova add-secgroup 2c59a875-bc23-4605-ad70-5315d7a3f8e2 novasg2& M8 Q3 x) E6 K4 b9 J2 H
复制代码
, T# ~9 f0 T/ _; c- J& [1.3 iptables 链2 @5 n* U* w, {& B+ F* I: Z
Nova-compute 增加了 filter 表的 INPUT,OUTPUT 和 FORWARD 链:
/ t0 E6 D# ~! I: I# E5 z3 G" y& m4 n7 j f
复制代码
1 J( w. d9 A w. M% i* y+ x! S-N nova-compute-FORWARD" i* M$ l) K4 v5 ]: d' Y% @
-N nova-compute-INPUT a4 A: v( F8 |0 d9 @1 r1 u
-N nova-compute-OUTPUT
% b, h; D8 m# C/ r-N nova-compute-inst-122 #每个虚机一个链,命名规则是 ”inst“-<instance 在数据库中的 id>
d8 D' T! ~. r5 W-N nova-compute-local
2 }; y9 o, q# o-N nova-compute-provider, r* b9 _( o" |$ E
-N nova-compute-sg-fallback* ~3 x/ j9 U7 b' a& `
-N nova-filter-top7 L+ L0 c' B' k, J$ u4 F# r
-A INPUT -j nova-compute-INPUT
. x& T& c6 B$ F! z-A FORWARD -j nova-filter-top2 `: b3 o. i6 `' C% N- Y1 G: B A$ f
-A FORWARD -j nova-compute-FORWARD
0 `2 S% X4 u1 K-A OUTPUT -j nova-filter-top O$ j# d% \- u6 D9 |
-A OUTPUT -j nova-compute-OUTPUT5 k; R) \7 O; p1 F) d8 Q* |
-A nova-compute-FORWARD -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp --sport 68 --dport 67 -j ACCEPT #允许本机上的虚机发出 DHCP 广播1 q/ P0 Z3 @# f' Q# y1 T
-A nova-compute-INPUT -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp --sport 68 --dport 67 -j ACCEPT #允许本机接受 DHCP 广播包
0 `5 y% D1 d; g" G7 r-A nova-compute-inst-122 -m state --state INVALID -j DROP& Y: i6 l' g+ [& ]. t
-A nova-compute-inst-122 -m state --state RELATED,ESTABLISHED -j ACCEPT, _9 x$ S$ [5 t- t% T# K* G
-A nova-compute-inst-122 -j nova-compute-provider
! x3 F! t' J: ^3 o3 j# s& W9 q-A nova-compute-inst-122 -s 91.1.180.2/32 -p udp -m udp --sport 67 --dport 68 -j ACCEPT #接受该虚机所在子网的 DHCP Server 返回的包
2 n( c! ?: o" S1 R5 P- g( j' {-A nova-compute-inst-122 -s 91.1.180.0/24 -j ACCEPT #在配置项 allow_same_net_traffic = true 的情况下接受同网段虚机的来访包$ V- G( O t! M5 n: H! |$ @
-A nova-compute-inst-122 -p tcp -m tcp --dport 22 -j ACCEPT #用户安全组规则指定的来访包
$ D/ ? f' A6 U0 y( \-A nova-compute-inst-122 -s 100.1.100.0/24 -p udp -m udp --dport 53 -j ACCEPT #用户安全组规则指定的来访包
- o6 S# L' \1 ]; H& J' ?-A nova-compute-inst-122 -p icmp -j ACCEPT #用户安全组规则指定的来防爆
7 _. F" t! c8 \2 \' }. t% T-A nova-compute-inst-122 -j nova-compute-sg-fallback #没被上面规则处理的其它来访包
( @9 w, x. W. t6 o, ]-A nova-compute-local -d 91.1.180.14/32 -j nova-compute-inst-122 # “-d“ 决定了 nova 安全组只检查进入虚机的网络包* |2 T$ w+ B& o; P3 X7 A
-A nova-compute-sg-fallback -j DROP #丢弃其它包,只允许上述规则指定的网络访问6 Y+ ]6 `% ^2 j u) |5 O
-A nova-filter-top -j nova-compute-local
3 P1 Z" N# ]$ `: ?复制代码( t* Q1 T$ ~7 ]4 w) o2 F
2. FWaas- l- r4 Z% [7 r; c3 X! |" [- Y. j3 V
2.1 概念
+ f/ m2 F+ l8 N8 E* M/ l 从 Havana 版本开始,Neutron 提供一种基于 Neutron L3 Agent 的一种网络四层防火墙虚拟化参考实现 Firewall-as-a-service,简称 FWaas。本文的分析是基于 OpenStack Juno 版本进行的。Juno 版本中,FWaas 是分租户的,但是可以在多个租户之间共享。每个租户只允许一个防火墙。与物理的防火墙类似,FWaas 也有三个主要概念:9 m1 I0 y1 d+ Y
(1)规则(Rule):允许用户指定所要匹配的名称,描述,针对的协议(TCP, UDP, ICMP, ANY),行为(Allow,Deny),源/目的 IP 地址/子网 和 端口号/端口号区间。
0 Q4 i7 l6 ]) ^- H
H5 g/ {$ [' v5 m& s( W) z与 neutron 安全组中的规则的区别是,这里需要指定被匹配到的数据包的处理行为是通过(ALLOW)和不通过(DENY),但是不能指定网络方向。FWaas 会将规则同时应用到进出网络的网络包上。 e0 u7 C7 J* @" R0 E0 z. c
(2)策略(Policy):规则的逻辑集合。Policy 可以是共享的 和 被审计的(Audited)。目前,FWaas 只是把 “audited” 保存到 DB 中,并没有对它做任何处理。
6 J! l3 r5 _: m. q! k' U* d9 c3 U2 _) S, ]# K/ G6 s, z2 V: A
(3)防火墙(Firewall):策略的逻辑集合。见上面右图。Juno 版本中,每个租户只能拥有最多一个 Firewall。防火墙可以是共享的。
* n, s8 [2 l( z2 C/ W; V 这里需要说明的是 FWaas 和 Security Group (安全组) 的区别。安全组规则在连接到一个实例的计算节点上的Linux桥 qbr 上实施,FWaaS 创建的防火墙规则在租户网络边缘实现的虚拟路由器上实施。 FWaaS 并不旨在取代安全组的功能,并且它提供更为补充安全组,特别是在其当前实现状态下。 FWaaS 目前缺乏安全组提供的一些功能,包括无法指定通信的方向等。与此相反,安全组,也因为他们缺乏创建特定规则拒绝所有流量的能力,因此需要 FWaas 作为补充。. c3 A6 H+ Q6 b& k3 V+ H
5 x. ?! ^( R* D8 [- T7 r1 ]- ] q' k5 ?% m4 F1 x
2.2 配置
/ a d/ F. [, V+ M. j0 {节点 配置和操作
q% }/ l7 ]/ w7 `: ^3 ^2 p7 F控制节点上
9 l6 r6 k8 V( ?* u! m g; H修改 /etc/neutron/neutron.conf:6 }8 B$ }2 s( E- i4 K4 Z2 }+ ~( i
[default]
5 q" i- r* g2 Gservice_plugins = router,lbaas,firewall
v) O& P; ^4 j7 z: H[service_providers]
3 g2 A7 m$ R. Y9 ~, h n# P- _service_provider = FIREWALL:Iptables:neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver:default
* `! M1 F" [2 M1 T t! i0 R
8 g% C1 k4 M6 mservice neutron-server restart0 T+ _& P# H5 m
/ u, O p7 h( G: z修改 /usr/share/openstack-dashboard/openstack_dashboard/local/local_settings.py:'enable_firewall': True
' I) n( u- u( Q. l$ {6 n5 Y# F网络节点上 5 B) ?: W( a) I( l5 m
修改 /etc/neutron/fwaas_driver.ini:
$ |1 w6 `7 `. c1 O2 ?[fwaas]
- {2 a3 J7 B2 B& G* Adriver = neutron.services.firewall.drivers.linux.iptables_fwaas.IptablesFwaasDriver
1 z* Z$ o. W9 e8 n6 z% C; ^enabled = True7 u0 B6 s7 i& K. L
. l2 Z$ R% J5 Z. }
service neutron-l3-agent restart
8 q) L% }! X& l3 K5 D0 y! k
: s2 k4 O) Y: ^3 @ w% Q$ d0 M5 h2.3 实现! C/ Z* s. }: s t$ X
目前的实现中,FWaas 是通过在其所在 tenant 中的所有 Virtual Router 上添加 iptbales 规则来实现对进出数据网络的网络包进行控制的。
0 R6 W$ {" F" t# R* R7 i
9 V$ [7 x" o! N4 ?. P代码实现:
Z6 d- }/ B" g6 [ e1 h控制节点上(class FirewallPlugin):, ?# i* H8 O* s" G: ^. q/ s, x
(1)create rule:纯数据库操作,将 rule 保存到数据中。
7 z! s; O) C+ [(2)create policy:纯数据库操作,将 policy 保存到数据中。; M3 b5 b' Z1 a$ o( \+ |
(3)如果将 rule 添加到一个已经添加到 firwall 的 policy,或者将一个 policy 加入一个存在的 firewall,在数据库操作后,通过 RPC fanout 到所有的 L3 Agent host:* ~0 S& T2 ]# |9 i6 N. ?
{'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'}
9 }- V: h7 o. Z3 o& X6 zinsert_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
1 V, G; W; T7 q4 Zcreate_firewall -> Firewall_db_mixin.create_firewall -> FirewallAgentApi.create_firewall9 S# u7 _1 q7 T$ L! ~9 a' i# @2 D- Z
update_firewall -> Firewall_db_mixin.update_firewall -> FirewallAgentApi.update_firewall
2 R# u+ y+ W$ ?, J- ^delete_firewall -> Firewall_db_mixin.delete_firewall -> FirewallAgentApi.delete_firewall
1 w/ H7 _3 ^ g) J) _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
( a# P E- s& m. K3 {) t 网络节点上(class FWaaSL3AgentRpcCallback):0 f% x! p; \* X
(1) 通过 RPC 获取所有的 router,在获取firewall 所在的 tenant 上的 routers; q! m0 K( s; F* J
(2)调用 IptablesFwaasDriver.update_firewall,依次更新每个 router 的 iptables 规则
8 O/ W9 t1 x# \: M% u; X+ b0 R: u0 g(3)首先删除已有规则,然后根据配置的 rules 重新生成规则 ( l! V) p9 I; I. V8 C
复制代码4 v9 T: L) v5 G( @% h8 Y. c# R
root@network:/var/cache# ip netns exec qrouter-e438bebe-6795-4b68-a613-ec0df38d3064 iptables -t filter -S' y4 }# F2 n* }" E" M
-P INPUT ACCEPT0 w8 b8 }! T+ m' M
-P FORWARD ACCEPT9 y! _# J7 x) F' X5 J2 u
-P OUTPUT ACCEPT
|$ c+ t2 O! t Q4 e' A-N neutron-filter-top3 B7 `$ p, M! V" {6 ^' B9 L! N
-N neutron-l3-agent-FORWARD
; v( t8 }2 b9 [$ c8 I n( r! ^6 G: \-N neutron-l3-agent-INPUT
7 x0 O f, m; Y4 l. }. z" n-N neutron-l3-agent-OUTPUT) ^5 [7 k p# b- n3 D0 u' F
-N neutron-l3-agent-fwaas-defau #新增的 firewall chain# w, L% s& v( H" m
-N neutron-l3-agent-iv4aa85bd66 #新增的 firewall chain- F* |# \- V% b. w$ {0 W6 C5 ]
-N neutron-l3-agent-local
/ \/ J: N3 B8 p& o- Y# }-N neutron-l3-agent-ov4aa85bd66 #for firewall0 d& v n9 L# O- [+ R
-A INPUT -j neutron-l3-agent-INPUT
) T4 R& L/ m) v$ V-A FORWARD -j neutron-filter-top
& R( Y5 |. b/ R' I4 C- A-A FORWARD -j neutron-l3-agent-FORWARD #将 forward 转到 neutron 的chain
) T; n* ^" q$ u) o9 H4 K! x: g O-A OUTPUT -j neutron-filter-top
+ U2 ~3 `% d F8 f% D9 n t0 n-A OUTPUT -j neutron-l3-agent-OUTPUT5 n( U$ P' a; P z5 D
-A neutron-filter-top -j neutron-l3-agent-local& Q3 l2 d+ ]9 M
-A neutron-l3-agent-FORWARD -o qr-+ -j neutron-l3-agent-iv4aa85bd66 #进数据网络的包
3 m( |/ \. t6 Y+ s8 f/ a h- v-A neutron-l3-agent-FORWARD -i qr-+ -j neutron-l3-agent-ov4aa85bd66 #出数据网络的包- C8 R3 P* m6 S; l2 z( B! z
-A neutron-l3-agent-FORWARD -o qr-+ -j neutron-l3-agent-fwaas-defau #进数据网络的包的默认处理 chain7 |. P( A: |* d6 r
-A neutron-l3-agent-FORWARD -i qr-+ -j neutron-l3-agent-fwaas-defau #出数据网络的包的默认处理 chain
& i. Y+ h8 w4 P( F-A neutron-l3-agent-INPUT -d 127.0.0.1/32 -p tcp -m tcp --dport 9697 -j ACCEPT
' n2 s- e' Z) O2 c+ p1 G-A neutron-l3-agent-fwaas-defau -j DROP #默认丢弃没有被以上规则处理的所有包
G* p/ [6 Q% G `1 s: {, k& d4 _-A neutron-l3-agent-iv4aa85bd66 -m state --state INVALID -j DROP3 E: E) G" Y& u5 j9 L% n% H# k
-A neutron-l3-agent-iv4aa85bd66 -m state --state RELATED,ESTABLISHED -j ACCEPT #接受状态为 RELATED, ESTABLISHED (已建立的连接)的包
( |; E5 I( Y# k; T-A neutron-l3-agent-iv4aa85bd66 -p tcp -m tcp --dport 80 -j ACCEPT #根据定义的 FWaas rule,接受目的端口为 80 的 tcp 包# Y1 n7 O- F5 i& N+ }$ }% ~. Z2 a
-A neutron-l3-agent-ov4aa85bd66 -m state --state INVALID -j DROP
. k: C2 E, d% p+ T5 \; l) I6 y-A neutron-l3-agent-ov4aa85bd66 -m state --state RELATED,ESTABLISHED -j ACCEPT
- I6 o: ~( h( [0 g% ]9 T2 c$ A! }-A neutron-l3-agent-ov4aa85bd66 -p tcp -m tcp --dport 80 -j ACCEPT #根据 FWaas rule,接收目的端口为 80 的 tcp 包
9 T3 J: o& s" C1 b" \复制代码: l' Y0 t9 b, f
|
|