# Is this (short) ipfw ruleset as tight as I think it is ?



## absduser (Jul 30, 2016)

Here is a very short ipfw ruleset I have on a firewall device:

```
5 allow tcp from any to any established
10 allow icmp from any to any icmptypes 0,3,8,11
20 allow udp from any to any dst-port 33433-33499 in via xl1
30 allow tcp from any to any dst-port 40 in via xl1
65535 deny ip from any to any
```
That's it.  I want interior machines (connected via xl1) to be able to ping, to be able to traceroute out to the world, and to be able to connect over TCP 40.

And nothing else.

It's extremely important that no other network traffic can be generated on the interior net and pass to the other side of this firewall.

Is this watertight ?  I think it is ... but I want a second opinion.

Thanks.


----------



## Murph (Jul 30, 2016)

Yeah, more or less, with a few notes.  Usual BSD disclaimer applies.


Start your rules at 1000, to allow the standard `setup_loopback()` rules in /etc/rc.firewall to remain in their normal position at the highest priority.
Those rules will block everything other than the limited set of ICMP for the firewall host as well.
I probably wouldn't allow the UDP traceroute, personally.  I would use `traceroute -I` to do ICMP ECHO traceroutes instead.
The internal hosts might benefit from access to a DNS resolver.  Possibly also NTP.  The firewall system might be a convenient system to provide those functions.
All of those allow rules can be used to establish a tunnel from the inside to anywhere on the net, even the ICMP rule (you can tunnel over any protocol that allows a payload, even ICMP ECHO).


----------



## absduser (Jul 30, 2016)

Murph said:


> Yeah, more or less, with a few notes.  Usual BSD disclaimer applies.
> 
> 
> Start your rules at 1000, to allow the standard `setup_loopback()` rules in /etc/rc.firewall to remain in their normal position at the highest priority.
> ...



OK, thank you - the part about traceroute -I is especially helpful as it allows me to remove that UDP opening in the ruleset.

A related question:   Does the ipfw ruleset get applied during boot BEFORE the network interfaces are brought up ?

I ask because I can imagine a scenario where someone quickly makes a connection before the ruleset gets applied, and then that connection is allowed to persist because it is "established" even though it is not TCP port 40 ....  is that possible ?  I am hoping the ipfw rules from /etc/ipfw.conf get applied before network interfaces are brought up, and therefore it's not possible...


----------



## Murph (Jul 30, 2016)

absduser said:


> A related question:   Does the ipfw ruleset get applied during boot BEFORE the network interfaces are brought up ?
> 
> I ask because I can imagine a scenario where someone quickly makes a connection before the ruleset gets applied, and then that connection is allowed to persist because it is "established" even though it is not TCP port 40 ....  is that possible ?  I am hoping the ipfw rules from /etc/ipfw.conf get applied before network interfaces are brought up, and therefore it's not possible...



Add `ipfw_load="YES"` to /boot/loader.conf.  Unless you have recompiled the kernel with the IPFIREWALL_DEFAULT_TO_ACCEPT option (not present in FreeBSD GENERIC kernels), it will block all traffic by default.  By loading the module very early, the default block will be in place long before there is any networking available (it will even be in place if you disable the firewall in /etc/rc.conf, so use `firewall_type="open"` if you need to disable it and allow all traffic).

Additionally, or alternatively, consider changing your tcp rule to `allow tcp from any to any dst-port 40 in via xl1 setup keep-state`, add a `check-state` at the top of your rules, and change/remove your `established` rule.  See the workstation example in /etc/rc.firewall for an example using `check-state`.  Stateful firewalling is slightly more expensive, but closes the small hole created by `established`.[/cmd]


----------



## absduser (Jul 30, 2016)

OK, so I ipfw_load="YES" in /boot/loader.conf, which will load rule 65535 (deny all) and no other rules.

Then we sit around and wait for the rest of the rules to load from /etc/ipfw.conf.

Out of curiousity, since I have ipfw compiled into my kernel, when does it normally start the firewall and load rule 65535 ?


----------



## Murph (Jul 30, 2016)

absduser said:


> OK, so I ipfw_load="YES" in /boot/loader.conf, which will load rule 65535 (deny all) and no other rules.
> 
> Then we sit around and wait for the rest of the rules to load from /etc/ipfw.conf.
> 
> Out of curiousity, since I have ipfw compiled into my kernel, when does it normally start the firewall and load rule 65535 ?



Oh, ok, if you have recompiled the kernel with ipfw embedded into it, then you don't need to worry about loader.conf, which just makes sure the module gets loaded early.  If it is present in the core kernel, the deny rule is there as soon as the kernel is loaded, before any of the /etc/rc* scripts fire.

With a GENERIC kernel and nothing in loader.conf, the module gets loaded when /etc/rc.d/ipfw runs, which is where the default deny would kick in.  You can examine the ordering with `rcorder /etc/rc.d/*`.  Assuming a relatively normal rc.conf, that script is what loads your custom rules.


----------

