|
|
1. Nova 安全组
* b+ Z/ t" b: d( e6 h0 s1.1 配置7 i, O: r" @1 }4 D) S
节点 配置文件 配置项 说明
( S" |. r7 I0 I; L3 r, G: Wcontroller /etc/nova/nova.conf security_group_api = nova 是的 nova secgroup* 命令使用的是 nova 安全组的 API
- N Y; I5 a! B0 M' H/etc/neutron/plugins/ml2/ml2_conf.ini enable_security_group = False 禁止 Neutron 安全组5 ^/ c. m/ ` Q) m) ]
nova-compute + d4 o( o) J2 K6 [: e/ Q
/etc/nova/nova.conf
/ L* e/ u4 F! b: z7 ?/etc/nova/nova-compute.conf
* u4 S) x4 Q2 _firewall_driver = nova.virt.firewall.IptablesFirewallDriver 指定 Nova 安全组的驱动,可以是IptablesFirewallDriver 或者 NWFilterFirewall。默认是 IptablesFirewallDriver。见下面的说明。+ x# m! }( a- J7 a
/etc/neutron/plugins/ml2/ml2_conf.ini enable_security_group = False 禁止 Neutron 安全组
. J# L# Y( Q4 [6 w( J- P2 ^6 B8 nnetwork /etc/neutron/plugins/ml2/ml2_conf.ini enable_security_group = False 禁止 Neutron 安全组, X$ L9 P2 N# u) C8 W7 H
nova 提供两种实现方式:使用 libvirt's nwfilter 的实现以及使用 linux iptables 的实现,默认的方式是使用 linux iptables。可以通过设置配置项 firewall_driver 的值指定。需要注意的是,即使使用 iptables,依然使用了部分 nwfilter 功能。参见 https://ask.openstack.org/en/question/19456/how-security-group-is-implemented/
$ d2 H2 S# p5 x6 s5 S1 a4 V+ xfirewall_driver=nova.virt.libvirt.firewall.IptablesFirewallDriver
6 ^. ]' V5 H" _7 J; B6 zfirewall_driver=nova.virt.libvirt.firewall.NWFilterFirewall+ W6 C9 g1 ?6 V
1.2 CLI, I9 U6 O, e* e$ F* v% z: j
复制代码 u( V6 V: k$ q3 H* L4 l, y, v2 K
列表安全组:
, _1 K+ n$ ^+ Z) a9 J# es1@controller:~$ nova secgroup-list-rules novasg1" l! ~5 h* Y }% ?
+-------------+-----------+---------+-----------+--------------+# H( g a0 K/ R I, M
| IP Protocol | From Port | To Port | IP Range | Source Group |
4 r1 u% ^, p0 l+-------------+-----------+---------+-----------+--------------+
4 o2 F2 g% S; A& z/ A- J| tcp | 22 | 22 | 0.0.0.0/0 | |
+ t E% X3 b/ G7 O$ e6 E+ j+-------------+-----------+---------+-----------+--------------+
! A A* q5 K% I, V z% C3 Y0 x: T创建一个安全组规则:
9 e. ~8 {) y% J& ^5 ]s1@controller:~$ nova secgroup-add-rule novasg1 udp 53 53 100.1.100.0/247 a$ _- |. ?( i- @
+-------------+-----------+---------+----------------+--------------+! w1 g6 o) h; Q8 p# ?+ U. z
| IP Protocol | From Port | To Port | IP Range | Source Group |
* h5 k+ s2 p& }: B# {- t, F' Z: U. W9 h& h+-------------+-----------+---------+----------------+--------------+; D2 u/ c" a9 `6 D+ G1 h
| udp | 53 | 53 | 100.1.100.0/24 | |# M1 Y" b6 X: i0 q& a
+-------------+-----------+---------+----------------+--------------+
7 r; O# ]" _. A: G8 e% D: T0 _6 C删除虚机的安全组:
' R% [! p4 A! Ds1@controller:~$ nova remove-secgroup 2c59a875-bc23-4605-ad70-5315d7a3f8e2 novasg1
- q* d" S5 a C: R3 @' X5 w& a, p添加安全组到虚机:
2 {7 ^0 D" @, A& P S6 Hs1@controller:~$ nova add-secgroup 2c59a875-bc23-4605-ad70-5315d7a3f8e2 novasg13 }" \( r; m" Z
创建第二个安全组:
4 p4 _) c" G7 js1@controller:~$ nova secgroup-add-rule novasg2
" c+ Q5 e: ]4 |( P, e添加规则:
( W: g2 y9 N( i+ g# g0 C) k& ss1@controller:~$ nova secgroup-add-rule novasg2 icmp -1 -1 0.0.0.0/0& ?1 c# F7 G* ^5 I) V
+-------------+-----------+---------+-----------+--------------+# y- k3 z; m& c* d' {( s) ~& q
| IP Protocol | From Port | To Port | IP Range | Source Group |/ a. z* F/ h* Q1 A% h! |3 m; q; Q
+-------------+-----------+---------+-----------+--------------+9 Y# ]% p$ t4 u$ I5 B
| icmp | -1 | -1 | 0.0.0.0/0 | |; d: L8 | N8 w9 p3 M6 x
+-------------+-----------+---------+-----------+--------------+- u" f, ]# M9 C6 D% |
再添加安全组到虚机: t S9 g, {$ I; z1 S/ m4 ]7 w
s1@controller:~$ nova add-secgroup 2c59a875-bc23-4605-ad70-5315d7a3f8e2 novasg2( Q. G* k- X4 X7 t0 A' B
复制代码
" r, t0 {5 y b3 v1.3 iptables 链
E% ?. ^" i6 T4 m9 G1 v9 N/ iNova-compute 增加了 filter 表的 INPUT,OUTPUT 和 FORWARD 链:; x- T+ c8 F2 \1 }6 R
- R2 p2 c4 p& f* }8 s
复制代码
, d3 R! w3 S- z0 Y* y1 }-N nova-compute-FORWARD
S a; P% F) ~% Y# m9 n1 } T% a-N nova-compute-INPUT( ^+ `# S2 W" |- Z# }7 c. l
-N nova-compute-OUTPUT
9 ?0 Q3 ^+ x# d R-N nova-compute-inst-122 #每个虚机一个链,命名规则是 ”inst“-<instance 在数据库中的 id>
% N/ R! U/ _ C-N nova-compute-local7 `' ?( m6 ]. I! u- ?. K
-N nova-compute-provider1 v" j% R5 [5 V. I
-N nova-compute-sg-fallback9 v( J2 W5 x1 g+ h
-N nova-filter-top4 H, \+ @ F) B& x) a1 C
-A INPUT -j nova-compute-INPUT7 V. N1 c$ b. }4 j6 R
-A FORWARD -j nova-filter-top- |3 R0 u: \3 e8 I
-A FORWARD -j nova-compute-FORWARD
' l, d2 x4 ?* u5 r4 w+ d+ Z-A OUTPUT -j nova-filter-top
/ B" V" F9 U# a. U7 o-A OUTPUT -j nova-compute-OUTPUT+ l F D! F/ S( F m% @. J
-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 广播) n% ?1 ]- x$ F- W, L4 `5 U
-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 广播包* _$ X7 H7 I4 i" g. w; C
-A nova-compute-inst-122 -m state --state INVALID -j DROP4 F+ Y0 h' k0 v8 q2 v4 @+ U
-A nova-compute-inst-122 -m state --state RELATED,ESTABLISHED -j ACCEPT! |* z9 w8 L* q$ w1 h; C* e
-A nova-compute-inst-122 -j nova-compute-provider
8 i; w% {/ Q9 A+ d" ~9 Q-A nova-compute-inst-122 -s 91.1.180.2/32 -p udp -m udp --sport 67 --dport 68 -j ACCEPT #接受该虚机所在子网的 DHCP Server 返回的包( G4 b2 R/ A1 L9 C. n% S) k4 \
-A nova-compute-inst-122 -s 91.1.180.0/24 -j ACCEPT #在配置项 allow_same_net_traffic = true 的情况下接受同网段虚机的来访包
3 A8 b% n+ H2 z* }-A nova-compute-inst-122 -p tcp -m tcp --dport 22 -j ACCEPT #用户安全组规则指定的来访包' }. |) [& d- E5 U* Z9 r
-A nova-compute-inst-122 -s 100.1.100.0/24 -p udp -m udp --dport 53 -j ACCEPT #用户安全组规则指定的来访包/ ]2 }5 c4 B6 l+ `7 A2 ~
-A nova-compute-inst-122 -p icmp -j ACCEPT #用户安全组规则指定的来防爆* j2 ~2 T6 x; w- ^6 T! p
-A nova-compute-inst-122 -j nova-compute-sg-fallback #没被上面规则处理的其它来访包 ( e9 l x" P( i2 S1 A% ]6 ]5 J1 ]. |4 d
-A nova-compute-local -d 91.1.180.14/32 -j nova-compute-inst-122 # “-d“ 决定了 nova 安全组只检查进入虚机的网络包
! B1 ?: ~8 [; p4 k% Q" ]-A nova-compute-sg-fallback -j DROP #丢弃其它包,只允许上述规则指定的网络访问
( @( l& x) R% C; x) C-A nova-filter-top -j nova-compute-local
% n- N- a1 O U% y6 v1 }8 T复制代码' f0 }/ D. _ {7 a& a
2. FWaas
8 w$ s* O0 f6 p' N5 g) P$ X7 R# _2.1 概念
: _# B% ]" J% k$ ~4 X: R# L 从 Havana 版本开始,Neutron 提供一种基于 Neutron L3 Agent 的一种网络四层防火墙虚拟化参考实现 Firewall-as-a-service,简称 FWaas。本文的分析是基于 OpenStack Juno 版本进行的。Juno 版本中,FWaas 是分租户的,但是可以在多个租户之间共享。每个租户只允许一个防火墙。与物理的防火墙类似,FWaas 也有三个主要概念:' g$ p- _) D- f& j2 h0 N- `
(1)规则(Rule):允许用户指定所要匹配的名称,描述,针对的协议(TCP, UDP, ICMP, ANY),行为(Allow,Deny),源/目的 IP 地址/子网 和 端口号/端口号区间。( t- V! _3 x" d; {' ~
# K$ n$ Y& b7 V$ ]3 W0 c$ I4 B
与 neutron 安全组中的规则的区别是,这里需要指定被匹配到的数据包的处理行为是通过(ALLOW)和不通过(DENY),但是不能指定网络方向。FWaas 会将规则同时应用到进出网络的网络包上。1 @3 T# d" r1 N5 u+ B% _6 b
(2)策略(Policy):规则的逻辑集合。Policy 可以是共享的 和 被审计的(Audited)。目前,FWaas 只是把 “audited” 保存到 DB 中,并没有对它做任何处理。, X0 k+ Q$ R3 ?3 R0 r- ]
* |0 m3 q4 Q# F; A8 N% j# k
(3)防火墙(Firewall):策略的逻辑集合。见上面右图。Juno 版本中,每个租户只能拥有最多一个 Firewall。防火墙可以是共享的。
, ~4 x) Q3 w" r8 i( N5 { 这里需要说明的是 FWaas 和 Security Group (安全组) 的区别。安全组规则在连接到一个实例的计算节点上的Linux桥 qbr 上实施,FWaaS 创建的防火墙规则在租户网络边缘实现的虚拟路由器上实施。 FWaaS 并不旨在取代安全组的功能,并且它提供更为补充安全组,特别是在其当前实现状态下。 FWaaS 目前缺乏安全组提供的一些功能,包括无法指定通信的方向等。与此相反,安全组,也因为他们缺乏创建特定规则拒绝所有流量的能力,因此需要 FWaas 作为补充。+ ]) W8 `, q$ v7 P. ]) E: y2 r
$ W* ~) n* H/ k6 X; d" Q3 R( z l- q' g3 |9 |9 v0 L; Z
2.2 配置
& w" Y0 X' j- X1 r% V节点 配置和操作
$ }# ]9 Y' e( M7 d! B7 V控制节点上 - N) c- D0 n: U: F# Z5 k
修改 /etc/neutron/neutron.conf:
' u5 U, S8 r" w2 R$ U }) m5 c[default]! j! e, c8 Y/ s0 ]0 k" B$ [
service_plugins = router,lbaas,firewall8 B1 l* a, I: K- B6 G) Z7 b: O
[service_providers]
& R" j0 e! N# p7 l8 qservice_provider = FIREWALL:Iptables:neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver:default
8 A& N( n4 O$ b9 f( H6 V
2 b/ y. y5 ^: m" G* ~3 ~service neutron-server restart4 n8 x6 |/ w% N& Y' Y
; z; H9 ^; D; K
修改 /usr/share/openstack-dashboard/openstack_dashboard/local/local_settings.py:'enable_firewall': True
% C# E; }9 x D6 p6 P网络节点上
: @# d# M7 v( B8 U; ~/ Q' L9 h修改 /etc/neutron/fwaas_driver.ini:( }, t! f* x1 X4 a k
[fwaas]
2 U! Z- g# u9 ]# bdriver = neutron.services.firewall.drivers.linux.iptables_fwaas.IptablesFwaasDriver, L8 W+ J3 B4 D# v7 f8 D) R
enabled = True/ u3 D; k; x+ V$ A. _8 G
( \& M' D5 ?# Y+ Y, N) W1 xservice neutron-l3-agent restart0 ?% y6 \3 ~' a {+ X
# r( E6 V) x1 m2.3 实现5 M$ P7 q' I2 _% A' z8 e
目前的实现中,FWaas 是通过在其所在 tenant 中的所有 Virtual Router 上添加 iptbales 规则来实现对进出数据网络的网络包进行控制的。; ^( i; Z3 X" T% x: K/ U' ^0 t
' i" x) [( P# Y% D" r( `! i# G
代码实现:
& f9 Z1 X- Q) `: Q! F7 p6 M控制节点上(class FirewallPlugin):; W: @' `$ H4 x
(1)create rule:纯数据库操作,将 rule 保存到数据中。
4 u; S. t' Y; w8 q0 s9 _" a(2)create policy:纯数据库操作,将 policy 保存到数据中。7 v+ Y" J( q; @
(3)如果将 rule 添加到一个已经添加到 firwall 的 policy,或者将一个 policy 加入一个存在的 firewall,在数据库操作后,通过 RPC fanout 到所有的 L3 Agent host:& T& U7 @# a/ j1 d$ M$ j- I; q( J
{'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'}
7 r) ]% C1 Y0 q: c, w: d; Q2 D Rinsert_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% P) h2 j5 J: @1 h9 v; z
create_firewall -> Firewall_db_mixin.create_firewall -> FirewallAgentApi.create_firewall
. m% |7 Z2 L( A$ Eupdate_firewall -> Firewall_db_mixin.update_firewall -> FirewallAgentApi.update_firewall
2 k) @' T; n$ |9 |delete_firewall -> Firewall_db_mixin.delete_firewall -> FirewallAgentApi.delete_firewall
" N4 W! S' R5 b- WFirewallAgentApi.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
8 G, x& r! F( V% L9 S 网络节点上(class FWaaSL3AgentRpcCallback):
# b% [9 [5 {6 b9 u* T8 e(1) 通过 RPC 获取所有的 router,在获取firewall 所在的 tenant 上的 routers
: P! y# ~* {2 ]4 d! x9 W1 H(2)调用 IptablesFwaasDriver.update_firewall,依次更新每个 router 的 iptables 规则" d& p. Q0 d, i
(3)首先删除已有规则,然后根据配置的 rules 重新生成规则 9 g+ X8 z: X/ C# P- j4 `" h
复制代码$ g, B6 w/ t4 h8 p* I& ^
root@network:/var/cache# ip netns exec qrouter-e438bebe-6795-4b68-a613-ec0df38d3064 iptables -t filter -S4 n! B! y: {& e- C9 m
-P INPUT ACCEPT
$ ^% U) y* f/ t5 n4 n-P FORWARD ACCEPT
4 I: |! [: i$ K7 h, |-P OUTPUT ACCEPT
; J5 n( }8 J( ^. t: Q-N neutron-filter-top
" B, L$ x+ T& o2 N-N neutron-l3-agent-FORWARD1 v& S- C" t o8 w2 d2 [+ L" \9 D* l
-N neutron-l3-agent-INPUT1 j% q& |3 I' k
-N neutron-l3-agent-OUTPUT( B( Y. Q0 u6 M
-N neutron-l3-agent-fwaas-defau #新增的 firewall chain
% K) Z, U8 V( U( z5 J6 O* ]-N neutron-l3-agent-iv4aa85bd66 #新增的 firewall chain: U' v! w2 V4 z2 x
-N neutron-l3-agent-local6 r7 a m5 V2 q: [: p' E
-N neutron-l3-agent-ov4aa85bd66 #for firewall5 x4 e1 H! z/ B7 Z6 L' _
-A INPUT -j neutron-l3-agent-INPUT+ R+ S. E$ p' X* f) B, M0 [
-A FORWARD -j neutron-filter-top' S7 u* J% F9 @! g4 Y% W; d
-A FORWARD -j neutron-l3-agent-FORWARD #将 forward 转到 neutron 的chain( W- x$ a- W U2 _# u5 c- f' R4 p; J, e
-A OUTPUT -j neutron-filter-top+ O, A( i9 b, P6 S, e' o: ^+ r, D
-A OUTPUT -j neutron-l3-agent-OUTPUT7 L0 Z' A4 c1 x4 j3 V5 P# p7 {
-A neutron-filter-top -j neutron-l3-agent-local
* n% m3 d. c6 A% k: s, |-A neutron-l3-agent-FORWARD -o qr-+ -j neutron-l3-agent-iv4aa85bd66 #进数据网络的包& T$ F. k7 V a$ d. j' x9 N) r
-A neutron-l3-agent-FORWARD -i qr-+ -j neutron-l3-agent-ov4aa85bd66 #出数据网络的包: \: Q0 W" y E# n1 n) U# F
-A neutron-l3-agent-FORWARD -o qr-+ -j neutron-l3-agent-fwaas-defau #进数据网络的包的默认处理 chain9 o1 k6 T) l+ u( F( O
-A neutron-l3-agent-FORWARD -i qr-+ -j neutron-l3-agent-fwaas-defau #出数据网络的包的默认处理 chain
- `3 i) K& y- o( s/ J" \9 o-A neutron-l3-agent-INPUT -d 127.0.0.1/32 -p tcp -m tcp --dport 9697 -j ACCEPT6 F, W8 P2 M) p: X' D+ S+ g2 h
-A neutron-l3-agent-fwaas-defau -j DROP #默认丢弃没有被以上规则处理的所有包
. m& L8 s& S7 O$ i- ]-A neutron-l3-agent-iv4aa85bd66 -m state --state INVALID -j DROP2 s/ P+ o9 e, R4 k; G7 x
-A neutron-l3-agent-iv4aa85bd66 -m state --state RELATED,ESTABLISHED -j ACCEPT #接受状态为 RELATED, ESTABLISHED (已建立的连接)的包
+ a; d' j8 i% J+ L& O; E-A neutron-l3-agent-iv4aa85bd66 -p tcp -m tcp --dport 80 -j ACCEPT #根据定义的 FWaas rule,接受目的端口为 80 的 tcp 包
a3 i2 z5 t* B T-A neutron-l3-agent-ov4aa85bd66 -m state --state INVALID -j DROP& D& L2 t6 D! c( ]6 ^0 W
-A neutron-l3-agent-ov4aa85bd66 -m state --state RELATED,ESTABLISHED -j ACCEPT5 B( T/ b# f% f$ w
-A neutron-l3-agent-ov4aa85bd66 -p tcp -m tcp --dport 80 -j ACCEPT #根据 FWaas rule,接收目的端口为 80 的 tcp 包( Z! ] ]" |8 G
复制代码" v& d" }0 k' ^! D
|
|