Re: New to IPFW and would like critique...

From: Lowell Gilbert (lowell_at_world.std.com)
Date: 10/02/03


Date: Thu, 02 Oct 2003 16:48:24 GMT


"GLOCK!" <glock_perfection@hotmail.com> writes:

> I decided to get rid of my Linksys cable router, so the other night I
> replaced it with my FBSD box. It's a dual homed 5.1 system. The firewall
> rules are my first attempt with some help from a FAQ. I'm looking for
> feedback in regards to the rule setup and also information on how to
> implement stateful rules. I think I could cut back a large amount of my
> rules by using it. I tried last night but ran out of time...probably sleep
> deprivation kicked in and "man ipfw" began to read like Alice in
> Wonderland...so I ended up with a non functioning internet connection until
> I reverted back to this set of rules.
>
> fxp0 is my outside interface (receives address via DHCP)
> fxp1 is my inside interface (statically addressed 192.168.1.1)
>
> Thanks for the help and input.

Your rule numbering is kind of silly. You might as well leave out the
numbers completely and let ipfw number them automatically. I find it
useful to specify numbers only when I'm trying to group rules in a way
that jumps out at the eye better.

Note that you can use port identifiers from /etc/services instead of
numbers. This improves intelligibility as well.

You log a *lot* of types of connections that aren't particularly
dangerous. If you really want to do that, I suggest developing some
scripts to separate out the relatively harmless connections from the
ones that you really want to notice.

> GLOCK!
>
> titanium# cat rc.firewall
> # Suck in the configuration variables.
> if [ -r /etc/defaults/rc.conf ]; then
> . /etc/defaults/rc.conf
> source_rc_confs
> elif [ -r /etc/rc.conf ]; then
> . /etc/rc.conf
> fi
>
> if [ -n "${1}" ]; then
> firewall_type="${1}"
> fi
>
> # Firewall program
> fwcmd="/sbin/ipfw"
>
> # Outside interface network and netmask and ip
> oif="fxp0"
> onet=`ifconfig fxp0 |grep "inet " |awk '{print $6}'`
> omask="255.255.240.0"
> oip=`ifconfig fxp0 |grep "inet " |awk '{print $2}'`

Okay; why do you do this? If it changes under you, the firewall stops
working. Since you seem to only have one global address, there's no
real security advantage to having the address in the firewall. If you
want to anyway, you'd be better off with the "me" keyword.

> # Inside interface network and netmask and ip
> iif="fxp1"
> inet="192.168.1.0"
> imask="255.255.255.0"
> iip="192.168.1.1"
>
> # Endpoints
> bb="xxx.xxx.xxx.xxx"
> auth01="xxx.xxx.xxx.xxx"
> auth02="xxx.xxx.xxx.xxx"
> phantom="xxx.xxx.xxx.xxx"

For tunnels?

> # Flush previous rules
> ${fwcmd} -f flush
>
> # Allow loopbacks, deny imposters
> ${fwcmd} add 101 pass all from any to any via lo0
> ${fwcmd} add 119 deny all from any to 127.0.0.0/8
>
> # Stop spoofing
> ${fwcmd} add 209 deny all from ${inet}:${imask} to any in via ${oif}
> ${fwcmd} add 219 deny all from ${onet}:${omask} to any in via ${iif}
>
> # Stop RFC1918 nets
> ${fwcmd} add 229 deny all from any to 10.0.0.0/8 via ${oif}
> ${fwcmd} add 239 deny all from any to 172.16.0.0/12 via ${oif}
> ${fwcmd} add 249 deny all from any to 192.168.0.0/16 via ${oif}
>
> # Stop draft-manning-dsua-03.txt (1 May 2000) nets (includes RESERVED-1,
> # DHCP auto-configuration, NET-TEST, MULTICAST (class D), and class E)
> # on the outside interface
> ${fwcmd} add 259 deny all from any to 0.0.0.0/8 via ${oif}
> ${fwcmd} add 269 deny all from any to 169.254.0.0/16 via ${oif}
> ${fwcmd} add 279 deny all from any to 192.0.2.0/24 via ${oif}
> ${fwcmd} add 289 deny all from any to 224.0.0.0/4 via ${oif}
> ${fwcmd} add 299 deny all from any to 240.0.0.0/4 via ${oif}
>
> # Network Address Translation. This rule is placed here deliberately
> # so that it does not interfere with the surrounding address-checking
> # rules. If for example one of your internal LAN machines had its IP
> # address set to 192.0.2.1 then an incoming packet for it after being
> # translated by natd(8) would match the `deny' rule above. Similarly
> # an outgoing packet originated from it before being translated would
> # match the `deny' rule below.
> ${fwcmd} add 300 divert natd all from any to any via ${natd_interface}

You should put rules here to stop unroutable networks on the outside
interface as source addresses. [Before the NAT, you ruled them out as
destination addresses. But you don't want them used as source
addresses either, and that has to be done *after* the translation is
done, for the cases where they are legitimate.]

> # Allow established connections with minimal overhead
> ${fwcmd} add 301 pass tcp from any to any established
>
> # Deny IP fragments
> ${fwcmd} add 399 deny all from any to any in frag

I hope you know what you're doing. Breaking path discovery can cause
all kinds of weird problems.

> ### TCP RULES
>
> # HTTP - Uncomment to allow access to our web server
> #${fwcmd} add 401 pass tcp from any to any 80 setup
>
> # SMTP - Uncomment to allow access to sendmail for incoming e-mail
> #${fwcmd} add 411 pass tcp from any to any 25 setup
>
> # FTP - Allow incoming data channel for outgoing connections,
> # reject & log all incoming control connections
> ${fwcmd} add 421 pass tcp from any 20 to any 1024-65535 setup
> ${fwcmd} add 429 deny log tcp from any to any 21 in via ${oif} setup

For a basic home firewall, you could stick with passive connections
and not worry about the first rule.

> # SSH Login - Allow & Log all incoming
> ${fwcmd} add 431 pass log tcp from any to any 22 in via ${oif} setup
>
> # RDP Login - Allow & Log all incoming
> ${fwcmd} add 441 pass log tcp from 216.150.131.207 to any 3389 in via ${oif}
>
> # IDENT - Reset incoming connections
> ${fwcmd} add 459 reset tcp from any to any 113 in via ${oif} setup
>
> # Reject & Log all setup of incoming connections from the outside
> ${fwcmd} add 469 deny log tcp from any to any in via ${oif} setup
>
> # Allow setup of any other TCP connection
> ${fwcmd} add 471 pass tcp from any to any setup
>
> # Reject & Log all setup of incoming connections from the outside
> ${fwcmd} add 499 deny log tcp from any to any in via ${oif}
>
> ### UDP RULES
>
> # DNS - Allow queries out in the world
> ${fwcmd} add 501 pass udp from any to any 53 out via ${oif}
> ${fwcmd} add 502 pass udp from any 53 to any in via ${oif}
> ${fwcmd} add 503 pass udp from any to any 53 via ${iif}
> ${fwcmd} add 504 pass udp from any 53 to any via ${iif}

This is a good candidate for keeping state. Imagine an incoming
packet coming from a port 53 and going to, say, port 137.

> # DHCP - Allow request and reply from OptOnline
> ${fwcmd} add 511 pass log udp from any 68 to xxx.xxx.xxx.xxx out via ${oif}
> ${fwcmd} add 512 pass log udp from xxx.xxx.xxx.xxx to any 68 in via ${oif}

Are you sure you need these?

> # SMB - Allow local traffic
> ${fwcmd} add 521 pass udp from any to any 137-139 via ${iif}
>
> # SYSLOG - Allow machines on inside net to log to us.
> ${fwcmd} add 531 pass udp from any 514 to any 514 via ${iif}

I tend to be a lot looser with my inside net. If it were wireless,
that would be a different story...

> # NTP - Allow queries out in the world
> ${fwcmd} add 541 pass udp from ${auth01} 123 to any 123 in via ${oif}
> ${fwcmd} add 542 pass udp from any to ${auth01} out via ${oif}
> ${fwcmd} add 543 pass udp from ${auth02} 123 to any 123 in via ${oif}
> ${fwcmd} add 544 pass udp from any to ${auth02} out via ${oif}
> ${fwcmd} add 545 pass udp from any 123 to any via ${iif}
> ${fwcmd} add 546 pass udp from any to any 123 via ${iif}

Again, this is a good place for keeping state.

> # TRACEROUTE - Allow outgoing
> ${fwcmd} add 551 pass udp from any to any 33434-33523 out via ${oif}

Unless you have a reason, you might want to just let any UDP go out,
and use keep-state to get the results back without opening up to the
outside world.

> # Reject & Log all setup of incoming connection from the outside
> ${fwcmd} add 599 deny log udp from any to any in via ${oif}
>
> ### ICMP RULES
>
> # Allow all ICMP packets on internal interface
> ${fwcmd} add 601 pass icmp from any to any via ${iif}
>
> # Allow outgoing pings
> ${fwcmd} add 611 pass icmp from any to any icmptypes 8 out via ${oif}
> ${fwcmd} add 621 pass icmp from any to any icmptypes 0 in via ${oif}
>
> # Allow Destination Unreachable, Source Quench, Time Exceeded, and Bad
> Header
> ${fwcmd} add 621 pass icmp from any to any icmptypes 3,4,11,12 via ${oif}
>
> # Deny the rest of them
> ${fwcmd} add 699 deny log icmp from any to any via ${oif}
>
> ### GRE RULE
>
> # PPTP VPN support
> #${fwcmd} add 700 pass gre from any to any
>
> ### MISCELLANEOUS REJECT RULES

I don't think anything is going to hit these, anyway. You should have
accepted or denied all of IP by now.

> # Reject broadcasts from outside interface
> ${fwcmd} add 60009 deny ip from any to 0.0.0.255:0.0.0.255 in via ${oif}
>
> # Reject&Log SMB connections on outside interface
> ${fwcmd} add 61009 deny log udp from any to any 137-139 via ${oif}
>
> # Reject&Log all other connections from outside interface
> ${fwcmd} add 62009 deny log ip from any to any via ${oif}
> ${fwcmd} add 65309 deny log ip from any to any
>
> # Everything else is denied by default, since the
> # IPFIREWALL_DEFAULT_TO_ACCEPT option is not set in the kernel