snabbco / snabb

Snabb: Simple and fast packet networking
Apache License 2.0
2.97k stars 301 forks source link

Create Snabb NFV documentation for Stateful Filtering support #378

Closed lukego closed 9 years ago

lukego commented 9 years ago

The Neutron API Extensions document needs to explain our interpretations of Neutron Security Groups (both stateful and stateless). Generally we need to make sure we have an interpretation that we are happy with and that agrees with the revised PacketFilter API of #375.

eugeneia commented 9 years ago

From Neutron/SecurityGroups (for my own reference and this discussion thread):

Behavior

The basic characteristics of Neutron Security Groups are:

For ingress traffic (to an instance) Only traffic matched with security group rules are allowed. When there is no rule defined, all traffic are dropped.

For egress traffic (from an instance) Only traffic matched with security group rules are allowed. When there is no rule defined, all egress traffic are dropped. When a new security group is created, rules to allow all egress traffic are automatically added.

"default security group" is defined for each tenant. For the default security group a rule which allows intercommunication among hosts associated with the default security group is defined by default. As a result, all egress traffic and intercommunication in the default group are allowed and all ingress from outside of the default group is dropped by default (in the default security group).

It seems like we are not following the spec correctly as of now: AFAIK when no rules are given, we pass all packets instead of dropping them.

Regarding stateful PF: I could only find mention of stateful PF in the referenced AWS docs, which also disagrees with Neutron:

You can specify separate rules for inbound and outbound traffic.

By default, no inbound traffic is allowed until you add inbound rules to the security group.

By default, all outbound traffic is allowed until you add outbound rules to the group (and then, you specify the outbound traffic that's allowed).

Responses to allowed inbound traffic are allowed to flow outbound regardless of outbound rules, and vice versa (security groups are therefore stateful).

Instances associated with a security group can't talk to each other unless you add rules allowing it (exception: the default security group has these rules by default).

E.g.: Stateful by default (outbound responses are allowed by default).

So we could with little changes default to the Neutron spec. Then we could maybe allow a flag in our vif_details extension to implement the AWS stateful behavior? E.g. not expose the more fine grained API of our NFV implementation to Neutron and instead implement the expected behavior(s)?

lukego commented 9 years ago

Great summary!

The Neutron rules are actually stateful even though they don't spell this out. When they talk about "inbound traffic" they are talking about two-way connections that originate with an inbound packet.

I agree that sticking as close to the standard Neutron API as possible makes sense. So the default behaviour should be stateful filtering. Then we should add a vif_details option to request stateless filtering. (And we could keep it in our minds that we probably want to add the ability to use pcap/pflua filter expressions instead of security group rules in the future.)

The three use cases we want to cover are:

  1. No packet filtering.
  2. Neutron security groups without stateful filtering.
  3. Neutron security groups with stateful filtering.

Beyond that it is more important to keep the Neutron interface simple than to expose additional capabilities of our packet filter.

Aside: I am bothered that Neutron default port settings will enable stateful security groups since this is usually not what you want in NFV. (Taking a high-throughput router/firewall/NAT and wrapping it in an additional layer of connection tracking would be madness.) However, I think I need to live with this and that it is better to explain our recommended configuration methods instead of changing the Neutron API semantics.

@n-nikolaev has written an end-to-end OpenStack test suite for our API extensions that will need to be updated too.

eugeneia commented 9 years ago

The Neutron rules are actually stateful even though they don't spell this out. When they talk about "inbound traffic" they are talking about two-way connections that originate with an inbound packet.

@javierguerragiraldez So does our PF app actually support connection tracking across PF apps? E.g. start tracking a connection in the ingress PF and pass packets based on that tracking in the egress PF?

javierguerragiraldez commented 9 years ago

So does our PF app actually support connection tracking across PF apps?

Yes, that's why I put the tracking in named tables. Just use the same name on both ingress and egress PF apps.

eugeneia commented 9 years ago

Ah-ha! :)

lukego commented 9 years ago

This sounds like the right model for us: one state table per virtio port i.e. per pair of ingress/egress packet filter apps.

(Our Neutron docs will have to spell out the fact that state is tracked individually per virtio port, just in case there is ever a situation where that presents a potential problem for somebody.)

eugeneia commented 9 years ago
  1. No packet filtering.

E.g. without Neutron since Neutron specifies that no rules == no packets, right?

  1. Neutron security groups without stateful filtering.
  2. Neutron security groups with stateful filtering.

I now check for the vif_details.stateless_pf field, to determine if PF should be stateless.

_Edit: Maybe the field should be called "filtermode" and contain "stateful"/"stateless"/"to be invented" while defaulting to "stateful".

If vif_details.stateless_pf is a false value, then the returned PacketFilter config will contain state_track=<port.id> and state_check=<port.id> (in both ingress and egress filters). If I understand this correctly that means:

Right? Wrong?

I removed the (previously mentioned) check for #rules > 0 and always return a PacketFIlter configuration because Neutron specifies:

When there is no rule defined, all traffic are dropped.

My WIP branch: https://github.com/eugeneia/snabbswitch/compare/stateful-nfv-pf

javierguerragiraldez commented 9 years ago

If vif_details.stateless_pf is a false value, then the returned PacketFilter config will contain state_track=<port.id> and state_check=<port.id> (in both ingress and egress filters). If I understand this correctly that means:

  • If the port establishes an egress connection to a client, the client's packets on that connection will pass regardless of the port's ingress rules.
  • If a client establishes an ingress connection to the port, the port's packets on that connection will pass regardless of the port's egress rules.

Right? Wrong?

Right.

In the 'global' part (not as part of any rule), the state_track=... is applied after the rules and tracks packets that pass any rule, while the state_check=... is applied before the rules, and passes (without further checking) packets that match a tracked connection.

lukego commented 9 years ago

I added a Stateless Packet Filtering section to our Neutron API Extensions document.

@eugeneia Does this look okay to you? (If yes then can you hack neutron2snabb and nfvconfig etc to make it so?)

lukego commented 9 years ago

Closing this issue as resolved.

The Neutron API Extensions page documents our packet filtering behavior. The default behavior is stateful filtering and no special explanation of that is required because it is the same as the normal Neutron behavior (not an extension). The stateless mode is optional and is documented as an extension.