On 3/23/14, 10:08 AM, Michael Sierchio wrote:
Thanks, Julian, this is sort of independent confirmation of something
I've been doing.  I've heard folks complain about efficiency of NAT
(more so when using natd/DIVERT), and then saw that they matched every
packet on a nat rule - 2 or 4 times.

Some things I abstract from this:

Use tables for lists of addresses where there's more than 5 or so.
I think tables are not as expensive as people think.. it's basically a single routing table lookup. The funtionality added by allowing rule sets to stay, while changing behaviour makes it worth using them even with 1 or 0 entries. We really should try profile ipfw..
I've never done that.. any profiling experts on the list?   :-)

I have not got my head fully around the lookup command yet or using interfaces
as table keys (I can't use that at work in 8.0 anyhow)
ipfw add 100 ipfw skipto tablearg ip from any to any recv 'table(10)' in but we should see if it gives us any performance advantage over a simple hardcoded
filter like I used in my set.
I'd also like to have a number of local variables that you can set on each packet..
tags come close and maybe we should look to see what they can do for us,
but



Use skipto (judiciously)
In static rulesets, skipto is fast since they are not 'computed' the destination is cached, and
the cache is only cleared when new rules are added or removed.
using a tablearg for a skipto is unfortunately not so good as it can not
cache the result and must therefore actually traverse the set looking for the target. (unless someone has added a table for rules that I missed since I last loooked.)



Use stateless and stateful rules appropriately
Basically in my experience, you can not use stateful behaviour on sessions that use NAT,
So you need to separate them out.
However you still get statefull behaviour because libalias uses a similar state table internally, meaning that incoming packets must match some session already started in an outgoing direction,
or a specifically re-arranged translation.

I would really like to have multiple state tables as mentioned earlier..
another thing for the 'todo' file I guess, or maybe the ability to add an entry to a table dynamically..

 # stash away the address of our ntp servers in table 3
e.g. ipfw add 1000 table_add_dest 3 udp from me to any 123  out xmit xn0


Stick to some convention for tables - 13 for bogons, 0 for whitelist
RFC1918 addrs, 1 for whitelist public addrs, etc.

we could make such a standard doc.. and put it in the rc.firewall code speaks loudest.

Separate processing of packets coming in versus going out
I really think this is important. rule requirements are very different for in and out. I further divide each into "for us" or "for other" on incoming, and "from us" or
"from other" on outgoing. these rulesets are also usually very different.
One difficulty I have thugh is handling alias addresses, and packets that have
been redirected to go out an interface that doesn't match the from address
it has, even though it was locally generated. I haven't found a way to say "was locally generated" other than "from me" which is expensive.. "me" is a fairly expensive lookup, and depends on a field that could have come from externally, (unless one has good anti-spoof
rules in place early in the set I guess.
<my own opinions below>

I have a function in the shell script that loads tables fro named
files - the contents of tables change without changing the ruleset.
yes, a good reason to use tables.


Packets not destined for "me" will be processed again when they're
headed out - you can "allow ip from any to any in" after filtering for
the things you do/don't want for "me" - which is the norm for a
firewall router protecting internal nets.  This is, of course, after
early drop for traffic that is obviously "bad"

I only do this on 'trusted' interfaces. I tend to trust on outgoing and filter on incoming more. but it's an interesting thought. I hadn't really considered that. another nice -to-have would be a filter point for routed traffic, just as it is routed.. (see the diagram in the man page). it's possible we could simulateit on output if we could see if packets have been routed or not,
sort of the inverse of the "locally generated" test.



Use rulesets and matching tables to permit atomic table replacement
with rule swap
I do this.. at $JOB I just wrote an ipfw set that is the same regardless of which configuration teh device is put in but rules come and go using set enable/disable as options are turned on/off. but disabled rules still have a cost I believe as hey still need to be traversed,
unless someone has been very smart..

I also do policy-based routing with setfib and table arg, which means
that as conditions change, I can send traffic from a particular net
out a different interface.
It's a pitty that you need to do policy based routing only on input,
as output packets are already past their routing decision.
The 'fwd' rule can however sometimes be used later.

/sbin/ipfw add set 1 05000 setfib tablearg ip from table\(1\) to any
in lookup src-ip 1
yes there is a reason I added fibs, and the ipfw rules to manipulate packet fibs.
:-)

NAT is something that should happen first on all packets incoming on
an if and last on packets headed out an if - with few exceptions.
"Last" except for a final decision to pass or deny the traffic.
I find that you can bypass NAT for all locally generated sessions by having local packet rules before the NAT. depending on whether the machine in question is a large user of the internet,
or just a router, that may be a big saving or not.


- M
_______________________________________________
freebsd-ipfw@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-ipfw
To unsubscribe, send any mail to "freebsd-ipfw-unsubscr...@freebsd.org"


_______________________________________________
freebsd-ipfw@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-ipfw
To unsubscribe, send any mail to "freebsd-ipfw-unsubscr...@freebsd.org"

Reply via email to