On Fri, Nov 01, 2002 at 02:14:58AM +1000, loki wrote: > rather than having an "embryo" flag on a rule tho, id make it its own > directive and have it before the normal filter rules, therefore evaluated > before the normal rules. state is checked before rules. since embryo > states are almost states, it makes sense to me that they get checked > before the rules as well.
I don't think adding such a mechanism to the rule set improves performance, quite the opposite. A single pointer comparison (for an empty tree of embryonic states) is about as cheap as it gets. Look at what already happens for each packet going through the packet filter, an additional single comparison is just a tiny fraction. If we'd argue about half a dozen cpu instructions, we could gain a lot more by removing a single byte/packet counter. What does pfctl -si show for 'Counters, match'? 1000 rule set evaluations per second? That would mean 1000 additional pointer comparisons per second. Now benchmark how many such comparisons you can do per second without increasing cpu load by more than 1%, on a 486/133 if you like :) The point of an embryonic state inserted by a proxy is that it's an exception from the static filter policy. If you could allow these connections using a static rule set, there would be no need for embryonic states. If you can't, you also have troubles expressing, statically, _what_ embryonic states to allow. A proxy making use of such a feature would require access to /dev/pf and it would have to be written as carefully as authpf, for instance. > having such a rule (or rules) has several other advantages, you could > create several trees, one for each proxy that requires it (include a > mechanism for the proxy to talk to its own tree). you could specify which > field of the state entry is variable (id still say that remote src port > would be th only one, but its nice to be flexible). you could specify tcp > flags and state modulation. whatever is needed for connections created by > the proxy. I can't think of a case where anything but the source port is missing, actually. And of course an embryonic state could hold any information a normal state can (like address translations, timeout values, etc.) or any information otherwise read from the rule that creates an ordinary state (like modulation, route-to, etc.) The proxy wouldn't need to do anything but insert an embryonic state (no enumeration, reading or changing of tree nodes), specifying a timeout value after which it's removed if not completed. The whole kernel part shouldn't get larger than a couple of lines, and the only change relevant for userland would be an additional ioctl. There's another way of comparing performance: if you're using embryonic states with a proxy, you're dealing with connections you want to allow. You want the firewall to create state and pass the packets of that connection. Creating a state entry from an embryonic state after doing a normal state lookup (failing) and a lookup in the embryonic state table is generally cheaper than walking the rule set and creating state in that way (assuming you could express a pass keep state rule there for such connections). If your embyonic state table constantly contains several thousand entries, the lookup for each new connection will of course have an impact. The question, in such a setup, is how many times an embryonic state matches and becomes a normal state, saving a rule set evaluation (which would always follow a failed state table lookup). I guess it boils down to the ratio of expected proxy connections vs. newly created normal states (or blocked connections) per second. Daniel