Monday, March 23, 2009

FreeBSD Setting up Firewall using IPFW

FreeBSD Setting up Firewall using IPFW
by Vivek Gite

Q. I'm new to FreeBSD and am trying to configure the firewall using IPFW, but I'm having a hard time understanding it as compare to Linux. Can you provide a small example on how to go about setting up the rules for a typical FreeBSD based Apache Web server?

A. Ipfirewall (ipfw) is a FreeBSD IP packet filter and traffic accounting facility.

IPFW is included in the basic FreeBSD install as a separate run time loadable module. The system will dynamically load the kernel module when the rc.conf statement firewall_enable="YES" is used.

FreeBSD compile kernel for IPFW
This step is optional. You do not need to compile IPFW into the FreeBSD kernel unless you want NAT function enabled. However some old version may not have IPFW compiled. Here is a quick guide to compile kernel with IPFW.

Make sure IPFW support not compiled into the kernel:
#ipfw list

If you get an error that read as follows, you must now compile the source code for the kernel.
ipfw: getsockopt(IP_FW_GET): Protocol not available
Another option is open default kernel config file /usr/src/sys/i386/conf and look for IPFIREWALL option:
# grep IPFIREWALL /usr/src/sys/i386/conf

Building and Installing a Custom Kernel with IPFW
Copy default kernel file:
# cd /usr/src/sys/i386/conf
# cp GENERIC IPFWKERNEL

Add IPFW support:
# vi IPFWKERNEL
Append following directives:
options IPFIREWALL # required for IPFW
options IPFIREWALL_VERBOSE # optional; logging
options IPFIREWALL_VERBOSE_LIMIT=10 # optional; don't get too many log entries
options IPDIVERT # needed for natd

Save and close the file. Building a Kernel, type following commnds:
# cd /usr/src
# make buildkernel KERNCONF=IPFWKERNEL

Install the new kernel:
# make installkernel KERNCONF=IPFWKERNEL

Now reboot the system:
# reboot

Step # 1: Enabling IPFW
Open /etc/rc.conf file
# vi /etc/rc.conf

Append following settings:
firewall_enable="YES"
firewall_script="/usr/local/etc/ipfw.rules"
Save and close the file..

Step # 2 Write a Firewall Rule Script
You need to place a firewall rules in a script called /usr/local/etc/ipfw.rule:
# vi /usr/local/etc/ipfw.rules

Append following code:

IPF="ipfw -q add"
ipfw -q -f flush

#loopback
$IPF 10 allow all from any to any via lo0
$IPF 20 deny all from any to 127.0.0.0/8
$IPF 30 deny all from 127.0.0.0/8 to any
$IPF 40 deny tcp from any to any frag

# statefull
$IPF 50 check-state
$IPF 60 allow tcp from any to any established
$IPF 70 allow all from any to any out keep-state
$IPF 80 allow icmp from any to any

# open port ftp (20,21), ssh (22), mail (25)
# http (80), dns (53) etc
$IPF 110 allow tcp from any to any 21 in
$IPF 120 allow tcp from any to any 21 out
$IPF 130 allow tcp from any to any 22 in
$IPF 140 allow tcp from any to any 22 out
$IPF 150 allow tcp from any to any 25 in
$IPF 160 allow tcp from any to any 25 out
$IPF 170 allow udp from any to any 53 in
$IPF 175 allow tcp from any to any 53 in
$IPF 180 allow udp from any to any 53 out
$IPF 185 allow tcp from any to any 53 out
$IPF 200 allow tcp from any to any 80 in
$IPF 210 allow tcp from any to any 80 out

# deny and log everything
$IPF 500 deny log all from any to anySave and close the file.


Step # 3: Start a firewall
You can reboot the box or you could reload these rules by entering on the command line.
# sh /usr/local/etc/ipfw.rules

Task: List all the rules in sequence
Type the following command:
# ipfw list

Further readings:
Refer ipfw man page
Read IPFW chapter from FreeBSD handbook
Read the FreeBSD kernel configuration file format chapter from FreeBSD handbook
Updated for accuracy.



# Set this to your ip address.
ip="192.168.1.5"
fwcmd="ipfw"
setup_loopback

# Allow anything outbound from this address.
${fwcmd} add allow all from ${ip} to any out

# Deny anything outbound from other addresses.
${fwcmd} add deny log all from any to any out

# Allow TCP through if setup succeeded.
${fwcmd} add allow tcp from any to any established

# Allow IP fragments to pass through.
${fwcmd} add allow all from any to any frag

# Allow all IPv6 packets through - they are handled by the separate
# ipv6 firewall rules in rc.firewall6.
${fwcmd} add allow ipv6 from any to any

# Allow inbound ftp, ssh, email, tcp-dns, http, https, imap, imaps,
# pop3, pop3s.
${fwcmd} add allow tcp from any to ${ip} 21 setup
${fwcmd} add allow tcp from any to ${ip} 22 setup
${fwcmd} add allow tcp from any to ${ip} 222 setup
${fwcmd} add allow tcp from any to ${ip} 25 setup
${fwcmd} add allow tcp from any to ${ip} 53 setup
${fwcmd} add allow tcp from any to ${ip} 80 setup
${fwcmd} add allow tcp from any to ${ip} 443 setup
${fwcmd} add allow tcp from any to ${ip} 143 setup
${fwcmd} add allow tcp from any to ${ip} 993 setup
${fwcmd} add allow tcp from any to ${ip} 110 setup
${fwcmd} add allow tcp from any to ${ip} 995 setup

# Deny inbound auth, netbios, ldap, and Microsoft's DB protocol
# without logging.
${fwcmd} add reset tcp from any to ${ip} 113 setup
${fwcmd} add reset tcp from any to ${ip} 139 setup
${fwcmd} add reset tcp from any to ${ip} 389 setup
${fwcmd} add reset tcp from any to ${ip} 445 setup

# Deny some chatty UDP broadcast protocols without logging.
${fwcmd} add deny udp from any 137 to any
${fwcmd} add deny udp from any to any 137
${fwcmd} add deny udp from any 138 to any
${fwcmd} add deny udp from any 513 to any
${fwcmd} add deny udp from any 525 to any

# Allow inbound DNS and NTP replies. This is somewhat of a hole,
# since we're looking at the incoming port number, which can be
# faked, but that's just the way DNS and NTP work.
${fwcmd} add allow udp from any 53 to ${ip}
${fwcmd} add allow udp from any 123 to ${ip}

# Allow inbound DNS queries.
${fwcmd} add allow udp from any to ${ip} 53

# Allow inbound NTP queries.
${fwcmd} add allow udp from any to ${ip} 123

# Allow traceroute to function, but not to get in.
${fwcmd} add unreach port udp from any to ${ip} 33435-33524

# Allow some inbound icmps - echo reply, dest unreach, source quench,
# echo, ttl exceeded.
${fwcmd} add allow icmp from any to any icmptypes 0,3,4,8,11

# Everything else is denied and logged.
${fwcmd} add deny log all from any to any

No comments: