Home arrow Guides arrow IPFW Firewall, Router and Traffic Shaping Quick Guide
IPFW Firewall, Router and Traffic Shaping Quick Guide PDF
Saturday, 11 June 2011
Here is a quick quide on IPFW FreeBSD's Firewall.  It shows you how to setup an IPFW Firewall. It also shows you how to configure a Router with NAT and Traffic Shapping.

IPFW Open Firewall
-----------------------

Here is a first example of IPFW as open firewall.

Recompile the kernel with the following options:
kernel options for ipfw
options IPDIVERT
options IPFIREWALL
options IPFIREWALL_VERBOSE
options IPFIREWALL_FORWARD
options DUMMYNET
options HZ=1000

Note: IPFIREWALL_FORWARD is deprecated as of FreeBSD 9.x versions.

Edit /etc/rc.conf and add the following lines:

add to /etc/rc.conf
firewall_enable="YES"
firewall_quiet="NO"
firewall_script="/etc/firewall"
firewall_logging="YES"

Now create a file and add the following lines (in order to create a simple firewall):

  edit /etc/firewall

/etc/firewall
#!/bin/sh
cmd="/sbin/ipfw -q"

# external interface
wan_if="em0"

# internal interface
lan_if="em1"

# flush rules
$cmd flush
$cmd pipe flush

# permit all
$cmd add 10 allow ip from any to any

We've just created a simple, open firewall. Every firewall with IPFW will start from here adding more complex rules.


Example 1. A simple router with IPFW
-------------------------------------------
Now we will build a simple router with IPFW. Well, the routing part of FreeBSD have nothing to do with IPFW (and you don't need IPFW only to route between computers) but we will use IPFW to allow some IPs from LAN to access the Internet.

To activate routing in FreeBSD add the following line to /etc/rc.conf:

  gateway_enable="YES"

Then we will build a simple firewall that will allow access to Internet only for two machines:

example 1. simple router
#!/bin/sh
cmd="/sbin/ipfw -q"

# external interface
wan_if="em0"

# internal interface
lan_if="em1"

# flush rules
$cmd flush
$cmd pipe flush

# allow on localhost
$cmd add 10 allow ip from any to any via lo0

# deny on 127.0.0.0/8
$cmd add 11 deny ip from any to 127.0.0.0/8
$cmd add 12 deny ip from 127.0.0.0/8 to any

# allow traffic to and from router
$cmd add 20 allow ip from any to me
$cmd add 30 allow ip from me to any

# permit 192.168.11.2
$cmd add 100 allow ip from 192.168.11.2 to any
$cmd add 110 allow ip from any to 192.168.11.2

# permit 192.168.11.3
$cmd add 120 allow ip from 192.168.11.3 to any
$cmd add 130 allow ip from any to 192.168.11.3

#$cmd add 140 allow ip from any to any

In this example only 192.168.11.2 and 192.168.11.3 are allowed to access the internet.

For this example the rc.conf of the router is:

/etc/rc.conf
defaultrouter="10.0.0.1"
hostname="router1"

ifconfig_em0="inet 10.0.0.1  netmask 255.255.255.0"
ifconfig_em1="inet 192.168.11.1  netmask 255.255.255.0"

gateway_enable="YES"

sshd_enable="YES"

ftpd_enable="YES"

firewall_enable="YES"
firewall_script="/etc/firewall"

This example works only if both IPs on em0 and em1 interface are public and the computer on our LAN is configured with public IP.
If we have IPs from 10.0.0.0/8 or 192.168.11.0/24 class, we must configure NAT on router.

In order for the router to work a FreeBSD sysctl variable must be configured. Run from command line:

  sysctl -w net.inet.ip.forwarding=1

Or add net.inet.ip.forwarding=1 to /etc/sysctl.conf.


Example 2. A router with bandwidth limit for a LAN computer
-----------------------------------------------------------------------

The next example uses a pipe of 512Kbits/s for the router and a pipe of 256Kbits/s for a LAN station:

firewall with bandwidth limit
#!/bin/sh
cmd="/sbin/ipfw -q"

# external interface
wan_if="em0"

# internal interface
lan_if="em1"

# flush rules
$cmd flush
$cmd pipe flush

# allow on localhost
$cmd add 10 allow ip from any to any via lo0

# deny on 127.0.0.0/8
$cmd add 11 deny ip from any to 127.0.0.0/8
$cmd add 12 deny ip from 127.0.0.0/8 to any

# allow traffic to and from router
$cmd add 20 allow ip from any to me
$cmd add 30 allow ip from me to any

$cmd pipe 1 config bw 512Kbit/s
$cmd add 100 set 1 pipe 1 all from any to me in
$cmd add 110 set 1 pipe 1 all from me to any out

$cmd pipe 2 config bw 256Kbit/s
$cmd add 200 set 2 pipe 2 all from 192.168.11.2 to any out
$cmd add 210 set 2 pipe 2 all from any to 192.168.11.2 in

# permit 192.168.11.2
$cmd add 1000 allow ip from 192.168.11.2 to any
$cmd add 1100 allow ip from any to 192.168.11.2

# permit 192.168.11.3
$cmd add 1200 allow ip from 192.168.11.3 to any
$cmd add 1300 allow ip from any to 192.168.11.3

#$cmd add 140 allow ip from any to any


Example 3. A router with IPFW's internal NAT
-----------------------------------------------------
Load ipfw_nat module with:

  kldload ipfw_nat.ko

Or recompile kernel with:

  options         IPFIREWALL_NAT
  options         LIBALIAS

Then we will use the following line in our firewall to enable IPFW's internal NAT:

  ipfw nat 1 config ip 10.0.0.1 same_ports              # 10.0.0.1 should be our WAN IP.

Now the complete firewall file will be:

router with IPFW and NAT
#!/bin/sh
cmd="/sbin/ipfw -q"

# external interface
wan_if="em0"

# internal interface
lan_if="em1"

# flush rules
$cmd flush
$cmd pipe flush

# allow on localhost
$cmd add 10 allow ip from any to any via lo0

# deny on 127.0.0.0/8
$cmd add 11 deny ip from any to 127.0.0.0/8
$cmd add 12 deny ip from 127.0.0.0/8 to any

# allow traffic to and from router
$cmd add 20 allow ip from any to me
$cmd add 30 allow ip from me to any

$cmd nat 1 config if $wan_if reset
$cmd add 14 nat 1 all from 192.168.11.0/24 to any via $wan_if out
$cmd add 15 nat 1 all from any to me via $wan_if in

$cmd pipe 1 config bw 1024Kbit/s
$cmd add 100 set 1 pipe 1 all from any to me in
$cmd add 110 set 1 pipe 1 all from me to any out

$cmd pipe 3 config bw 256Kbit/s
$cmd add 200 set 2 pipe 3 all from 192.168.11.3 to any out
$cmd add 210 set 2 pipe 3 all from any to 192.168.11.3 in

# permit 192.168.11.2
$cmd add 1000 allow ip from 192.168.11.2 to any
$cmd add 1100 allow ip from any to 192.168.11.2

# permit 192.168.11.3
$cmd add 1200 allow ip from 192.168.11.3 to any
$cmd add 1300 allow ip from any to 192.168.11.3


Example 4. Router with IPFW Nat and Upload and Download Limit
-----------------------------------------------------------------------------
See next firewall rule example:



Router with IPFW, NAT and Upload and Download Limit
#!/bin/sh
cmd="/sbin/ipfw -q"

# external interface
wan_if="em0"

# internal interface
lan_if="em1"

# flush rules
$cmd flush
$cmd pipe flush

# allow on localhost
$cmd add 10 allow ip from any to any via lo0

# deny on 127.0.0.0/8
$cmd add 11 deny ip from any to 127.0.0.0/8
$cmd add 12 deny ip from 127.0.0.0/8 to any

$cmd nat 1 config if $wan_if reset
$cmd add 14 nat 1 all from 192.168.11.0/24 to any via $wan_if out
$cmd add 15 nat 1 all from any to me via $wan_if in

# allow traffic to and from router
$cmd add 20 allow ip from any to me
$cmd add 30 allow ip from me to any


# upload
$cmd pipe 1 config bw 256Kbit/s mask src-ip 0x000000ff
$cmd add 100 pipe 1 ip from any to any in recv $lan_if

# download
$cmd pipe 3 config bw 512Kbit/s
$cmd add 200 set 2 pipe 3 all from 192.168.11.3 to any out
$cmd add 210 set 2 pipe 3 all from any to 192.168.11.3 in

# permit 192.168.11.3
$cmd add 1200 allow ip from 192.168.11.3 to any
$cmd add 1300 allow ip from any to 192.168.11.3


Example 5. Router with IPFW Nat Dynamic Limits
-----------------------------------------------------

In next example we limit upload and download for computers from LAN so that if we use multiple apps from a computer on LAN to download files or access the internet the traffic on that LAN computer will be dinamically adjusted so we could for example easily browse the net and in the mean time to get a file via FTP without affecting our browsing.

See next example:

Router with IPFW, NAT and Dynamic Limits
#!/bin/sh
cmd="/sbin/ipfw -q"

# external interface
wan_if="em0"

# internal interface
lan_if="em1"

# flush rules
$cmd flush
$cmd pipe flush


# allow on localhost
$cmd add 10 allow ip from any to any via lo0

# deny on 127.0.0.0/8
$cmd add 11 deny ip from any to 127.0.0.0/8
$cmd add 12 deny ip from 127.0.0.0/8 to any

# allow traffic to and from router
$cmd add 20 allow ip from any to me
$cmd add 30 allow ip from me to any

$cmd nat 1 config if $wan_if reset
$cmd add 14 nat 1 all from 192.168.12.0/24 to any via $wan_if out
$cmd add 15 nat 1 all from any to me via $wan_if in

# config pipes and queues for download
$cmd pipe 1 config bw 256Kbit/s
$cmd queue 1 config weight 1 pipe 1 queue 20 mask dst-ip 0x000000ff
$cmd queue 2 config weight 10 pipe 1 queue 20 mask dst-ip 0x000000ff

# upload
$cmd pipe 2 config bw 128Kbit/s mask src-ip 0x000000ff
$cmd add 100 pipe 2 ip from any to any in recv $lan_if

# download rules
$cmd add 400 queue 2 tcp from any to any out xmit $lan_if tcpflags ack iplen 0-52
$cmd add 410 skipto 1200 tcp from any to any out xmit $lan_if tcpflags ack iplen 0-52


Example 6. Filter traffic on layer2 based on MAC address
----------------------------------------------------------------------------

The following rules will allow traffic to the internet for three LAN clients with the following MAC addresses: 08:00:27:75:ba:cf   08:00:27:12:29:18      08:00:27:41:4e:76. Followig rules are only to allow/block traffic. You will also need rules for NAT and pipes/queues if you plan to do bandwidth shaping. Place the rules before your NAT rules.

/etc/firewall
$cmd add 12 allow ip from any to any layer2 mac-type arp
$cmd
add 14 allow ip from any to any MAC any 08:00:27:75:ba:cf in via $lan_if
$cmd add 15 allow ip from any to any MAC any 08:00:27:12:29:18 in via $lan_if
$cmd add 16 allow ip from any to any MAC any 08:00:27:41:4e:76 in via $lan_if

$cmd add 20 deny ip from any to any layer2 in via $lan_if
$cmd add 21 allow ip from any to any layer2 via $wan_if



IPFW Firewall Tips
---------------------
  /etc/firewall > /dev/null ; sleep 3
        # restart firewall from remote ssh without losing your ssh connection to the firewall
  ipfw show                                             # show ipfw rules with packet counts (equivalent with ipfw -a list)
  ipfw pipe show
                                     # see pipes from ipfw command line
  ipfw queue show                                  # see queues
  ipfw list                                                   # see list rules (order by the rule number)
  ipfw -t list                                                  # see list rules and also timestamp for last matched packet
  ipfw -d show                                           # also list dynamic rules
  ipfw table 1 list                                        # show ips from table 1

Don't forget to setup sysctl -w net.inet.ip.forwarding=1 when you build a router.

The following rules are equivalent:
  ipfw add allow ip from any to any
  ipfw add pass ip from any to any
  ipfw add permit ip from any to any


In a ipfw rule ip is equivalent to all.
In an ipfw rule drop is equivalent to deny. There is also reset which send a TCP reset to the initiator of the connection.

Last Updated ( Thursday, 16 October 2014 )
 
< Prev   Next >

Other BSD Systems

OpenBSD

Misc

Solaris

Polls

Best BSD firewall?