I bypassed my own firewall (+ I'm stupid about "limit")

dave madden dhm@mersenne.com
Thu, 30 Sep 1999 01:36:25 -0700

Let's get stupid out of the way first:

 =>You'll want a target on that rule: what did you want to do if it's not
 =>limited?  (TODO: -m limit should take a ! flag).
 =>I think you want:
 =>	/sbin/iptables -A spoof -m limit --limit 60/h --limit-burst 30/m
    -j LOG --log-prefix `SPOOF!'

What I intended to do was make a "black hole" chain that would log a
packet if it was below the limit, and ALWAYS drop it.  So I guess what
I really want is:

	iptables -N blackhole
	iptables -A blackhole -m limit --limit 60/h -j DROP
	iptables -A blackhole -j LOG --log-prefix 'SPOOF!'
	iptables -A blackhole -j DROP

    [some rules]
	iptables -A INPUT [match bad packet] -j blackhole
    [more rules]

Of course, I don't know whether the sense of the limit is "match
packets UNDER the limit" or "match packets OVER the limit", so those
rules may end up not logging anything unless there's a whole bunch of
'em -- I assume that's why you said "limit should take a ! flag."

								* * *

So much for me being stupid.  Now, for "probably stupid, aggravated by
late at night":

 =>From: Paul Rusty Russell <Paul.Russell@rustcorp.com.au>
 =>Date: Thu, 30 Sep 1999 17:18:55 +0930
 =>In message <199909300655.XAA04182@mersenne.com.> I wrote:
 =>> [NAT appears to bypass filtering?]
 =>I'm surprised.
 =>Did you set up your firewall rules IGNORING NAT, or did you think they
 =>have and effect on each other in some way?  They're supposed to be
 =>independent; you think of the firewall rules as seeing `real' IP

Yes, I set up the firewall rules first (no NAT), then added
masquerading so that I could get out from my private network, and
finally added port-forwarding so that the outside world could get to
certain ports on certain private boxes.

I actually have a couple of problems: first, it appears that packets
whose dports are forwarded to private machines don't go through the
filter, or at least they don't tickle the counters on the expected

Second, private machines that attempt to access private services
through the public address fail because I've done an incomplete job of
setting up the forwarding.  What happens (tcpdumping the private
ethernet) is: private-a sends a packet to public-svc, and the firewall
modifies the packet and retransmits so that it goes to private-b,
where the service actually resides.  However, the source address is
still private-a, so private-b responds directly to private-a, which
ignores the response.  This is exactly what you warn about in the
HOWTO: packets must go through the firewall in both directions or
things won't work.  I just don't know how to get them to do it.

I'll append my complete config, because it's not that long, and it may
show the nature of my cluelessness in a way that makes it easier to
get me to stop pestering you :-)

My network looks like:

                local ethernet: 192.168.x.x
---dsl---+  +----------+------------+-----------+
         |  |          |            |
      +--+--+--+  +----+----+  +----+----+
      |firewall|  |private-a|  |private-b|
      +--------+  +---------+  +---------+
        ^           ^            ^
        HTTP      (no services)  HTTPS,SSH


# rc.firewall - set up vheissu firewall


# Load the necessary modules...
for MOD in iptables ipt_udp ipt_tcp ipt_limit ipt_LOG ; do
	/sbin/modprobe $MOD

# Set up firewall: allows all packets received on interfaces other than
# $OUTSIDE_IF; all established TCP connections; all new connections to SSH,
# HTTP, HTTPS, SMTP, AUTH, and DNS, and UDP packets for NTP and DNS.
# Other packets are logged and dropped.
/sbin/iptables --policy INPUT DROP

# This is wrong and I know it!
/sbin/iptables -N spoof
/sbin/iptables -A spoof -m limit --limit 60/h --limit-burst 30/m
/sbin/iptables -A spoof -j LOG --log-prefix 'SPOOF!'

/sbin/iptables -A INPUT \! -i $OUTSIDE_IF -j ACCEPT
/sbin/iptables -A INPUT    -i $OUTSIDE_IF -s -j spoof
/sbin/iptables -A INPUT    -i $OUTSIDE_IF -s -j DROP
/sbin/iptables -A INPUT    -i $OUTSIDE_IF -s -j spoof
/sbin/iptables -A INPUT    -i $OUTSIDE_IF -s -j DROP
/sbin/iptables -A INPUT    -i $OUTSIDE_IF -s -j spoof
/sbin/iptables -A INPUT    -i $OUTSIDE_IF -s -j DROP
/sbin/iptables -A INPUT -p tcp -i $OUTSIDE_IF \! --syn -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport ssh -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport http -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport https -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport smtp -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport domain -j ACCEPT
/sbin/iptables -A INPUT -p udp --dport domain -j ACCEPT
/sbin/iptables -A INPUT -p tcp --sport domain -j ACCEPT
/sbin/iptables -A INPUT -p udp --sport domain -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport ntp -j ACCEPT
/sbin/iptables -A INPUT -p udp --dport ntp -j ACCEPT
/sbin/iptables -A INPUT -p udp --sport ntp -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport auth -j ACCEPT
/sbin/iptables -A INPUT -p icmp \! -f -j ACCEPT
# Log other packets for attack detection or overzealous firewall debugging
/sbin/iptables -A INPUT -m limit --limit 60/h --limit-burst 30/m
/sbin/iptables -A INPUT -j LOG

# Forward any packet that can get in and needs to go somewhere else
/sbin/iptables --policy FORWARD ACCEPT

/sbin/modprobe ip_nat_map_masquerade

# Masquerade all local packets so that private-IP machines can get
# out...
ipnatctl -I -s 192.168.x.0/24 -b source -m masquerade

# Forward certain ports to internal machines for processing
ipnatctl -I -p tcp -d --dport 22 -b dest --to 192.168.x.1 --to-ports 22
ipnatctl -I -p tcp -d --dport 25 -b dest --to 192.168.x.1 --to-ports 25
ipnatctl -I -p tcp -d --dport 443 -b dest --to 192.168.x.1 --to-ports 443