[ovs-dev] [PATCH v3 3/3] ovn: Apply ACL changes to existing connections.

Ben Pfaff blp at ovn.org
Wed Mar 23 20:50:16 UTC 2016


On Mon, Mar 21, 2016 at 10:54:59AM -0400, Russell Bryant wrote:
> Prior to this commit, once a connection had been committed to the
> connection tracker, the connection would continue to be allowed, even
> if the policy defined in the ACL table changed.  This patch changes
> the implementation so that existing connections are affected by policy
> changes.
> 
> The implementation is based on the suggested approach in this mailing
> list thread:
> 
>     http://openvswitch.org/pipermail/dev/2016-February/065716.html
> 
> Instead of always allowing packets associated with an established
> connection, we now put all packets in the request direction through
> the flows generated based on OVN ACLs.  If a packet associated with an
> established connection hits a "drop" ACL, that means we have
> encountered a policy change and should drop packets associated with
> this connection from now on.  We handle this by setting "ct_label" on
> the associated connection tracking entry.
> 
> These changes also account for re-allowing a known connection after
> ct_label had been set on it. This can happen if you delete an ACL and
> then re-create it while connection state is still known.
> 
> The proposal on the mailing list also discussed the idea that
> ovn-controller could periodically sweep the connection tracker and
> delete entries with ct_label set.  That is not implemented in this
> patch.  Instead, we rely on connections dying since we're dropping
> its packets and then allowing the connection tracking entry to
> eventually time out.  More proactively clearing them out could be a
> future enhancement.
> 
> As a realistic example of how this works, consider this security policy
> from an OpenStack+OVN development environment.
> 
>     +---------+-----------------------+
>     | name    | security_group_rules  |
>     +---------+-----------------------+
>     | default | egress, IPv4          |
>     |         | egress, IPv6          |
>     |         | ingress, IPv4, 22/tcp |
>     |         | ingress, IPv4, icmp   |
>     +---------+-----------------------+
> 
> The OpenStack Neutron plugin creates ACLs that drop traffic by default
> and higher priority ACLs for each type of traffic that is allowed.  In
> this case, the ACLs for a port using the "default" security group are:
> 
>   from-lport  1002 (inport == "0a7409c8-d179-4915-9eb2-f53426ae16dd" && ip4) allow-related
>   from-lport  1002 (inport == "0a7409c8-d179-4915-9eb2-f53426ae16dd" && ip6) allow-related
>   from-lport  1001 (inport == "0a7409c8-d179-4915-9eb2-f53426ae16dd" && ip) drop
>     to-lport  1002 (outport == "0a7409c8-d179-4915-9eb2-f53426ae16dd" && ip4 && icmp4) allow-related
>     to-lport  1002 (outport == "0a7409c8-d179-4915-9eb2-f53426ae16dd" && ip4 && tcp && tcp.dst == 22) allow-related
>     to-lport  1001 (outport == "0a7409c8-d179-4915-9eb2-f53426ae16dd" && ip) drop
> 
> which results in the following logical flows:
> 
> ...
>   table=1(   ls_in_pre_acl), priority=  100, match=(ip), action=(ct_next;)
>   table=1(   ls_in_pre_acl), priority=    0, match=(1), action=(next;)
>   table=2(       ls_in_acl), priority=65535, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_label[0] == 0), action=(next;)
>   table=2(       ls_in_acl), priority=65535, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label[0] == 0), action=(next;)
>   table=2(       ls_in_acl), priority=65535, match=(ct.inv || (ct.est && ct.rpl && ct_label[0] == 1)), action=(drop;)
>   table=2(       ls_in_acl), priority= 2002, match=(!ct.new && ct.est && !ct.rpl && ct_label[0] == 0 && (inport == "0a7409c8-d179-4915-9eb2-f53426ae16dd" && ip4)), action=(next;)
>   table=2(       ls_in_acl), priority= 2002, match=(!ct.new && ct.est && !ct.rpl && ct_label[0] == 0 && (inport == "0a7409c8-d179-4915-9eb2-f53426ae16dd" && ip6)), action=(next;)
>   table=2(       ls_in_acl), priority= 2002, match=(((ct.new && !ct.est) || (!ct.new && ct.est && !ct.rpl && ct_label[0] == 1)) && (inport == "0a7409c8-d179-4915-9eb2-f53426ae16dd" && ip4)), action=(ct_commit(ct_label=0); next;)
>   table=2(       ls_in_acl), priority= 2002, match=(((ct.new && !ct.est) || (!ct.new && ct.est && !ct.rpl && ct_label[0] == 1)) && (inport == "0a7409c8-d179-4915-9eb2-f53426ae16dd" && ip6)), action=(ct_commit(ct_label=0); next;)
>   table=2(       ls_in_acl), priority= 2001, match=((!ct.est || (ct.est && ct_label[0] == 1)) && (inport == "0a7409c8-d179-4915-9eb2-f53426ae16dd" && ip)), action=(drop;)
>   table=2(       ls_in_acl), priority= 2001, match=(ct.est && ct_label[0] == 0 && (inport == "0a7409c8-d179-4915-9eb2-f53426ae16dd" && ip)), action=(ct_commit(ct_label=1);)
>   table=2(       ls_in_acl), priority=    1, match=(ip && (!ct.est || (ct.est && ct_label[0] == 1))), action=(ct_commit(ct_label=0); next;)
>   table=2(       ls_in_acl), priority=    0, match=(1), action=(next;)
> ...
>   table=0(  ls_out_pre_acl), priority=  100, match=(ip), action=(ct_next;)
>   table=0(  ls_out_pre_acl), priority=    0, match=(1), action=(next;)
>   table=1(      ls_out_acl), priority=65535, match=(!ct.est && ct.rel && !ct.new && !ct.inv && ct_label[0] == 0), action=(next;)
>   table=1(      ls_out_acl), priority=65535, match=(ct.est && !ct.rel && !ct.new && !ct.inv && ct.rpl && ct_label[0] == 0), action=(next;)
>   table=1(      ls_out_acl), priority=65535, match=(ct.inv || (ct.est && ct.rpl && ct_label[0] == 1)), action=(drop;)
>   table=1(      ls_out_acl), priority= 2002, match=(!ct.new && ct.est && !ct.rpl && ct_label[0] == 0 && (outport == "0a7409c8-d179-4915-9eb2-f53426ae16dd" && ip4 && icmp4)), action=(next;)
>   table=1(      ls_out_acl), priority= 2002, match=(!ct.new && ct.est && !ct.rpl && ct_label[0] == 0 && (outport == "0a7409c8-d179-4915-9eb2-f53426ae16dd" && ip4 && tcp && tcp.dst == 22)), action=(next;)
>   table=1(      ls_out_acl), priority= 2002, match=(((ct.new && !ct.est) || (!ct.new && ct.est && !ct.rpl && ct_label[0] == 1)) && (outport == "0a7409c8-d179-4915-9eb2-f53426ae16dd" && ip4 && icmp4)), action=(ct_commit(ct_label=0); next;)
>   table=1(      ls_out_acl), priority= 2002, match=(((ct.new && !ct.est) || (!ct.new && ct.est && !ct.rpl && ct_label[0] == 1)) && (outport == "0a7409c8-d179-4915-9eb2-f53426ae16dd" && ip4 && tcp && tcp.dst == 22)), action=(ct_commit(ct_label=0); next;)
>   table=1(      ls_out_acl), priority= 2001, match=((!ct.est || (ct.est && ct_label[0] == 1)) && (outport == "0a7409c8-d179-4915-9eb2-f53426ae16dd" && ip)), action=(drop;)
>   table=1(      ls_out_acl), priority= 2001, match=(ct.est && ct_label[0] == 0 && (outport == "0a7409c8-d179-4915-9eb2-f53426ae16dd" && ip)), action=(ct_commit(ct_label=1);)
>   table=1(      ls_out_acl), priority=    1, match=(ip && (!ct.est || (ct.est && ct_label[0] == 1))), action=(ct_commit(ct_label=0); next;)
>   table=1(      ls_out_acl), priority=    0, match=(1), action=(next;)
> ...
> 
> One way I tested this by leaving ping running, ensuring that it was
> blocked when the rule for ICMP was deleted, and then re-allowed when
> the rule allowing ICMP was restored.  In this case, the ICMP
> connection is still known by the connection tracker, but the flows
> ensure that ct_label gets reset back to 0.
> 
> Reported-by: Xiao Li Xu <xiaolixu at cn.ibm.com>
> Reported-at: https://bugs.launchpad.net/networking-ovn/+bug/1536080
> Suggested-by: Justin Pettit <jpettit at ovn.org>
> Signed-off-by: Russell Bryant <russell at ovn.org>
> Acked-by: Han Zhou <zhouhan at gmail.com>

Thanks for doing all this work!

Acked-by: Ben Pfaff <blp at ovn.org>



More information about the dev mailing list