topo
outside network
|
|
|
+----------------+------------------------------+
| eth1 |
| |
| sw outside |
| |
| outside-edge1 |
+----------------------+-----------------------+
|
|
|
+----------------------------------------------+
| edge1-outside |
| 02:0a:7f:00:01:29 10.127.0.129 |
| |
| Gateway router edge1 |
| |
| 02:ac:10:ff:00:01 172.16.255.1 |
| edge1-transit |
+----------------------+-----------------------+
|
|
|
+----------------------+-----------------------+
| transit-edge1 |
| |
| sw transit |
| 172.16.255.0/30 |
| |
| transit-tenant1 |
+----------------------+-----------------------+
|
|
|
+----------------------+------------------------------------------------------+
| router tenant1 |
| |
| |
| 02:ac:10:ff:01:29 02:ac:10:ff:01:93 |
| 172.16.255.129 172.16.255.193 |
| tenant1-dmz tenant1-inside |
+----+----------------------------------------------------------+-------------+
| |
| |
| |
+----+------------------------------+ +-----------------+-------------+
| dmz-tenant1 | | inside-tenant1 |
| | | |
| sw dmz | | sw inside |
| 172.16.255.128/26 | | 172.16.255.192/26 |
| | | |
| dmz-vm1 dmz-vm2 | | inside-vm1 inside-vm2 |
+-----+-----------------------+-----+ +-------+--------------+--------+
| | | |
| | | |
| | | |
+-----+------------+ +-------+-----------+ +--------+--------+ +-+----------------+
| 02:ac:10:ff:01:30| | 02:ac:10:ff:01:31 | |02:ac:10:ff:01:94| | 02:ac:10:ff:01:95|
| 172.16.255.130 | | 172.16.255.131 | | 172.16.255.194 | | 172.16.255.195 |
| vm1 | | vm2 | | vm3 | | vm4 |
+------------------- +-------------------+ +-----------------+ +------------------+
在实验三环境的基础上做下面的额外配置。
概念
在出站和入站方向都支持使用ACL:
入站:从工作负载(from-lport)进入逻辑端口(从虚拟机出来进入逻辑网络)
出站:从逻辑端口出去到工作负载(to-lport)(从逻辑网络出去,进入虚拟机)。
此外,为每个ACL分配一个优先级,以确定它们的匹配顺序,最高优先级首先被匹配。另外ACL可以被赋予相同的优先级。
然而,在两个具有相同优先级并且都匹配同一个分组的ACL的情况下,将仅匹配一个ACL。
确切地说,哪一个ACL最终将被匹配是不确定的,你不能真正地确定哪个规则将应用于给定的情况。所以我建议:在大多数情况下尽量使用不同的优先级。
ACL中的匹配规则基于OVS中的流语法,对于具有编程背景的人都会觉得很熟悉。该语法在ovn-sb手册页的“Logical_Flow表”部分中进行了说明。它值得一读,特别是介绍“!=”匹配规则的那部分内容。
另外值得强调的一点是,您不能在具有type = router的端口上创建ACL匹配规则。
为了减少ACL表中的条目数,可以使用定义相同类型地址组的地址集。
例如,一组IPv4地址/网络,一组MAC地址或一组IPv6地址可以放置在命名地址集内。
然后地址集可以被ACL的match子句内的“name”引用(以$ name的形式)。
#允许来自交换机“ls1”上端口“ls1-vm1”的所有ip流量,同时允许相关回包通过
ovn-nbctl acl-add ls1 from-lport 1000 "inport == \"ls1-vm1\" && ip" allow-related
# 允许 ssh 到 ls1-vm1
ovn-nbctl acl-add ls1 to-lport 999 "outport == \"ls1-vm1\" && tcp.dst == 22" allow-related
# 阻止所有到ls1-vm1的IPv4/IPv6流量
ovn-nbctl acl-add ls1 to-lport 998 "outport == \"ls1-vm1\" && ip" drop
注意“allow-related”的使用。 它的作用是这样:它允许反向相关的流量(例如,响应,fragements等)通过。 在第二条规则中,为了允许从服务器回来的SSH响应流量通过,我就使用了 allow-related 。
我们再来看看地址集。 如前文所述,地址集是相同类型的地址组。 使用ovn-nbctl北向数据库命令创建地址集,然后在ACL中调用地址集。 这里有几个创建地址集的例子:
ovn-nbctl create Address_Set name=wwwServers addresses=172.16.1.2,172.16.1.3
ovn-nbctl create Address_Set name=www6Servers addresses=\"fd00::1\",\"fd00::2\"
ovn-nbctl create Address_Set name=macs addresses=\"02:00:00:00:00:01\",\"02:00:00:00:00:02\"
注意使用带有包含‘:’字符的地址集的双引号。 如果你在命令中不使用双引号,将会报错。
实验
# 通过为每个服务器创建一个静态NAT规则来允许从外部访问DMZ中的服务器。
# 为vm1创建snat-dnat规则并应用于edge1
ovn-nbctl -- --id=@nat create nat type="dnat_and_snat" logical_ip=172.16.255.130 external_ip=10.127.0.250 -- add logical_router edge1 nat @nat
# 为vm2创建snat-dnat规则并应用于edge1
ovn-nbctl -- --id=@nat create nat type="dnat_and_snat" logical_ip=172.16.255.131 external_ip=10.127.0.251 -- add logical_router edge1 nat @nat
# 此时里外都能主动访问对方。
# 添加默认ACL策略(对不匹配任何转发规则的流量进行丢弃)
ovn-nbctl acl-add dmz to-lport 900 "outport == \"dmz-vm1\" && ip" drop
ovn-nbctl acl-add dmz to-lport 900 "outport == \"dmz-vm2\" && ip" drop
# 此时里外都不能访问对方
# 允许所有ip流量和相关连接回包通过
ovn-nbctl acl-add dmz from-lport 1000 "inport == \"dmz-vm1\" && ip" allow-related
ovn-nbctl acl-add dmz from-lport 1000 "inport == \"dmz-vm2\" && ip" allow-related
# 此时虚拟机可以主动访问外面
# 允许外部到DMZ服务器的入站HTTPS (tcp 443端口)和回包流量:
ovn-nbctl acl-add dmz to-lport 1000 "outport == \"dmz-vm1\" && tcp.dst == 443" allow-related
ovn-nbctl acl-add dmz to-lport 1000 "outport == \"dmz-vm2\" && tcp.dst == 443" allow-related
实验二
接下来的操作会使它更加安全:阻止所有出站访问,并且只允许从dmz访问tcp 3306。
我们将配置一个地址集来表示DMZ内的一些地址。
注意在“acl-add”命令中使用了单引号。
我们实际上是通过地址集名称来引用它,前缀是一个'$'字符。
因为我们不希望bash将其解释为一个变量,所以我们使用了单引号。
# 为dmz服务器创建一个地址集。 使用/31掩码
ovn-nbctl create Address_Set name=dmz addresses=\"172.16.255.130/31\"
# 允许源IP为dmz地址集内的IP地址,且目标端口为3306
ovn-nbctl acl-add inside to-lport 1000 'outport == "inside-vm3" && ip4.src == $dmz && tcp.dst == 3306' allow-related
ovn-nbctl acl-add inside to-lport 1000 'outport == "inside-vm4" && ip4.src == $dmz && tcp.dst == 3306' allow-related
# 添加默认ACL策略(对不匹配任何转发规则的流量进行丢弃)
ovn-nbctl acl-add inside to-lport 900 "outport == \"inside-vm3\" && ip" drop
ovn-nbctl acl-add inside to-lport 900 "outport == \"inside-vm4\" && ip" drop
# 只有vm1和vm2能访问vm3和vm4
# vm3和vm4不能互相访问。