On Wed, 15 Nov 2006, Mick wrote:
On Wednesday 15 November 2006 21:25, Flophouse Joe wrote:
On Wed, 15 Nov 2006, Mick wrote:

UPLINK="eth0 wlan0 ppp0"
for x in ${INTERFACES}
        do
                iptables -A INPUT -i ! ${x} -j ACCEPT
                . . . more rules . . .
                iptables -A INPUT -p tcp -i ${x} -j DROP
        fi
=====================================================
type of think.  Not sure if the syntax is correct, but the idea is that we
define multiple interfaces, but only write the rules once with the
variable 'x' where the interface is meant to go.

I'm not 100% certain that I understand the goal, so please let me know
if I've gotten it wrong.  It sounds like you want to apply identical
firewall rules to each of three interfaces.  It's possible that there
are other interfaces, and if traffic arrives on those interfaces, then
it should not be matched by the rules in the for loop.

If this is the case, then yes, the for loop you've suggested should be
perfectly fine.  The rules you specify in that loop will only be applied
to traffic which arrives on the interfaces that you loop through.

If you're anything like me, you'll find the rules created in this manner slightly difficult to read from the output of "iptables -vnL", but you'd have the same problem using the test-then-jump method I mentioned in my previous post. As near as I can tell, this is a limitation of iptables (or netfilter) itself, in that (to the best of my knowledge) it isn't possible to specify a rule that matches multiple interfaces whose names don't begin the same way.

It's entirely possible that I'm misunderstanding the design of
netfilter, but it seems to me that the solution to complicated rulesets
is to permit boolean logic in rules like so:

        iptables -A INPUT \
        \(-i eth0 -or -i wlan0) -and \(-p tcp --dport ssh\) \
        -j ACCEPT

Is there a legit way of specifying such rules?

Not that I'm aware of, but I'd very much like to be proven wrong.  Does
anyone else on the list know of a way to specify boolean conditions in
iptables rules as illustrated above?

For what it's worth, I have found a way to get something that
approximates the ability to use ORs in iptables rules, but it borders on
the criminially insane.  I describe it below:

I have a Gentoo system in my house which acts as a firewall and NAT
gateway.  It has three network interfaces:

eth0 connects to the public internet,
eth1 connects to a non-routable network segment,
eth2 connects to a non-routable wireless access point left wide open.

I wish for some hosts-- and only some hosts-- to be able to connect to the
wireless access point and have their traffic masqueraded out to the
public internet.

Since I'm dealing with a very small number of hosts, and since these
hosts are directly connected to the Gentoo system's ethernet segment,
I've decided to filter traffic from the wireless access point based on
the source MAC address of the ethernet frames coming from the wireless
access point.

Let's say that I trused the hosts with MAC address 00:11:22:33:44:55 and
with MAC address 00:22:44:66:88:AA, and I wished for these hosts to have
their traffic forwarded out to the internet without any restrictions
whatsoever.

This would be simple enough:

        iptables -A FORWARD -i eth2 -o eth0 \
        -m mac --source-mac 00:11:22:33:44:55 -j ACCEPT

        iptables -A FORWARD -i eth2 -o eth0 \
        -m mac --source-mac 00:22:44:66:88:AA -j ACCEPT

But in reality, the rules are a bit more complicated.  I disallow
outgoing access to SMTP and BitTorrent, for example.  I also disallow
outgoing traffic to certain UDP ports.

These rules add up quickly. It's possible to collapse some of these rules using -m multiport , but I still end up with a few rules for each of the hosts that are being forwarded from the wireless interface to the public. And since I can't test for multiple MAC addresses in one rule, I need separate rules for each host.

I've got about six hosts connecting to the wireless access point, and
I've got three rules for each host.  Because I can't "OR" rules
together, I've got 6 x 3 = 18 rules to juggle.

This isn't too big of a deal if I wrap it up in a for loop, but it's
still unsightly to look at in the output of "iptables -vnL"

I've used the connmark match and the CONNMARK target to get the same
effect.

In table mangle chain PREROUTING, I have rules that look like this:

        iptables -t mangle -A PREROUTING \
        -m mac --mac-source 00:11:22:33:44:55 \
        -j CONNMARK --set-mark 0x1/0x1

        iptables -t mangle -A PREROUTING \
        -m mac --mac-source 00:22:44:66:88:AA \
        -j CONNMARK --set-mark 0x1/0x1

        iptables -t mangle -A PREROUTING \
        -m mac --mac-source 33:66:99:CC:FF:00 \
        -j CONNMARK --set-mark 0x1/0x1

And now I can collapse the rules in table filter, chain FORWARD like so:

        iptables -A FORWARD -p tcp -m multiport ! --dports 25,6881 \
        -i eth2 -o eth0 -m connmark 0x1/0x1 -j ACCEPT

        iptables -A FORWARD -p udp -m multiport ! --dports 123,456 \
        -i eth2 -o eth0 -m connmark 0x1/0x1 -j ACCEPT

The "connmark 0x1/0x1" business sets a bit associated with the connection; 
think of
it as setting a variable and then checking for it later.

The above two rules are effectively saying the following:

        iptables -A FORWARD -p tcp -m multiport ! --dports 25,6881 \
        -i eth2 -o eth0 \
        -m mac --mac-source mac-1,mac-2,mac3 \
        -j ACCEPT

        iptables -A FORWARD -p tcp -m multiport ! --dports 123,456 \
        -i eth2 -o eth0 \
        -m mac --mac-source mac-1,mac-2,mac-3 \
        -j ACCEPT

As you can see, this method is pretty complicated, too.  It's not really
any substitute for "real" boolean logic (as described near the top of
this post).  If anyone knows of a way to do this, I'd like to know
about it.

Joe
--
gentoo-user@gentoo.org mailing list

Reply via email to