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

absduser

Member

Reaction score: 3
Messages: 69

Here is a very short ipfw ruleset I have on a firewall device:
Code:
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.
 
Last edited by a moderator:

Murph

Well-Known Member

Reaction score: 183
Messages: 297

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

  1. 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.
  2. Those rules will block everything other than the limited set of ICMP for the firewall host as well.
  3. I probably wouldn't allow the UDP traceroute, personally. I would use traceroute -I to do ICMP ECHO traceroutes instead.
  4. 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.
  5. 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).
 
OP
A

absduser

Member

Reaction score: 3
Messages: 69

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

  1. 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.
  2. Those rules will block everything other than the limited set of ICMP for the firewall host as well.
  3. I probably wouldn't allow the UDP traceroute, personally. I would use traceroute -I to do ICMP ECHO traceroutes instead.
  4. 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.
  5. 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).
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

Well-Known Member

Reaction score: 183
Messages: 297

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]
 
OP
A

absduser

Member

Reaction score: 3
Messages: 69

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

Well-Known Member

Reaction score: 183
Messages: 297

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.
 
Top