kompics/kompact

BlockList / AllowList in the Network

adamhass opened this issue · 3 comments

Allow kompact users to control which IP's/IP:port combinations/subnets are allowed to connect to systems.

@haraldng

I had some thoughts about the details of the implementation we want to end up with for this.

Basically, we said that we want to be able to define rules at different granularity, e.g.:

  • BLOCK/ALLOW 192.168.0.0/255.255.0.0 (i.e. all IPs in 192.168.0.0 - 192.168.255.255)
  • BLOCK/ALLOW 192.168.0.1 (i.e. all connections from one IP)
  • BLOCK/ALLOW 192.168.0.1:23456 (i.e. only connections from a specific IP+port)

Essentially, we always want the most specific rule to apply.

For example, if we have rules BLOCK 192.168.0.0/255.255.0.0 and ALLOW 192.168.0.1:23456 then connections from 192.168.0.1:23456 should be allowed, but e.g. 192.168.0.1:23457 would be blocked as would all other IPs in that range.

So the way I'm thinking to go about this, is that we assign a numerical "specificity" value to reach rule. Clearly something like 192.168.0.1:23456 has the highest specificity (well, we could add transport protocol as well, I suppose) and * (i.e. 0.0.0.0/0.0.0.0) has the lowest specificity.

Given this, we can store rules by their specificity. If we were expecting A LOT of rules some kind of tree would likely be sensible, with the most specific rules at the leaves and less specific rules in the nodes. But I'm thinking most people probably won't have more than a couple of rules, so maybe a simple sorted Vec will do. We search via linear scan from the most specific side until we find a rule that matches, which is thus the most specific rule.

There is one kind of ambiguity left after specificity: What to do if someone specifies both ALLOW 192.168.0.1 and BLOCK 192.168.0.1? I'm thinking we should detect that during insert and simply eliminate the rule. I.e. ALLOW and BLOCK cancel each other out and then the next less specific rule will then apply. This is also consistent with the current API from @haraldng where we block/unblock specific nodes.

I guess one remaining question about this mechanism would be if we also want to allow rules like ALLOW 192.168.0.0/255.255.0.0:8080, because this makes the specificity not quite linear anymore, i.e. there might be multiple rules that apply. How do you compare ALLOW 192.168.0.0/255.255.0.0:8080 vs. BLOCK 192.168.0.1? Which is more specific?
I'm thinking to disallow these kinds of rules to keep the mechanism simple. If someone really needs a very powerful mechanism for this, they should be using a firewall in front of Kompact.

I agree that having a tree is an overkill and using a sorted vec is sufficient. And I suppose when two rules with the lowest specificity cancel each other we pick the latest one? I.e. BLOCK -> ALLOW results in ALLOW but ALLOW -> BLOCK results in BLOCK.

I agree that having a tree is an overkill and using a sorted vec is sufficient. And I suppose when two rules with the lowest specificity cancel each other we pick the latest one? I.e. BLOCK -> ALLOW results in ALLOW but ALLOW -> BLOCK results in BLOCK.

No we remove them completely. We shouldn't even enter rules that cancel each other out into the list. We should detect this situation during insert of the second one and then remove the first one.

For example, say you got the following 2 rules:

  • ALLOW *
  • BLOCK 192.168.0.1

and then you try to add ALLOW 192.168.0.1. What should happen is that we remove BLOCK 192.168.0.1 from the list completely and only ALLOW * applies from then on.

I think that is sensible behaviour with respect to the idea that BLOCK and ALLOW are inverses of each other.