Access Control
OVN provides an extensive ACL implementation to apply security policies to the network. By default, the network has no security policy so you are only limited by routing and NAT.
Please see the ovn-nbctl man pages for more information on how the ACL works. Additionally, please see the ovn-sbctl man pages for the Logical_Flow table documentation for the match expressions to set up filters in your ACL.
In the kvm-compose.yaml file, there is an optional section called acl under the ovn element, which exposes the OVN ACL api. We supply a shortcut to apply a deny all security policy with a low priority to reduce boilerplate code.
The yaml schema is as follows:
acl:
apply_deny_all: false
switches:
sw0:
- direction: to-lport
priority: 10
match: "ip4.src == '10.0.0.10'"
action: allow
The apply_deny_all element defaults to false if not specified.
The switches element is optional, if specified you must specify valid logical switch names that are found in the switches section of the ovn network definition. You can specify a list of ACL per switch. Each ACL requires:
- directioneither
to-lport
from-lport
priority : 0 to 32767 inclusive
match : the filter to match to this rule
- actionone of
allow-related
allow-stateless
allow
drop
pass
reject
Creating and Designing Rules
The OVN ACL rules are very expressive, and some care is necessary to craft the right rule without any unintended side edge cases. We have to consider the contents of the filter in the match section, the direction and the action.
Before setting up any security rules, you must consider how you open up your network traffic. You will likely want to place a drop rule with a low priority as a base, so that you can then open up specifically the traffic flows you want. To do this, you want to specify a generic drop rule with a match such as “ip”. Alternatively, you can specifically block certain traffic flows when you generally want to allow all traffic.
Direction
There are two directions, to-lport and from-lport.
to-lport specifies that the filtering will happen on traffic forwarded to a logical port.
from-lport specifies that the filtering will happen on traffic arriving from a logical port.
There is an important distinction when using these, when you are using the ACL just on a logical switch or when using a port group. If you are just applying the ACL to a logical switch, for to-lport this rule will be applied as it arrives to the logical switch. For from-lport this rule will be applied as it leaves the logical switch. Similarly, for the port group, when the traffic is leaving or arriving at one of the logical ports in the port group.
So in the case of a drop rule, you can think of this as placing the ACL at the start of the packet’s journey (from-lport) or at the end of it’s journey (to-lport). This means if you use to-lport, the packet will still travel all the way up to the logical switch (say there was many hops to reach the destination). Whereas if you use from-lport, the packet will be immediately filtered as it leaves the logical port.
So if you want to create a drop all traffic rule for a logical switch to stop traffic coming in, you will want to use a to-lport with a drop.
Match
The match section is the filter that OVN will apply on every packet. There is an extensive syntax for this, so it is recommended to see the ovn-nbctl documentation for the full list and descriptions. For this documentation, we will discuss how to create a basic filter. Note that these filters may not be the most efficient, but the should be clear in their purpose.
If you want to drop all traffic travelling to logical ports in a specific logical switch (sw0):
sw0:
- direction: to-lport
priority: 1
match: "ip4"
action: drop
The use of to-lport means that the filtering will be triggered when the traffic is destined to the port. We match on just ip4 to catch any ipv4 traffic (you may want to also block ip6 if that is being used). If the filter is matched, then we apply the action which is drop in this case.
If you want to allow traffic with a specific source and destination address:
sw0:
- direction: to-lport
priority: 2
match: "ip4 && ip4.src == 10.0.0.11 && ip4.dst == 10.0.0.12"
action: allow
Similar to the drop rule, we also specify the source and destination explicitly. You can also specify a subnet rather than a specific ip such as 10.0.0.0/24 which is valid syntax.
By combining rules like these, you can shape your traffic in complex ways. These examples would ultimately be time consuming for a large network with complex security requirements. It is recommended to both look at the OVN ACL documentation for more sophisticated syntax, but also to experiment with rules. You can quickly iterate with rules on an existing testbed deployment with the following command:
kvm-compose up -a
Which will remove the existing rules and re-apply the rules in the yaml file. This command will not attempt to rebuild guests or the network.
Additionally, you can also test your rules from guests by either using the ping command to the specific ip address of a guest. Or, you can use netcat for tcp connections since ping would use icmp traffic. You can do this with:
# server with ip 10.0.0.10
nc -l -p 8000
# client
nc 10.0.0.10 8000
Then you can type in any message, press enter and you will see this message appear on the server, if the ACL allowed the traffic.
Action
TODO