ovsfw: fix allowed_address_pairs MAC issue

Current ovsfw implementation does not take care of the different
MACs in allowed_address_pairs with the VM's MAC.
This patch use the following method to fix this issue:
1. Do not check dl_src in table=72 because table=71 has checked
dl_src for Egress.
2. Add all allowed MACs in table=0 and table=73 for Ingress.
3. Do not check dl_dst in table=82 because this check has done
in table=0 and table=73.
4. Delete allowed MACs in table=0 and table=73 when needed.

Change-Id: Iad59096f0c9855ebfd4a0d5b447e73b443d66c1d
Closes-Bug: #1697593
This commit is contained in:
jufeng 2017-06-13 15:13:53 +08:00 committed by Jesse
parent c3c43bedac
commit b7892b16b2
6 changed files with 122 additions and 82 deletions

View File

@ -129,12 +129,14 @@ the second security group. Ports have following attributes:
- ip address: 192.168.0.1 - ip address: 192.168.0.1
- mac address: fa:16:3e:a4:22:10 - mac address: fa:16:3e:a4:22:10
- security group 1: can send icmp packets out - security group 1: can send icmp packets out
- allowed address pair: 10.0.0.1/32, fa:16:3e:8c:84:13
Port 2 Port 2
- plugged to the port 2 in OVS bridge - plugged to the port 2 in OVS bridge
- ip address: 192.168.0.2 - ip address: 192.168.0.2
- mac address: fa:16:3e:24:57:c7 - mac address: fa:16:3e:24:57:c7
- security group 2: can receive icmp packets from security group 1 - security group 2: can receive icmp packets from security group 1
- allowed address pair: 10.1.0.0/24, fa:16:3e:8c:84:14
``table 0`` contains a low priority rule to continue packets processing in ``table 0`` contains a low priority rule to continue packets processing in
``table 60`` aka TRANSIENT table. ``table 0`` is left for use to other ``table 60`` aka TRANSIENT table. ``table 0`` is left for use to other
@ -152,7 +154,9 @@ connections into separate conntrack zones.
table=60, priority=100,in_port=1 actions=load:0x1->NXM_NX_REG5[],load:0x284->NXM_NX_REG6[],resubmit(,71) table=60, priority=100,in_port=1 actions=load:0x1->NXM_NX_REG5[],load:0x284->NXM_NX_REG6[],resubmit(,71)
table=60, priority=100,in_port=2 actions=load:0x2->NXM_NX_REG5[],load:0x284->NXM_NX_REG6[],resubmit(,71) table=60, priority=100,in_port=2 actions=load:0x2->NXM_NX_REG5[],load:0x284->NXM_NX_REG6[],resubmit(,71)
table=60, priority=90,dl_vlan=0x284,dl_dst=fa:16:3e:a4:22:10 actions=load:0x1->NXM_NX_REG5[],load:0x284->NXM_NX_REG6[],resubmit(,81) table=60, priority=90,dl_vlan=0x284,dl_dst=fa:16:3e:a4:22:10 actions=load:0x1->NXM_NX_REG5[],load:0x284->NXM_NX_REG6[],resubmit(,81)
table=60, priority=90,dl_vlan=0x284,dl_dst=fa:16:3e:8c:84:13 actions=load:0x1->NXM_NX_REG5[],load:0x284->NXM_NX_REG6[],resubmit(,81)
table=60, priority=90,dl_vlan=0x284,dl_dst=fa:16:3e:24:57:c7 actions=load:0x2->NXM_NX_REG5[],load:0x284->NXM_NX_REG6[],resubmit(,81) table=60, priority=90,dl_vlan=0x284,dl_dst=fa:16:3e:24:57:c7 actions=load:0x2->NXM_NX_REG5[],load:0x284->NXM_NX_REG6[],resubmit(,81)
table=60, priority=90,dl_vlan=0x284,dl_dst=fa:16:3e:8c:84:14 actions=load:0x2->NXM_NX_REG5[],load:0x284->NXM_NX_REG6[],resubmit(,81)
table=60, priority=0 actions=NORMAL table=60, priority=0 actions=NORMAL
Following ``table 71`` implements arp spoofing protection, ip spoofing Following ``table 71`` implements arp spoofing protection, ip spoofing
@ -185,7 +189,9 @@ Following rules implement arp spoofing protection
:: ::
table=71, priority=95,arp,reg5=0x1,in_port=1,dl_src=fa:16:3e:a4:22:10,arp_spa=192.168.0.1 actions=NORMAL table=71, priority=95,arp,reg5=0x1,in_port=1,dl_src=fa:16:3e:a4:22:10,arp_spa=192.168.0.1 actions=NORMAL
table=71, priority=95,arp,reg5=0x1,in_port=1,dl_src=fa:16:3e:8c:84:13,arp_spa=10.0.0.1 actions=NORMAL
table=71, priority=95,arp,reg5=0x2,in_port=2,dl_src=fa:16:3e:24:57:c7,arp_spa=192.168.0.2 actions=NORMAL table=71, priority=95,arp,reg5=0x2,in_port=2,dl_src=fa:16:3e:24:57:c7,arp_spa=192.168.0.2 actions=NORMAL
table=71, priority=95,arp,reg5=0x2,in_port=2,dl_src=fa:16:3e:8c:84:14,arp_spa=10.1.0.0/24 actions=NORMAL
DHCP and DHCPv6 traffic is allowed to instance but DHCP servers are blocked on DHCP and DHCPv6 traffic is allowed to instance but DHCP servers are blocked on
instances. instances.
@ -207,7 +213,9 @@ combinations. All other packets are dropped.
:: ::
table=71, priority=65,ct_state=-trk,ip,reg5=0x1,in_port=1,dl_src=fa:16:3e:a4:22:10,nw_src=192.168.0.1 actions=ct(table=72,zone=NXM_NX_REG6[0..15]) table=71, priority=65,ct_state=-trk,ip,reg5=0x1,in_port=1,dl_src=fa:16:3e:a4:22:10,nw_src=192.168.0.1 actions=ct(table=72,zone=NXM_NX_REG6[0..15])
table=71, priority=65,ct_state=-trk,ip,reg5=0x1,in_port=1,dl_src=fa:16:3e:8c:84:13,nw_src=10.0.0.1 actions=ct(table=72,zone=NXM_NX_REG6[0..15])
table=71, priority=65,ct_state=-trk,ip,reg5=0x2,in_port=2,dl_src=fa:16:3e:24:57:c7,nw_src=192.168.0.2 actions=ct(table=72,zone=NXM_NX_REG6[0..15]) table=71, priority=65,ct_state=-trk,ip,reg5=0x2,in_port=2,dl_src=fa:16:3e:24:57:c7,nw_src=192.168.0.2 actions=ct(table=72,zone=NXM_NX_REG6[0..15])
table=71, priority=65,ct_state=-trk,ip,reg5=0x2,in_port=2,dl_src=fa:16:3e:8c:84:14,nw_src=10.1.0.0/24 actions=ct(table=72,zone=NXM_NX_REG6[0..15])
table=71, priority=65,ct_state=-trk,ipv6,reg5=0x1,in_port=1,dl_src=fa:16:3e:a4:22:10,ipv6_src=fe80::f816:3eff:fea4:2210 actions=ct(table=72,zone=NXM_NX_REG6[0..15]) table=71, priority=65,ct_state=-trk,ipv6,reg5=0x1,in_port=1,dl_src=fa:16:3e:a4:22:10,ipv6_src=fe80::f816:3eff:fea4:2210 actions=ct(table=72,zone=NXM_NX_REG6[0..15])
table=71, priority=65,ct_state=-trk,ipv6,reg5=0x2,in_port=2,dl_src=fa:16:3e:24:57:c7,ipv6_src=fe80::f816:3eff:fe24:57c7 actions=ct(table=72,zone=NXM_NX_REG6[0..15]) table=71, priority=65,ct_state=-trk,ipv6,reg5=0x2,in_port=2,dl_src=fa:16:3e:24:57:c7,ipv6_src=fe80::f816:3eff:fe24:57c7 actions=ct(table=72,zone=NXM_NX_REG6[0..15])
table=71, priority=10,ct_state=-trk,reg5=0x1,in_port=1 actions=drop table=71, priority=10,ct_state=-trk,reg5=0x1,in_port=1 actions=drop
@ -226,8 +234,8 @@ In case below we allow all icmp egress traffic.
:: ::
table=72, priority=70,ct_state=+est-rel-rpl,icmp,reg5=0x1,dl_src=fa:16:3e:a4:22:10 actions=resubmit(,73) table=72, priority=70,ct_state=+est-rel-rpl,icmp,reg5=0x1, actions=resubmit(,73)
table=72, priority=70,ct_state=+new-est,icmp,reg5=0x1,dl_src=fa:16:3e:a4:22:10 actions=resubmit(,73) table=72, priority=70,ct_state=+new-est,icmp,reg5=0x1, actions=resubmit(,73)
table=72, priority=50,ct_state=+inv+trk actions=drop table=72, priority=50,ct_state=+inv+trk actions=drop
@ -270,7 +278,9 @@ remaining egress connections are sent to normal switching.
:: ::
table=73, priority=100,reg6=0x284,dl_dst=fa:16:3e:a4:22:10 actions=load:0x1->NXM_NX_REG5[],resubmit(,81) table=73, priority=100,reg6=0x284,dl_dst=fa:16:3e:a4:22:10 actions=load:0x1->NXM_NX_REG5[],resubmit(,81)
table=73, priority=100,reg6=0x284,dl_dst=fa:16:3e:8c:84:13 actions=load:0x1->NXM_NX_REG5[],resubmit(,81)
table=73, priority=100,reg6=0x284,dl_dst=fa:16:3e:24:57:c7 actions=load:0x2->NXM_NX_REG5[],resubmit(,81) table=73, priority=100,reg6=0x284,dl_dst=fa:16:3e:24:57:c7 actions=load:0x2->NXM_NX_REG5[],resubmit(,81)
table=73, priority=100,reg6=0x284,dl_dst=fa:16:3e:8c:84:14 actions=load:0x2->NXM_NX_REG5[],resubmit(,81)
table=73, priority=90,ct_state=+new-est,reg5=0x1 actions=ct(commit,zone=NXM_NX_REG6[0..15]),NORMAL table=73, priority=90,ct_state=+new-est,reg5=0x1 actions=ct(commit,zone=NXM_NX_REG6[0..15]),NORMAL
table=73, priority=90,ct_state=+new-est,reg5=0x2 actions=ct(commit,zone=NXM_NX_REG6[0..15]),NORMAL table=73, priority=90,ct_state=+new-est,reg5=0x2 actions=ct(commit,zone=NXM_NX_REG6[0..15]),NORMAL
table=73, priority=80,reg5=0x1 actions=NORMAL table=73, priority=80,reg5=0x1 actions=NORMAL
@ -284,18 +294,18 @@ port. Not tracked packets are sent to obtain conntrack information.
:: ::
table=81, priority=100,arp,reg5=0x1,dl_dst=fa:16:3e:a4:22:10 actions=strip_vlan,output:1 table=81, priority=100,arp,reg5=0x1 actions=strip_vlan,output:1
table=81, priority=100,arp,reg5=0x2,dl_dst=fa:16:3e:24:57:c7 actions=strip_vlan,output:2 table=81, priority=100,arp,reg5=0x2 actions=strip_vlan,output:2
table=81, priority=100,icmp6,reg5=0x1,dl_dst=fa:16:3e:a4:22:10,icmp_type=130 actions=strip_vlan,output:1 table=81, priority=100,icmp6,reg5=0x1,icmp_type=130 actions=strip_vlan,output:1
table=81, priority=100,icmp6,reg5=0x1,dl_dst=fa:16:3e:a4:22:10,icmp_type=131 actions=strip_vlan,output:1 table=81, priority=100,icmp6,reg5=0x1,icmp_type=131 actions=strip_vlan,output:1
table=81, priority=100,icmp6,reg5=0x1,dl_dst=fa:16:3e:a4:22:10,icmp_type=132 actions=strip_vlan,output:1 table=81, priority=100,icmp6,reg5=0x1,icmp_type=132 actions=strip_vlan,output:1
table=81, priority=100,icmp6,reg5=0x1,dl_dst=fa:16:3e:a4:22:10,icmp_type=135 actions=strip_vlan,output:1 table=81, priority=100,icmp6,reg5=0x1,icmp_type=135 actions=strip_vlan,output:1
table=81, priority=100,icmp6,reg5=0x1,dl_dst=fa:16:3e:a4:22:10,icmp_type=136 actions=strip_vlan,output:1 table=81, priority=100,icmp6,reg5=0x1,icmp_type=136 actions=strip_vlan,output:1
table=81, priority=100,icmp6,reg5=0x2,dl_dst=fa:16:3e:24:57:c7,icmp_type=130 actions=strip_vlan,output:2 table=81, priority=100,icmp6,reg5=0x2,icmp_type=130 actions=strip_vlan,output:2
table=81, priority=100,icmp6,reg5=0x2,dl_dst=fa:16:3e:24:57:c7,icmp_type=131 actions=strip_vlan,output:2 table=81, priority=100,icmp6,reg5=0x2,icmp_type=131 actions=strip_vlan,output:2
table=81, priority=100,icmp6,reg5=0x2,dl_dst=fa:16:3e:24:57:c7,icmp_type=132 actions=strip_vlan,output:2 table=81, priority=100,icmp6,reg5=0x2,icmp_type=132 actions=strip_vlan,output:2
table=81, priority=100,icmp6,reg5=0x2,dl_dst=fa:16:3e:24:57:c7,icmp_type=135 actions=strip_vlan,output:2 table=81, priority=100,icmp6,reg5=0x2,icmp_type=135 actions=strip_vlan,output:2
table=81, priority=100,icmp6,reg5=0x2,dl_dst=fa:16:3e:24:57:c7,icmp_type=136 actions=strip_vlan,output:2 table=81, priority=100,icmp6,reg5=0x2,icmp_type=136 actions=strip_vlan,output:2
table=81, priority=95,udp,reg5=0x1,tp_src=67,tp_dst=68 actions=strip_vlan,output:1 table=81, priority=95,udp,reg5=0x1,tp_src=67,tp_dst=68 actions=strip_vlan,output:1
table=81, priority=95,udp6,reg5=0x1,tp_src=547,tp_dst=546 actions=strip_vlan,output:1 table=81, priority=95,udp6,reg5=0x1,tp_src=547,tp_dst=546 actions=strip_vlan,output:1
table=81, priority=95,udp,reg5=0x2,tp_src=67,tp_dst=68 actions=strip_vlan,output:2 table=81, priority=95,udp,reg5=0x2,tp_src=67,tp_dst=68 actions=strip_vlan,output:2
@ -304,25 +314,27 @@ port. Not tracked packets are sent to obtain conntrack information.
table=81, priority=90,ct_state=-trk,ipv6,reg5=0x1 actions=ct(table=82,zone=NXM_NX_REG6[0..15]) table=81, priority=90,ct_state=-trk,ipv6,reg5=0x1 actions=ct(table=82,zone=NXM_NX_REG6[0..15])
table=81, priority=90,ct_state=-trk,ip,reg5=0x2 actions=ct(table=82,zone=NXM_NX_REG6[0..15]) table=81, priority=90,ct_state=-trk,ip,reg5=0x2 actions=ct(table=82,zone=NXM_NX_REG6[0..15])
table=81, priority=90,ct_state=-trk,ipv6,reg5=0x2 actions=ct(table=82,zone=NXM_NX_REG6[0..15]) table=81, priority=90,ct_state=-trk,ipv6,reg5=0x2 actions=ct(table=82,zone=NXM_NX_REG6[0..15])
table=81, priority=80,ct_state=+trk,reg5=0x1,dl_dst=fa:16:3e:a4:22:10 actions=resubmit(,82) table=81, priority=80,ct_state=+trk,reg5=0x1 actions=resubmit(,82)
table=81, priority=80,ct_state=+trk,reg5=0x2,dl_dst=fa:16:3e:24:57:c7 actions=resubmit(,82) table=81, priority=80,ct_state=+trk,reg5=0x2 actions=resubmit(,82)
table=81, priority=0 actions=drop table=81, priority=0 actions=drop
Similarly to ``table 72``, ``table 82`` accepts established and related Similarly to ``table 72``, ``table 82`` accepts established and related
connections. In this case we allow all icmp traffic coming from connections. In this case we allow all icmp traffic coming from
``security group 1`` which is in this case only ``port 1`` with ip address ``security group 1`` which is in this case only ``port 1``.
``192.168.0.1``. The first two rules match on the ip address, and the The first two rules match on the ip packets, and the
next two rules match on the icmp protocol and the destination mac address. next two rules match on the icmp protocol.
These four rules define conjunction flows. These four rules define conjunction flows.
:: ::
table=82, priority=70,ct_state=+est-rel-rpl,ip,reg6=0xfff,nw_src=192.168.0.1 actions=conjunction(2147352552,1/2) table=82, priority=70,ct_state=+est-rel-rpl,ip,reg6=0x284,nw_src=192.168.0.1 actions=conjunction(2147352552,1/2)
table=82, priority=70,ct_state=+new-est,ip,reg6=0xfff,nw_src=192.168.0.1 actions=conjunction(2147352553,1/2) table=82, priority=70,ct_state=+est-rel-rpl,ip,reg6=0x284,nw_src=10.0.0.1 actions=conjunction(2147352552,1/2)
table=82, priority=70,ct_state=+est-rel-rpl,icmp,reg5=0x2,dl_dst=fa:16:3e:24:57:c7 actions=conjunction(2147352552,2/2) table=82, priority=70,ct_state=+new-est,ip,reg6=0x284,nw_src=192.168.0.1 actions=conjunction(2147352553,1/2)
table=82, priority=70,ct_state=+new-est,icmp,reg5=0x2,dl_dst=fa:16:3e:24:57:c7 actions=conjunction(2147352553,2/2) table=82, priority=70,ct_state=+new-est,ip,reg6=0x284,nw_src=10.0.0.1 actions=conjunction(2147352553,1/2)
table=82, priority=70,conj_id=2147352552,ct_state=+est-rel-rpl,ip,reg5=0x2,dl_dst=fa:16:3e:24:57:c7 actions=strip_vlan,output:2 table=82, priority=70,ct_state=+est-rel-rpl,icmp,reg5=0x2 actions=conjunction(2147352552,2/2)
table=82, priority=70,conj_id=2147352553,ct_state=+new-est,ip,reg5=0x2,dl_dst=fa:16:3e:24:57:c7 actions=ct(commit,zone=NXM_NX_REG6[0..15]),strip_vlan,output:2 table=82, priority=70,ct_state=+new-est,icmp,reg5=0x2 actions=conjunction(2147352553,2/2)
table=82, priority=70,conj_id=2147352552,ct_state=+est-rel-rpl,ip,reg5=0x2 actions=strip_vlan,output:2
table=82, priority=70,conj_id=2147352553,ct_state=+new-est,ip,reg5=0x2 actions=ct(commit,zone=NXM_NX_REG6[0..15]),strip_vlan,output:2
table=82, priority=50,ct_state=+inv+trk actions=drop table=82, priority=50,ct_state=+inv+trk actions=drop
The mechanism for dropping connections that are not allowed anymore is the The mechanism for dropping connections that are not allowed anymore is the
@ -332,10 +344,10 @@ same as in ``table 72``.
table=82, priority=50,ct_mark=0x1,reg5=0x1 actions=drop table=82, priority=50,ct_mark=0x1,reg5=0x1 actions=drop
table=82, priority=50,ct_mark=0x1,reg5=0x2 actions=drop table=82, priority=50,ct_mark=0x1,reg5=0x2 actions=drop
table=82, priority=50,ct_state=+est-rel+rpl,ct_zone=644,ct_mark=0,reg5=0x1,dl_dst=fa:16:3e:a4:22:10 actions=strip_vlan,output:1 table=82, priority=50,ct_state=+est-rel+rpl,ct_zone=644,ct_mark=0,reg5=0x1 actions=strip_vlan,output:1
table=82, priority=50,ct_state=+est-rel+rpl,ct_zone=644,ct_mark=0,reg5=0x2,dl_dst=fa:16:3e:24:57:c7 actions=strip_vlan,output:2 table=82, priority=50,ct_state=+est-rel+rpl,ct_zone=644,ct_mark=0,reg5=0x2 actions=strip_vlan,output:2
table=82, priority=50,ct_state=-new-est+rel-inv,ct_zone=644,ct_mark=0,reg5=0x1,dl_dst=fa:16:3e:a4:22:10 actions=strip_vlan,output:1 table=82, priority=50,ct_state=-new-est+rel-inv,ct_zone=644,ct_mark=0,reg5=0x1 actions=strip_vlan,output:1
table=82, priority=50,ct_state=-new-est+rel-inv,ct_zone=644,ct_mark=0,reg5=0x2,dl_dst=fa:16:3e:24:57:c7 actions=strip_vlan,output:2 table=82, priority=50,ct_state=-new-est+rel-inv,ct_zone=644,ct_mark=0,reg5=0x2 actions=strip_vlan,output:2
table=82, priority=40,ct_state=-est,reg5=0x1 actions=drop table=82, priority=40,ct_state=-est,reg5=0x1 actions=drop
table=82, priority=40,ct_state=+est,reg5=0x1 actions=ct(commit,zone=NXM_NX_REG6[0..15],exec(load:0x1->NXM_NX_CT_MARK[])) table=82, priority=40,ct_state=+est,reg5=0x1 actions=ct(commit,zone=NXM_NX_REG6[0..15],exec(load:0x1->NXM_NX_CT_MARK[]))
table=82, priority=40,ct_state=-est,reg5=0x2 actions=drop table=82, priority=40,ct_state=-est,reg5=0x2 actions=drop

View File

@ -113,6 +113,13 @@ class OFPort(object):
return {(aap['mac_address'], aap['ip_address']) for aap in aap_dict return {(aap['mac_address'], aap['ip_address']) for aap in aap_dict
if netaddr.IPNetwork(aap['ip_address']).version == version} if netaddr.IPNetwork(aap['ip_address']).version == version}
@property
def all_allowed_macs(self):
macs = {item[0] for item in self.allowed_pairs_v4.union(
self.allowed_pairs_v6)}
macs.add(self.mac)
return macs
@property @property
def ipv4_addresses(self): def ipv4_addresses(self):
return [ip_addr for ip_addr in self.fixed_ips return [ip_addr for ip_addr in self.fixed_ips
@ -450,12 +457,15 @@ class OVSFirewallDriver(firewall.FirewallDriver):
self._initialize_egress_no_port_security(port['device']) self._initialize_egress_no_port_security(port['device'])
return return
old_of_port = self.get_ofport(port) old_of_port = self.get_ofport(port)
of_port = self.get_or_create_ofport(port) # Make sure delete old allow_address_pair MACs because
# allow_address_pair MACs will be updated in
# self.get_or_create_ofport(port)
if old_of_port: if old_of_port:
LOG.error(_LE("Initializing port %s that was already " LOG.error(_LE("Initializing port %s that was already "
"initialized."), "initialized."),
port['device']) port['device'])
self.delete_all_port_flows(old_of_port) self.delete_all_port_flows(old_of_port)
of_port = self.get_or_create_ofport(port)
self.initialize_port_flows(of_port) self.initialize_port_flows(of_port)
self.add_flows_from_rules(of_port) self.add_flows_from_rules(of_port)
@ -571,21 +581,22 @@ class OVSFirewallDriver(firewall.FirewallDriver):
ovs_consts.BASE_EGRESS_TABLE) ovs_consts.BASE_EGRESS_TABLE)
) )
# Identify ingress flows after egress filtering # Identify ingress flows
self._add_flow( for mac_addr in port.all_allowed_macs:
table=ovs_consts.TRANSIENT_TABLE, self._add_flow(
priority=90, table=ovs_consts.TRANSIENT_TABLE,
dl_dst=port.mac, priority=90,
dl_vlan='0x%x' % port.vlan_tag, dl_dst=mac_addr,
actions='set_field:{:d}->reg{:d},' dl_vlan='0x%x' % port.vlan_tag,
'set_field:{:d}->reg{:d},' actions='set_field:{:d}->reg{:d},'
'strip_vlan,resubmit(,{:d})'.format( 'set_field:{:d}->reg{:d},'
port.ofport, 'strip_vlan,resubmit(,{:d})'.format(
ovsfw_consts.REG_PORT, port.ofport,
port.vlan_tag, ovsfw_consts.REG_PORT,
ovsfw_consts.REG_NET, port.vlan_tag,
ovs_consts.BASE_INGRESS_TABLE), ovsfw_consts.REG_NET,
) ovs_consts.BASE_INGRESS_TABLE),
)
self._initialize_egress(port) self._initialize_egress(port)
self._initialize_ingress(port) self._initialize_ingress(port)
@ -753,16 +764,17 @@ class OVSFirewallDriver(firewall.FirewallDriver):
# Fill in accept_or_ingress table by checking that traffic is ingress # Fill in accept_or_ingress table by checking that traffic is ingress
# and if not, accept it # and if not, accept it
self._add_flow( for mac_addr in port.all_allowed_macs:
table=ovs_consts.ACCEPT_OR_INGRESS_TABLE, self._add_flow(
priority=100, table=ovs_consts.ACCEPT_OR_INGRESS_TABLE,
dl_dst=port.mac, priority=100,
reg_net=port.vlan_tag, dl_dst=mac_addr,
actions='set_field:{:d}->reg{:d},resubmit(,{:d})'.format( reg_net=port.vlan_tag,
port.ofport, actions='set_field:{:d}->reg{:d},resubmit(,{:d})'.format(
ovsfw_consts.REG_PORT, port.ofport,
ovs_consts.BASE_INGRESS_TABLE), ovsfw_consts.REG_PORT,
) ovs_consts.BASE_INGRESS_TABLE),
)
for ethertype in [constants.ETHERTYPE_IP, constants.ETHERTYPE_IPV6]: for ethertype in [constants.ETHERTYPE_IP, constants.ETHERTYPE_IPV6]:
self._add_flow( self._add_flow(
table=ovs_consts.ACCEPT_OR_INGRESS_TABLE, table=ovs_consts.ACCEPT_OR_INGRESS_TABLE,
@ -836,7 +848,6 @@ class OVSFirewallDriver(firewall.FirewallDriver):
table=ovs_consts.BASE_INGRESS_TABLE, table=ovs_consts.BASE_INGRESS_TABLE,
priority=100, priority=100,
reg_port=port.ofport, reg_port=port.ofport,
dl_dst=port.mac,
dl_type=constants.ETHERTYPE_IPV6, dl_type=constants.ETHERTYPE_IPV6,
nw_proto=lib_const.PROTO_NUM_IPV6_ICMP, nw_proto=lib_const.PROTO_NUM_IPV6_ICMP,
icmp_type=icmp_type, icmp_type=icmp_type,
@ -850,7 +861,6 @@ class OVSFirewallDriver(firewall.FirewallDriver):
priority=100, priority=100,
dl_type=constants.ETHERTYPE_ARP, dl_type=constants.ETHERTYPE_ARP,
reg_port=port.ofport, reg_port=port.ofport,
dl_dst=port.mac,
actions='output:{:d}'.format(port.ofport), actions='output:{:d}'.format(port.ofport),
) )
self._initialize_ingress_ipv6_icmp(port) self._initialize_ingress_ipv6_icmp(port)
@ -887,7 +897,6 @@ class OVSFirewallDriver(firewall.FirewallDriver):
ct_state=ovsfw_consts.OF_STATE_TRACKED, ct_state=ovsfw_consts.OF_STATE_TRACKED,
priority=80, priority=80,
reg_port=port.ofport, reg_port=port.ofport,
dl_dst=port.mac,
actions='resubmit(,{:d})'.format(ovs_consts.RULES_INGRESS_TABLE) actions='resubmit(,{:d})'.format(ovs_consts.RULES_INGRESS_TABLE)
) )
@ -914,7 +923,6 @@ class OVSFirewallDriver(firewall.FirewallDriver):
self._add_flow( self._add_flow(
table=ovs_consts.RULES_INGRESS_TABLE, table=ovs_consts.RULES_INGRESS_TABLE,
priority=50, priority=50,
dl_dst=port.mac,
reg_port=port.ofport, reg_port=port.ofport,
ct_state=state, ct_state=state,
ct_mark=ovsfw_consts.CT_MARK_NORMAL, ct_mark=ovsfw_consts.CT_MARK_NORMAL,
@ -995,18 +1003,17 @@ class OVSFirewallDriver(firewall.FirewallDriver):
def delete_all_port_flows(self, port): def delete_all_port_flows(self, port):
"""Delete all flows for given port""" """Delete all flows for given port"""
self._strict_delete_flow( for mac_addr in port.all_allowed_macs:
priority=90, self._strict_delete_flow(priority=90,
table=ovs_consts.TRANSIENT_TABLE, table=ovs_consts.TRANSIENT_TABLE,
dl_dst=port.mac, dl_dst=mac_addr,
dl_vlan=port.vlan_tag) dl_vlan=port.vlan_tag)
self._strict_delete_flow( self._delete_flows(table=ovs_consts.ACCEPT_OR_INGRESS_TABLE,
priority=100, dl_dst=mac_addr, reg_net=port.vlan_tag)
table=ovs_consts.TRANSIENT_TABLE, self._strict_delete_flow(priority=100,
in_port=port.ofport) table=ovs_consts.TRANSIENT_TABLE,
in_port=port.ofport)
self._delete_flows(reg_port=port.ofport) self._delete_flows(reg_port=port.ofport)
self._delete_flows(table=ovs_consts.ACCEPT_OR_INGRESS_TABLE,
dl_dst=port.mac, reg_net=port.vlan_tag)
def delete_flows_for_ip_addresses( def delete_flows_for_ip_addresses(
self, ip_addresses, direction, ethertype, vlan_tag): self, ip_addresses, direction, ethertype, vlan_tag):

View File

@ -77,11 +77,9 @@ def populate_flow_common(direction, flow_template, port):
"""Initialize common flow fields.""" """Initialize common flow fields."""
if direction == firewall.INGRESS_DIRECTION: if direction == firewall.INGRESS_DIRECTION:
flow_template['table'] = ovs_consts.RULES_INGRESS_TABLE flow_template['table'] = ovs_consts.RULES_INGRESS_TABLE
flow_template['dl_dst'] = port.mac
flow_template['actions'] = "output:{:d}".format(port.ofport) flow_template['actions'] = "output:{:d}".format(port.ofport)
elif direction == firewall.EGRESS_DIRECTION: elif direction == firewall.EGRESS_DIRECTION:
flow_template['table'] = ovs_consts.RULES_EGRESS_TABLE flow_template['table'] = ovs_consts.RULES_EGRESS_TABLE
flow_template['dl_src'] = port.mac
# Traffic can be both ingress and egress, check that no ingress rules # Traffic can be both ingress and egress, check that no ingress rules
# should be applied # should be applied
flow_template['actions'] = 'resubmit(,{:d})'.format( flow_template['actions'] = 'resubmit(,{:d})'.format(

View File

@ -398,20 +398,51 @@ class FirewallTestCase(BaseFirewallTestCase):
port_mac = self.tester.vm_mac_address port_mac = self.tester.vm_mac_address
allowed_ip = netaddr.IPAddress(self.tester.vm_ip_address) + 1 allowed_ip = netaddr.IPAddress(self.tester.vm_ip_address) + 1
not_allowed_ip = "%s/24" % (allowed_ip + 1) not_allowed_ip = "%s/24" % (allowed_ip + 1)
allowed_mac = 'fa:16:3e:8c:84:13'
not_allowed_mac = 'fa:16:3e:8c:84:14'
self.src_port_desc['allowed_address_pairs'] = [ self.src_port_desc['allowed_address_pairs'] = [
{'mac_address': port_mac, {'mac_address': port_mac,
'ip_address': "%s/32" % allowed_ip},
{'mac_address': allowed_mac,
'ip_address': "%s/32" % allowed_ip}] 'ip_address': "%s/32" % allowed_ip}]
allowed_ip = "%s/24" % allowed_ip allowed_ip = "%s/24" % allowed_ip
self.firewall.update_port_filter(self.src_port_desc) self.firewall.update_port_filter(self.src_port_desc)
self.tester.assert_connection(protocol=self.tester.ICMP, self.tester.assert_connection(protocol=self.tester.ICMP,
direction=self.tester.INGRESS) direction=self.tester.INGRESS)
self.tester.assert_connection(protocol=self.tester.ICMP,
direction=self.tester.EGRESS)
self.tester.vm_ip_cidr = allowed_ip self.tester.vm_ip_cidr = allowed_ip
self.tester.assert_connection(protocol=self.tester.ICMP, self.tester.assert_connection(protocol=self.tester.ICMP,
direction=self.tester.INGRESS) direction=self.tester.INGRESS)
self.tester.assert_connection(protocol=self.tester.ICMP,
direction=self.tester.EGRESS)
self.tester.vm_ip_cidr = not_allowed_ip self.tester.vm_ip_cidr = not_allowed_ip
self.tester.assert_no_connection(protocol=self.tester.ICMP, self.tester.assert_no_connection(protocol=self.tester.ICMP,
direction=self.tester.INGRESS) direction=self.tester.INGRESS)
self.tester.assert_no_connection(protocol=self.tester.ICMP,
direction=self.tester.EGRESS)
self.tester.vm_mac_address = allowed_mac
self.tester.vm_ip_cidr = allowed_ip
self.tester.flush_arp_tables()
self.tester.assert_connection(protocol=self.tester.ICMP,
direction=self.tester.INGRESS)
self.tester.assert_connection(protocol=self.tester.ICMP,
direction=self.tester.EGRESS)
self.tester.vm_mac_address = allowed_mac
self.tester.vm_ip_cidr = not_allowed_ip
self.tester.flush_arp_tables()
self.tester.assert_no_connection(protocol=self.tester.ICMP,
direction=self.tester.INGRESS)
self.tester.assert_no_connection(protocol=self.tester.ICMP,
direction=self.tester.EGRESS)
self.tester.vm_mac_address = not_allowed_mac
self.tester.vm_ip_cidr = allowed_ip
self.tester.flush_arp_tables()
self.tester.assert_no_connection(protocol=self.tester.ICMP,
direction=self.tester.INGRESS)
self.tester.assert_no_connection(protocol=self.tester.ICMP,
direction=self.tester.EGRESS)
def test_arp_is_allowed(self): def test_arp_is_allowed(self):
self.tester.assert_connection(protocol=self.tester.ARP, self.tester.assert_connection(protocol=self.tester.ARP,

View File

@ -459,7 +459,8 @@ class TestOVSFirewallDriver(base.BaseTestCase):
def test_prepare_port_filter(self): def test_prepare_port_filter(self):
port_dict = {'device': 'port-id', port_dict = {'device': 'port-id',
'security_groups': [1]} 'security_groups': [1],
'fixed_ips': ["10.0.0.1"]}
self._prepare_security_group() self._prepare_security_group()
self.firewall.prepare_port_filter(port_dict) self.firewall.prepare_port_filter(port_dict)
exp_egress_classifier = mock.call( exp_egress_classifier = mock.call(
@ -482,7 +483,6 @@ class TestOVSFirewallDriver(base.BaseTestCase):
filter_rule = mock.call( filter_rule = mock.call(
actions='ct(commit,zone=NXM_NX_REG6[0..15]),' actions='ct(commit,zone=NXM_NX_REG6[0..15]),'
'output:{:d}'.format(self.port_ofport), 'output:{:d}'.format(self.port_ofport),
dl_dst=self.port_mac,
dl_type="0x{:04x}".format(n_const.ETHERTYPE_IP), dl_type="0x{:04x}".format(n_const.ETHERTYPE_IP),
nw_proto=constants.PROTO_NUM_TCP, nw_proto=constants.PROTO_NUM_TCP,
priority=70, priority=70,
@ -528,7 +528,6 @@ class TestOVSFirewallDriver(base.BaseTestCase):
filter_rules = [mock.call( filter_rules = [mock.call(
actions='resubmit(,{:d})'.format( actions='resubmit(,{:d})'.format(
ovs_consts.ACCEPT_OR_INGRESS_TABLE), ovs_consts.ACCEPT_OR_INGRESS_TABLE),
dl_src=self.port_mac,
dl_type="0x{:04x}".format(n_const.ETHERTYPE_IP), dl_type="0x{:04x}".format(n_const.ETHERTYPE_IP),
nw_proto=constants.PROTO_NUM_UDP, nw_proto=constants.PROTO_NUM_UDP,
priority=70, priority=70,
@ -538,7 +537,6 @@ class TestOVSFirewallDriver(base.BaseTestCase):
mock.call( mock.call(
actions='conjunction({:d},2/2)'.format(conj_id), actions='conjunction({:d},2/2)'.format(conj_id),
ct_state=ovsfw_consts.OF_STATE_ESTABLISHED_NOT_REPLY, ct_state=ovsfw_consts.OF_STATE_ESTABLISHED_NOT_REPLY,
dl_src=mock.ANY,
dl_type=mock.ANY, dl_type=mock.ANY,
nw_proto=6, nw_proto=6,
priority=70, reg5=self.port_ofport, priority=70, reg5=self.port_ofport,

View File

@ -186,7 +186,6 @@ class TestCreateProtocolFlows(base.BaseTestCase):
rule = {'protocol': constants.PROTO_NAME_TCP} rule = {'protocol': constants.PROTO_NAME_TCP}
expected_flows = [{ expected_flows = [{
'table': ovs_consts.RULES_INGRESS_TABLE, 'table': ovs_consts.RULES_INGRESS_TABLE,
'dl_dst': self.port.mac,
'actions': 'output:1', 'actions': 'output:1',
'nw_proto': constants.PROTO_NUM_TCP, 'nw_proto': constants.PROTO_NUM_TCP,
}] }]
@ -197,7 +196,6 @@ class TestCreateProtocolFlows(base.BaseTestCase):
rule = {'protocol': constants.PROTO_NAME_TCP} rule = {'protocol': constants.PROTO_NAME_TCP}
expected_flows = [{ expected_flows = [{
'table': ovs_consts.RULES_EGRESS_TABLE, 'table': ovs_consts.RULES_EGRESS_TABLE,
'dl_src': self.port.mac,
'actions': 'resubmit(,{:d})'.format( 'actions': 'resubmit(,{:d})'.format(
ovs_consts.ACCEPT_OR_INGRESS_TABLE), ovs_consts.ACCEPT_OR_INGRESS_TABLE),
'nw_proto': constants.PROTO_NUM_TCP, 'nw_proto': constants.PROTO_NUM_TCP,
@ -209,7 +207,6 @@ class TestCreateProtocolFlows(base.BaseTestCase):
rule = {} rule = {}
expected_flows = [{ expected_flows = [{
'table': ovs_consts.RULES_EGRESS_TABLE, 'table': ovs_consts.RULES_EGRESS_TABLE,
'dl_src': self.port.mac,
'actions': 'resubmit(,{:d})'.format( 'actions': 'resubmit(,{:d})'.format(
ovs_consts.ACCEPT_OR_INGRESS_TABLE), ovs_consts.ACCEPT_OR_INGRESS_TABLE),
}] }]
@ -221,7 +218,6 @@ class TestCreateProtocolFlows(base.BaseTestCase):
'protocol': constants.PROTO_NAME_ICMP} 'protocol': constants.PROTO_NAME_ICMP}
expected_flows = [{ expected_flows = [{
'table': ovs_consts.RULES_EGRESS_TABLE, 'table': ovs_consts.RULES_EGRESS_TABLE,
'dl_src': self.port.mac,
'actions': 'resubmit(,{:d})'.format( 'actions': 'resubmit(,{:d})'.format(
ovs_consts.ACCEPT_OR_INGRESS_TABLE), ovs_consts.ACCEPT_OR_INGRESS_TABLE),
'nw_proto': constants.PROTO_NUM_IPV6_ICMP, 'nw_proto': constants.PROTO_NUM_IPV6_ICMP,
@ -236,7 +232,6 @@ class TestCreateProtocolFlows(base.BaseTestCase):
'port_range_max': 23} 'port_range_max': 23}
expected_flows = [{ expected_flows = [{
'table': ovs_consts.RULES_EGRESS_TABLE, 'table': ovs_consts.RULES_EGRESS_TABLE,
'dl_src': self.port.mac,
'actions': 'resubmit(,{:d})'.format( 'actions': 'resubmit(,{:d})'.format(
ovs_consts.ACCEPT_OR_INGRESS_TABLE), ovs_consts.ACCEPT_OR_INGRESS_TABLE),
'nw_proto': constants.PROTO_NUM_TCP, 'nw_proto': constants.PROTO_NUM_TCP,
@ -353,7 +348,6 @@ class TestCreateConjFlows(base.BaseTestCase):
conj_id = 1234 conj_id = 1234
expected_template = { expected_template = {
'table': ovs_consts.RULES_INGRESS_TABLE, 'table': ovs_consts.RULES_INGRESS_TABLE,
'dl_dst': port.mac,
'dl_type': n_const.ETHERTYPE_IPV6, 'dl_type': n_const.ETHERTYPE_IPV6,
'priority': 70, 'priority': 70,
'conj_id': conj_id, 'conj_id': conj_id,