Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 20 Dec 2007 22:45:23 +1100 (EST)
From:      Ian Smith <smithi@nimnet.asn.au>
To:        "W. D." <WD@US-Webmasters.com>
Cc:        freebsd-security@freebsd.org, Tuomo Latto <djv@iki.fi>
Subject:   Re: IPFW: Blocking me out.  How to debug?
Message-ID:  <Pine.BSF.3.96.1071220212656.15482A-100000@gaia.nimnet.asn.au>
In-Reply-To: <20071220063926.4B2D113C457@mx1.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
Firstly, this really belongs over on freebsd-net@ if not 
freebsd-questions@, but anyway ..

On Thu, 20 Dec 2007, W. D. wrote:

 > At 03:49 12/17/2007, Tuomo Latto wrote:
 > >W. D. wrote:
 > >> How do I tell which rule is blocking me out?  SSH *is* working,
 > >> but others are not.
 > >
 > >It all depends on what you mean by "blocking you out" and "others".

True; it's not really clear what you're trying to do, whether this is a
single server with a single net interface with no NAT or what, but based
on your present rules I'll have to make that assumption.

 > >Did you try *reading* your fw config?
 > >
 > >>         # Loopback:
 > >>         # Allow anything on the local loopback:
 > >>         add allow all from any to any via lo0
 > >>         add deny ip from any to 127.0.0.0/8
 > >>         add deny ip from 127.0.0.0/8 to any
 > >Nope.

Meaning, these rules are ok and not the problem.  Ignore Mr. Nipples.

 > >>         # Allow established connections:
 > >>         add allow tcp from any to any established
 > >Nope.

That's ok.  It may help you in debugging what's happening to use:

  allow [log] tcp from any to any in established
  allow [log] tcp from any to any out established

and really, using 'any to any' without specifying on which interfaces or
whether 'any' is your box or the outside world is a bit too general, but
moving on .. 

 > >>         # Deny fragmented packets:
 > >>         add deny ip from any to any frag
 > >Nope.
 > >>         # Show pings:
 > >>         add count icmp from any to any icmptypes 8 in
 > >Nope.

That's inbound ping requests.  Don't forget that 'inbound' means coming
into the firewall, not necessarily from the outside world.  Your own
ping requests _from_ this box also have to both come in, and go out. 

 > >>         # Allow pings, ping replies, and host unreach:
 > >>         add allow icmp from any to any icmptypes 0,8,3
 > >Nope.

Add icmptype 11 as well if you want traceroutes to work ..

 > >>         # Allow UDP traceroutes:
 > >>         add allow udp from any to any 33434-34458 in
 > >>         add allow udp from any 33434-34458 to any out
 > >Nope.

Ok, though udp rules are often better done statefully.  See below.

 > >>         # Allow DNS with name server
 > >>         add allow udp from any to any domain out
 > >>         add allow udp from any domain to any in
 > >Nope.

You want to watch out here.  This allows udp packets from any address
with source port 53 to connect with any open udp port on your system,
and allows the responses as well.  It's a simple matter using such as
netcat to source packets from port 53. 

I gather from this that you're not running a DNS server yourself, but
using upstream server/s?  In that case a stateful rule is safer:

  allow udp from me to any 53 keep-state 

which allows after the return packets but denies connections not
initiated from your box. 

 > >>         # SSH
 > >>         #  Note that /etc/hosts.allow has restrictions
 > >>         #  on which IP addresses are allowed.
 > >>         #
 > >>         # Allow SSH:
 > >>         add allow tcp from any to any ssh in setup
 > >Nope, but this explains SSH working.

By 'ssh working', I guess you mean ssh connections to this box from
elsewhere, rather than ssh connections from this box?  Not clear.

 > >>         # HTTP & HTTPS:
 > >>         add allow tcp from any to any https in setup
 > >>         add allow tcp from any to any http in setup
 > >Nope.

So, you have a webserver running on this box, listening on ports 80 and
443?  You've verified with 'netstat -finet -a' that this is the case?

 > >>         # Mail: SMTP & IMAP:
 > >>         add allow tcp from any to any smtp in setup
 > >>         add allow tcp from any to any imap in setup
 > >Nope.

You're running SMTP and IMAP servers, verified as above?

You see, this also allows you (as 'any') to connect to any outside SMTP
server too.  It really helps to differentiate connections into your box
from those you're making to outside boxes, which these don't do.
 
Have a close look at the 'simple' section in rc.firewall.  There are
advantages to running a script such as that rather than rules in a file,
like variable substitution, at least while getting it all working right. 

 > >>         # FTP:
 > >>         add allow tcp from any to any ftp in setup
 > >>         add allow tcp from any to any ftp\-data in setup
 > >>         add allow tcp from any ftp\-data to any setup out
 > >Nope.

Mmm, I prefer using and enforcing FTP passive mode, but YMMV.

 > >>         # Allow NTP in and out
 > >>         add allow udp from any ntp to 128.252.19.1 ntp out
 > >>         add allow udp from 128.252.19.1 ntp to any ntp in
 > >Nope.

Unless running a time service for other boxes, something like:

  allow udp from me to any ntp keep-state # or to a specific server

 > >>         # Deny and log everything else:
 > >>         add deny log all from any to any
 > >Bingo!

Ok, so you got rid of interface 'all', great.

 > >"ipfw -a list" may also help (packet counts).

It's only a short ruleset, it may help us if you show the output of say
'ipfw -t show' (or ipfw -at list, same thing), if you're still having
problems, but see below re 'inness' and 'outness'.

 > I've been banging my head against this for the past few
 > days.  I don't get it.  
 > 
 > My understanding of the way this is supposed to work is
 > that:
 > 
 >   # HTTP & HTTPS:
 >   add allow tcp from any to any https in setup
 >   add allow tcp from any to any http in setup
 > 
 > should let initial HTTP & HTTPS requests through,
 > and that:
 > 
 >  # Allow established connections:
 >  add allow tcp from any to any established

Not quite.  Looks like you're allowing http/https setup packets in (ie,
into the firewall) but not letting them out (of the firewall, to the
webserver).  For example in the 'simple' ruleset mentioned, we have:

        # Allow access to our WWW
        ${fwcmd} add pass tcp from any to ${oip} 80 setup

        # Reject&Log all setup of incoming connections from the outside
        ${fwcmd} add deny log tcp from any to any in via ${oif} setup

        # Allow setup of any other TCP connection
        ${fwcmd} add pass tcp from any to any setup

Note there's no 'in' or 'out' on the port 80 rule, so this allows the
packets on both the in and out pass of the firewall.  Also, the IP is
specified as our IP - 'me' will do fine if it's just this box. 

 > should allow connections that are "setup" to 
 > continue.  Do I need a "check-state" or "keep-state"
 > statement somewhere?

No, though you can use stateful TCP rules if you want to, in which case
you'll want to DENY established connections.  Personally I find relying
on the TCP state established by using 'setup' and 'established' fine for
TCP, but tend to use keep-state for UDP and some ICMP rules. 

 > I don't understand what is wrong with the last rule:
 > 
 >   # Deny and log everything else:
 >   add deny log all from any to any
 > 
 > My understanding is that anything that doesn't match
 > the previous rules will match this one and hence
 > be logged and denied.  Is this not correct?

That's correct.  Aren't you seeing any?  Try show rather than tell.

 > Again, I am having a great deal of difficulty
 > understanding why these rules don't work as expected.
 > I've scoured the 'Net and printed out just about
 > every coherent ruleset out there.
 > 
 > Besides adding the "log" keyword on all of the rules,
 > these are the debugging tools I have been using:
 > 
 >   ipfw disable firewall
 >   ipfw -f flush
 >   ipfw enable firewall
 >   /etc/rc.d/ipfw start
 >   ipfw -a -S -N -t list
 >   ipfw list      
 >   tail  -f   /var/log/ipfw/ipfw.log
 >   tcpdump -i nve0 'proto \tcp && port http'
 > 
 > Could anyone please throw this tired dog a bone?

Getting the two-pass nature of ipfw understood seems to be your main
difficulty.  I know it was for me back then.  Have a look at the section
in ipfw(8) regarding packet flows, and although it sounds trite, RTFM
about 10 times :)

Cheers, Ian




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.3.96.1071220212656.15482A-100000>