In article <[EMAIL PROTECTED]>,
Brad Chapman  <[EMAIL PROTECTED]> wrote:
>Mr. Blaxell,
>--- Zygo Blaxell <[EMAIL PROTECTED]> wrote:
>      There was a large discussion (I think) early on in the mailinglist about
>the priorities of the mangle table. 

When these new generations of Linux network filtering code come along,
I keep vainly hoping that each new generation won't make things that used
to be easy become very very hard.  Twice I have been wrong.  :-(

>I believe it was eventually agreed that mangle
>belongs before nat. 

No argument with that.  Everywhere that they appear in order, the order
is always "mangle, nat, filter", which is usually the right thing.

>As for having the filter table take up allfive hook points, I
>don't think that's feasible, IMO.

Oh?  Why not?  I think if you can call mangle in all five points, then
you can call filter in all five points too.

Actually I wonder why filter and mangle were ever separated in the
first place.  Separating 'nat' from the others makes sense, but not
filter and mangle.  Everywhere you might be able to and want to mangle
a packet, you might be able to and want to filter it and vice versa.
The only caveat I see is that you probably won't be able to have an
ACCEPT in PREROUTING that overrides a DROP or REJECT in INPUT or FORWARD,
but on the other hand that is not a big loss (and it's what mangle
PREROUTING does already).

>       OK. I understand why you want a POSTROUTING chain for filtration purposes.
>But I don't think that the coreteam will auhorize any new patches to change the
>location and number of hooks in the current tables. At least I don't think they
>will right now; if a good enough reason comes up, maybe they will ;)

Well, they just did it for mangle, which is a major step in the right
direction, but only one step...

I think that having a well-positioned last line of defense against
bugs/misconfigurations/unexpected features etc is a pretty good reason,
especially since historically there have been so many of them.
This is the only reason why I don't yet use iptables on production
firewalls.  This is one thing ipchains can easily do and iptables
can't do so easily (if at all).

>        Well, TBH if you have a strong firewall policy and keep a rigid control
>over what packets go in and out, then this scenario may not take place. 

POSTROUTING filter is exactly "rigid control over what packets go out."
If I could rigidly control everything else (including the Linux routing
code and NAT/MASQ), I wouldn't need a firewall.

iptables should give me more control than ipchains, not less.

>What sort of firewall rules do you have in place?

The rules for input and output go like this:

        accept all traffic on interface 'lo'
        deny all traffic matching 127.0.0.0/8, 0.0.0.0/8, multicast,
                private IP ranges (e.g. 192.168.0.0/16) I'm not using, etc.

Note that as I write "deny" here, the actual rules are always "log and deny."

        for all private interfaces (the ones that are supposed to be "secure"):
                accept packets matching source and destination masks on
                each interface.  These rules are highly specific, matching
                all of interface name, packet source and destination
                address, and protocol and port numbers.

                deny all other traffic on these interfaces

        deny all traffic with source or destination matching a 
        private network address

Note that there is some redundancy between the previous set of rules
and the next set.  This is partly to protect against problems in the
later rules, which are necessarily less strict, and which interact
with policy routing and masquerade (or SNAT, if I could use iptables).
The redundancy also simplifies the later rules--I don't need to explicitly
guard against private-network traffic on public-network interfaces,
since I know that by this point there is no possibility of private
network traffic on those interfaces.

This is the kind of assertion that is difficult to make in pre-1.2.6
iptables without writing a perl script that distributes similar rules
into two or three places.  After the mangle5hooks change, the common
rules for INPUT and the input half of FORWARD can all go into the
PREROUTING chain of the mangle table, but I still seem to be stuck
for output if MASQ is involved.

OK, I've said that like three or more times already...

        for all static-IP permanent interfaces:
                accept packets matching source and destination masks
                on each interface.  These rules are highly specific,
                matching all of interface name, packet source and
                destination address, and protocol and port numbers.

                deny those source or destination masks on all other
                interfaces.  These rules are highly generic, matching
                packet source or destination address without regard
                to protocol.

                deny all other traffic on those interfaces.

        for all dynamic-IP or non-permanent interfaces:
                jump to a "bounce" chain for each interface.  The "bounce"
                chain in turn jumps to a "policy" chain for each security 
                policy.

Each "bounce" chain is a one-rule chain for each interface that jumps to
another chain where the policy for that interface is.  This is because
the mapping from interface name to security policy is dynamic (see rant
below).  Also, since the ACCEPT rules specify acceptable combinations
of interface name, source address mask, and destination address mask,
the rules have to be rewritten whenever the interface address changes.

The various 'ifup' scripts rewrite the rules in the "bounce" chains
so that packets not matching the correct source/dest address etc are
dropped, then any other packets are sent to the appropriate "policy"
chain for final accept/reject/deny.  Separate chains are used for this
so that the index numbers for -R are constant.

IP addresses on all incoming and outgoing packets should have been
verified by now.  Those that don't match have been logged and dropped.

        for all other interfaces:
                accept packets matching permitted port numbers (both
                incoming and outgoing) in the "least secure" policy.
                If the machine is connected to the Internet and runs
                a public server of some kind, ports directly related
                to the service will be allowed.  If the machine is a
                dedicated firewall, then no packets will be allowed and
                this section will be empty.

                deny everything else on those interfaces.

Each rule set ends with:

        deny and log all other traffic (in addition to policy DENY).

In most cases, my forward chains have about four rules.  I verify all the
interfaces and addresses in input and output chains, so there's nothing
left to filter in the forward chain--it is used only to set up where we
do and do not MASQ, and to deny "impossible" forwarding that might be
an attack.  Anyway, the forward chain is:

        ACCEPT traffic that has to be forwarded between private subnets
        or otherwise forwarded without MASQ

        deny traffic that is forwarded between private subnets, or with
        source subnet == destination subnet

        MASQ traffic from approved source subnets

        deny all other traffic

My firewalls have between 3 and 10 interfaces connecting up to 8
subnets and "the Internet."  Half of the interfaces are some kind of
crypto tunnel (IPSEC, CIPE, whatever).  Usually at least one interface
on any given machine has a dynamic IP.  Most machines have at least two
uplinks to the Internet, although only a few use more than one at any
one time.

<begin "interface name matches suck" rant>

Most of my firewalls have at least two interfaces that have different
policies and have different names at different times--e.g. two PPP
interfaces, or a removable ethernet interface that might also be a
wireless LAN interface.  This is the #1 thing that sucks about both
ipchains and iptables.  I have to do all kinds of ugly hackery if the
IP address of an interface or what physical network it's connected to
might change.  If the interface might be reused by networks with different
security policies, then I get race conditions that lead to security holes.

Consider a machine that has a PPP (dialup) connection to a private LAN
and a PPPoE connection to the public internet.  What good is it to be
able to distinguish between ppp0 and ppp1 in firewall rules, if I want
nearly opposite security policies for these two interfaces, and I can't
predict which will be connected to what until after the fact?  What if
I have ethernet and wireless interfaces on eth0 and eth1 on a laptop, 
which might all swap positions at the same time (e.g. after a
suspend/resume cycle) and lead to security-breaching race conditions?

Ideally, I'd be able to assign a temporary symbolic name (call it a
"label") to an interface after it comes up, so that I can match the label
in iptables rules instead of the real interface name.  If the interface
goes down, it should be disassociated with its label automatically.
Heck, there's no reason to have a one-to-one mapping either; I could
just use one label like "verified" assign it to all of my interfaces
that I want the firewall to talk to.

In ipfwadm I used to be able to filter based on an interface address,
which was almost as good as a label--it works on all of my real-world
cases except for laptops and any machine with both dialup PPP and PPPoE.

Similarly, having a match module that says "source (destination) IP
matches an IP address on the output (input) interface" would solve many
cases except the laptop and PPPoE ones.

<end "interface name matches suck" rant>
-- 
Zygo Blaxell (Laptop) <[EMAIL PROTECTED]>
GPG = D13D 6651 F446 9787 600B AD1E CCF3 6F93 2823 44AD

Reply via email to