Firewalls / ipfw – protect your subnet
see also Firewall rules – some more work.A firewall is a good line of defense against external intruders. It can allow precisely what you want and exclude everything you don’t want. I’m using ipfw which [I think] means Internet Packet FireWall.
This section will deal mostly with how to configure ipfw. For details on to install ipfw, see Firewalls, filtering, ipfw, and FTP clients.
Deny everything. Accept nothing.
My first step was to try invoking the simple firewall by telneting to my box and typing sh /etc/rc.firewall. That worked. But it also terminated my telnet session! <grin> Then, from the console, I did sh /etc/rc.firewall simple. That worked but it also stopped IRC from working. It must be something in the rules.The existing rules did not allow me to ping other machines from my FreeBSD box. That’s because, by default, everything is denied. That’s a good thing because it means you aren’t allowing things you don’t want. It also means you must explicitly state what you do want.
Getting ping to work
I received the following message. This applied to local machines and to those in the outside world.ping: sendto: Permission denied
After some thought I noticed that I did not have the following rule:
$fwcmd add pass all from any to any
This allowed me to ping my local network. And the outside world. NOTE: The above rule isn’t for long term use. I plan to explicitly allow things rather than allow everything like that.
What is denying?
But I have bigger problems. I can access my local webserver via internal address and by external address. But I cannot access an external website. I can access my local POP3 server but not my ISP. Something in the rules is preventing this. I think I must explicitly allow these things.I tried removing some of the deny rules, but that didn’t achieve anything. Here is the firewall rules you get if you don’t specify which model you want:
00100 allow ip from any to any via lo0 00200 deny ip from any to 127.0.0.0/8 00300 divert 8668 ip from any to any via ed0 65000 allow ip from any to any 65535 deny ip from any to any
The above rule set allows me me to do whatever I need to do. So these rules within the simple rule set aren’t the problem. It must be the other rules.
Found!
I’ve done some testing. By removing rules one at a time and trying connections to the outside world, I’ve found that the rules which prevent the connections.Here are the rules and the connections they prevented:
- prevents Agent from connecting to my ISP’s news server.
$fwcmd add deny all from any to 192.168.0.0:255.255.0.0 via ${oif} out
- prevents IRC connections from occurring.
$fwcmd add deny log tcp from any to any in via ${oif} setup
IRC
I spent some time talking to virus on Undernet #FreeBSD. He suggested I add some rules to allow these two rules to allow IRC:# allow IRC $fwcmd add allow tcp from any to ${oip} 194 $fwcmd add allow udp from any to ${oip} 194
By doing that, I could reinstate rule 01300 listed above
A temporary fix
This rule sets seems fine now:01800 allow ip from any to any
Now I’ve started to get rid of rule 1800 above. It’s not very secure.
21 October 1998
I’ve replaced:$fwcmd add deny all from any to 192.168.0.0:255.255.0.0 via ${oif}
with
$fwcmd add deny all from any to 192.168.0.0:255.255.0.0 via ${oif} out
I’m not sure what’s at fault. It’s either the rule or it’s ipfw. I’m undecided. I’ve posted a message to the questions mailing list.
I’ve also noticed that it takes much longer to connect via IRC with the simple firewall model than with the open model. I have no idea why.
rc.firewall model | open | simple | time to connect via IRC | 0:02 | 1:30 |
Something is definitely wrong somewhere. I’ll find out where.
ipfw version
I’ve discovered which version of ipfw I’m running (as taken from /usr/src/sbin/ipfw/ipfw.c)* $Id: firewall.php,v 1.26 2007/08/27 16:34:46 dan Exp $
Speeding things up
In attempt at speeding up the connection time, I decided to remove some rules. After a few tests, I found this rule was the culprit:$fwcmd add deny log tcp from any to any in via ${oif} setup
This was the bottleneck. For whatever reason, this causes the connection time to become unacceptable long. Without this rule, the connect time is < 2s. With this rule, the time required to connect is > 1:30. Interesting! Perhaps I need other rules before this in order to speed things up.
After some talk in #nz, I was told that I was probably blocking ident. So I added the following two rules:
# allow IDENT $fwcmd add allow tcp from any to ${oip} 113 $fwcmd add allow udp from any to ${oip} 113
With this rule in placed, I removed the following rule which I added earlier:
pass all from any to any
ipfw with DHCP etc (added on 8 August 2000)
Ernie wrote in with these tips:
If you’re trying to configure your firewall to work with DHCP or another dynamic connection, then use this line in /etc/rc.firewall (ed. note: remember to change ep0 as appropriate to your situation):
onet=`ifconfig ep0 |grep "inet " |awk '{print $6}'`
to replace:
onet=255.255.255.x
Also replace the entry for the ip address with:
oip=`onet=`ifconfig ep0 |grep "inet " |awk '{print $2}'`
This works because rc.firewall is a shell script, and using the backticks runs the command within. Note that ifconfig ep0 gets all the information on the specified network interface, grep gets the right line, and awk sucks in the right field. (in this case, the netmask). I’d try this command at the command line before putting it into rc.firewall though. 🙂
Also remember when you’re setting up your firewall to actually block things, (ie, not "open") that the order of the firewall rules is very important, and that when ipfw blocks internet requests, it logs the information in /var/log/security (and sometimes /var/log/messages) complete with the rule number, which you can look up in the output from "ipfw show," making it easy to find out why people can’t get into your webserver. 🙂
Thanks Ernie.
Happened across the example for extracting the IP address,
which involves a pipeline similar to the following (translated
to use the NIC I happen to have on the machine I’m using at the
moment):
ifconfig an0 | grep "inet " | awk ‘{print $2}’
Comment is that it’s fairly rare to actually need the "grep"
invocation if you’re invoking "awk" anyhow; try:
ifconfig an0 | awk ‘/inet / {print $2}’
(Hmmm… looking at this, I note that it you have multiple IP
addresses assigned to the NIC in question — of course, for this
application, no one would do that, I suppose…. Anyhow, things
could get Fairly Weird for someone who might try such a thing.)
Hi,
a "deny" rule results in silently discarding a matching packed, a "reject" rule causes the network stack to generate an answer ("not reachable").
So if any program (may it be IRC or sendmail or whatever) tries to connect to the IDENT service of a "deny" protected host, it has to wait until a timeout occours.
With a "reject" rule the program usually doesn’t has to wait that long, because it gets an answer before the timeout is reached.
Instead of allowing the access to IDENT (if you haven’t it explicitely activated in inetd.conf, there’s nothing running anyway) you could "reject" connections while still getting the same benefit.
Bye,
Alexander.
Someone people consider the reject rule to be an acknowledgement that yes, the service exists, but not, I’m not going to deal with you. In this regard, from a security point of view, some consider deny better than reject.
Hello,
I would suggest that you investigate the IP address(es) of your favorite IRC servers, then add rules to either REJECT (** or ALLOW), from those IP(s), then another broader rule, to DENY IDENT from any.
That way, you’d be able to connect to your favorite IRC server(s) quickly, while remaining as secure as possible (any nefarious IDENT requests, could go to hell).
As a sweet by-product of your diligence, this is also a little friendlier to your chosen IRC servers.
** You may want to ALLOW IDENT as some IRC servers won’t allow you to connect without a valid IDENT.
Cheers!
Chris P
[%sig%]