Introduction
Firewalls make it possible to filter the incoming and outgoing traffic that flows
through a system. A firewall can use one or more sets of “rules” to inspect
network packets as they come in or go out of network connections and either allows the
traffic through or blocks it. The rules of a firewall can inspect one or more
characteristics of the packets such as the protocol type, source or destination host
address, and source or destination port.
Firewalls can enhance the security of a host or a network. They can be used to do one
or more of the following:
- 
Protect and insulate the applications, services, and   machines of an internal
network from unwanted traffic from   the public Internet.
 
- 
Limit or disable access from hosts of the internal   network to services of the
public Internet.
 
- 
Support network address translation   (NAT), which allows an internal network   to use private IP addresses and share a   single connection to the
public Internet using either a   single IP address or a shared pool of   automatically assigned public
addresses.
 
After reading this chapter, you will know:
- 
How to define packet filtering rules.
 
- 
The differences between the firewalls built into   FreeBSD.
 
- 
How to use and configure the   PF firewall.
 
- 
How to use and configure the   IPFILTER firewall.
 
- 
How to use and configure the   IPFW firewall.
 
Before reading this chapter, you should:
- 
Understand basic FreeBSD and Internet concepts.
Firewall
Concepts 
A firewall ruleset can be either “exclusive” or “inclusive”.
An exclusive firewall allows all traffic through except for the traffic matching the
ruleset. An inclusive firewall does the reverse as it only allows traffic matching the
rules through and blocks everything else.
An inclusive firewall offers better control of the outgoing traffic, making it a
better choice for systems that offer services to the public Internet. It also controls
the type of traffic originating from the public Internet that can gain access to a
private network. All traffic that does not match the rules is blocked and logged.
Inclusive firewalls are generally safer than exclusive firewalls because they
significantly reduce the risk of allowing unwanted traffic.
Note: Unless noted otherwise, all configuration and example  rulesets in
this chapter create inclusive firewall  rulesets.
 
Security can be tightened further using a “stateful  firewall”. This
type of firewall keeps track of open connections and only allows traffic which either
matches an existing connection or opens a new, allowed connection. The disadvantage of a
stateful firewall is that it can be vulnerable to Denial of Service (DoS) attacks if a lot of new connections are opened very
fast. Most firewalls use a combination of stateful and non-stateful behavior.
Firewall
Packages 
FreeBSD has three firewalls built into the base system: IPFILTER, also known as IPF, IPFIREWALL, also known as IPFW, and PF). FreeBSD also
provides two traffic shapers for controlling bandwidth usage: altq(4) and dummynet(4). Dummynet has
traditionally been closely tied with IPFW,
and ALTQ with PF. Each firewall uses rules to control the access of packets to and from a
FreeBSD system, although they go about it in different ways and each has a different rule
syntax.
FreeBSD provides multiple firewalls in order to meet the different requirements and
preferences for a wide variety of users. Each user should evaluate which firewall best
meets their needs.
Since all firewalls are based on inspecting the values of selected packet control
fields, the creator of the firewall ruleset must have an understanding of how
TCP/IP works, what the different values in
the packet control fields are, and how these values are used in a normal session
conversation. For a good introduction, refer to Daryl's TCP/IP  Primer
.The IPFILTER (IPF)
Firewall
IPFILTER is a cross-platform, open source firewall which has been ported to FreeBSD,
NetBSD, OpenBSD, SunOS™, HP/UX, and Solaris™ operating systems. 
IPFILTER is based on a kernel-side firewall and NAT mechanism that can be controlled and monitored by userland interface
programs. The firewall rules can be set or deleted using ipf(8). The NAT rules can be set or deleted using ipnat(8). Run-time
statistics for the kernel parts of IPFILTER can be printed using ipfstat(8). To log IPFILTER
actions to the system log files, use ipmon(8).
IPF was originally written using a rule processing logic of “the last matching
rule wins” and only used stateless rules. Over time, IPF has been enhanced to
include a “quick” option and a stateful “keep state” option which
modernized the rules processing logic. IPF's official documentation covers only the
legacy rule coding parameters and rule file processing logic and the modernized functions
are only included as additional options.
The instructions contained in this section are based on using rules that contain
“quick” and “keep state” as these provide the basic framework for
configuring an inclusive firewall ruleset.
For a detailed explanation of the legacy rules processing method, refer to http://www.munk.me.uk/ipf/ipf-howto.html and http://coombs.anu.edu.au/~avalon/ip-filter.html.
The IPF FAQ is at http://www.phildev.net/ipf/index.html.
A searchable archive of the IPFilter mailing list is available at http://marc.theaimsgroup.com/?l=ipfilter.
IPF is included in the basic FreeBSD install as a kernel  loadable module. The
system will dynamically load  this module at boot time when  ipfilter_enable="YES" is added to  rc.conf. The module enables logging and  default
pass all. To change the  default to block all, add a
 block all rule at the end of the  ruleset.
For users who prefer to statically compile IPF support  into a custom kernel, the
following IPF option statements,  listed in /usr/src/sys/conf/NOTES, are  available:
options IPFILTER
options IPFILTER_LOG
options IPFILTER_DEFAULT_BLOCK
options IPFILTER enables support for  the
“IPFILTER” firewall.
options IPFILTER_LOG enables IPF  logging using the
ipl packet logging  pseudo—device for every rule
that has the  log keyword.
options IPFILTER_DEFAULT_BLOCK changes  the default
behavior so that any packet not matching a  firewall pass
rule gets blocked.
These settings will take effect only after installing a  kernel that has been
built with the above options set.
To activate IPF at boot time, the following statements  need to be added to
/etc/rc.conf:
ipfilter_enable="YES"             # Start ipf firewall
ipfilter_rules="/etc/ipf.rules"   # loads rules definition text file
ipmon_enable="YES"                # Start IP monitor log
ipmon_flags="-Ds"                 # D = start as daemon
                                  # s = log to syslog
                                  # v = log tcp window, ack, seq
                                  # n = map IP & port to names
If there is a LAN behind the firewall that uses the  reserved private IP address
ranges, the following lines have  to be added to enable NAT  functionality:
gateway_enable="YES"              # Enable as LAN gateway
ipnat_enable="YES"                # Start ipnat function
ipnat_rules="/etc/ipnat.rules"    # rules definition file for ipnat 
 
 
 
To load the ruleset file, use ipf(8). Custom rules
 are normally placed in a file, and the following command can  be used to replace
the currently running firewall  rules:
# ipf -Fa -f /etc/ipf.rules
-Fa flushes all the internal rules  tables.
-f specifies the file containing the  rules to
load.
This provides the ability to make changes to a custom  rules file, run the above
IPF command, and thus update the  running firewall with a fresh copy of the rules
without having  to reboot the system. This method is convenient for testing  new
rules as the procedure can be executed as many times as  needed.
Refer to ipf(8) for details on the
other flags  available with this command.
ipf(8) expects the rules
file to be a standard text  file. It will not accept a rules file written as a script
 with symbolic substitution.
There is a way to build IPF rules that utilize the power  of script symbolic
substitution. For more information, see  .
The default behavior of ipfstat(8) is to retrieve
 and display the totals of the accumulated statistics gathered  by applying the
rules against packets going in and out of the  firewall since it was last started, or
since the last time the  accumulators were reset to zero using ipf   -Z.
Refer to ipfstat(8) for details.
The default ipfstat(8) output will look
something  like this:
input packets: blocked 99286 passed 1255609 nomatch 14686 counted 0
 output packets: blocked 4200 passed 1284345 nomatch 14687 counted 0
 input packets logged: blocked 99286 passed 0
 output packets logged: blocked 0 passed 0
 packets logged: input 0 output 0
 log failures: input 3898 output 0
 fragment state(in): kept 0 lost 0
 fragment state(out): kept 0 lost 0
 packet state(in): kept 169364 lost 0
 packet state(out): kept 431395 lost 0
 ICMP replies: 0 TCP RSTs sent: 0
 Result cache hits(in): 1215208 (out): 1098963
 IN Pullups succeeded: 2 failed: 0
 OUT Pullups succeeded: 0 failed: 0
 Fastroute successes: 0 failures: 0
 TCP cksum fails(in): 0 (out): 0
 Packet log flags set: (0)
When supplied with either -i for inbound  or
-o for outbound, the command will retrieve  and display
the appropriate list of filter rules currently  installed and in use by the
kernel.
ipfstat -in displays the inbound  internal rules table
with rule numbers.
ipfstat -on displays the outbound  internal rules table
with rule numbers.
The output will look something like this:
@1 pass out on xl0 from any to any
@2 block out on dc0 from any to any
@3 pass out quick on dc0 proto tcp/udp from any to any keep state
ipfstat -ih displays the inbound  internal rules table,
prefixing each rule with a count of how  many times the rule was matched.
ipfstat -oh displays the outbound  internal rules table,
prefixing each rule with a count of how  many times the rule was matched.
The output will look something like this:
2451423 pass out on xl0 from any to any
354727 block out on dc0 from any to any
430918 pass out quick on dc0 proto tcp/udp from any to any keep state
One of the most important options of  ipfstat is
-t which  displays the state table in a way similar to
how top(1)  shows the
FreeBSD running process table. When a firewall is  under attack, this function
provides the ability to identify  and see the attacking packets. The optional
sub-flags give  the ability to select the destination or source IP, port, or
 protocol to be monitored in real time. Refer to  ipfstat(8) for details.
 
In order for ipmon to work properly,  the kernel option
IPFILTER_LOG must be  turned on. This command has two
different modes. Native mode  is the default mode when the command is used without
 -D.
Daemon mode provides a continuous system log file so that  logging of past events
may be reviewed. FreeBSD has a built in  facility to automatically rotate system
logs. This is why  outputting the log information to syslogd(8) is better
 than the default of outputting to a regular file. The default  rc.conf  ipmon_flags statement uses
 -Ds:
ipmon_flags="-Ds" # D = start as daemon
                  # s = log to syslog
                  # v = log tcp window, ack, seq
                  # n = map IP & port to names
Logging provides the ability to review, after the fact,  information such as which
packets were dropped, what addresses  they came from and where they were going. These
can all  provide a significant edge in tracking down attackers.
Even with the logging facility enabled, IPF will not  generate any rule logging by
default. The firewall  administrator decides which rules in the ruleset should be
 logged and adds the log keyword to those rules. Normally,  only deny rules are
logged.
It is customary to include a “default deny   everything” rule with the
log keyword included as the  last rule in the ruleset. This makes it possible to see
all  the packets that did not match any of the rules in the  ruleset.
IPMON Logging
syslogd(8) uses its own
method for segregation of log  data. It uses groupings called “facility”
and  “level”. By default, IPMON in  -Ds
mode uses local0 as  the “facility” name. The
following levels can be  used to further segregate the logged data:
LOG_INFO - packets logged using the "log" keyword as the action rather than pass or block.
LOG_NOTICE - packets logged which are also passed
LOG_WARNING - packets logged which are also blocked
LOG_ERR - packets which have been logged and which can be considered short
In order to setup IPFILTER to log all data to  /var/log/ipfilter.log, first  create the empty file:
# touch /var/log/ipfilter.log
syslogd(8) is controlled by
definition statements in  /etc/syslog.conf. This file
offers  considerable flexibility in how  syslog will
deal with system  messages issued by software applications like IPF.
To write all logged messages to the specified file,  add the following statement
to  /etc/syslog.conf:
local0.* /var/log/ipfilter.log
To activate the changes and instruct syslogd(8)  to read the
modified /etc/syslog.conf,  run service
syslogd reload.
Do not forget to change  /etc/newsyslog.conf to rotate
the new  log file.
Messages generated by ipmon consist  of data fields
separated by white space. Fields common to  all messages are:
 
- 
The date of packet receipt.
 
- 
The time of packet receipt. This is in the form   HH:MM:SS.F, for hours, minutes,
seconds, and fractions   of a second.
 
- 
The name of the interface that processed the   packet.
 
- 
The group and rule number of the rule in the format   @0:17.
 
These can be viewed with  
ipfstat -in.
- 
The action: p for passed,   b
for blocked, S for   a short packet, n did not match any   rules, and L for a log
rule. The order   of precedence in showing flags is: S,
  p, b,   n, L. A capital   P
or B means that   the packet has been logged due to a global
logging   setting, not a particular rule.
 
- 
The addresses written as three fields: the source   address and port separated by
a comma, the -> symbol,   and the destination address and port. For example:
  209.53.17.22,80 ->   198.73.220.17,1722.
 
- 
PR followed by the protocol name   or number: for
example, PR tcp.
 
- 
len followed by the header length   and total length of
the packet: for example,   len 20 40.
 
If the packet is a 
TCP packet, there
 will be an additional field starting with a hyphen followed by  letters
corresponding to any flags that were set. Refer to  
ipf(5) for a list of letters
and their flags.
If the packet is an ICMP packet, there will be two fields  at the end: the first
always being “ICMP” and  the next being the ICMP message and sub-message
type,  separated by a slash. For example: ICMP 3/3 for a port  unreachable
message.
Building the Rule Script with Symbolic
 Substitution
Some experienced IPF users create a file containing the  rules and code them in a
manner compatible with running them  as a script with symbolic substitution. The
major benefit  of doing this is that only the value associated with the  symbolic
name needs to be changed, and when the script is  run all the rules containing the
symbolic name will have the  value substituted in the rules. Being a script, symbolic
 substitution can be used to code frequently used values and  substitute them in
multiple rules. This can be seen in the  following example.
The script syntax used here is compatible with the  
sh(1), 
csh(1), and 
tcsh(1) shells.
Symbolic substitution fields are prefixed with a  
$.
Symbolic fields do not have the $ prefix.
The value to populate the symbolic field must be enclosed  between double quotes
(
").
Start the rule file with something like this:
############# Start of IPF rules script ########################
oif="dc0"            # name of the outbound interface
odns="192.0.2.11"    # ISP's DNS server IP address
myip="192.0.2.7"     # my static IP address from ISP
ks="keep state"
fks="flags S keep state"
# You can choose between building /etc/ipf.rules file
# from this script or running this script "as is".
#
# Uncomment only one line and comment out another.
#
# 1) This can be used for building /etc/ipf.rules:
#cat > /etc/ipf.rules << EOF
#
# 2) This can be used to run script "as is":
/sbin/ipf -Fa -f - << EOF
# Allow out access to my ISP's Domain name server.
pass out quick on $oif proto tcp from any to $odns port = 53 $fks
pass out quick on $oif proto udp from any to $odns port = 53 $ks
# Allow out non-secure standard www function
pass out quick on $oif proto tcp from $myip to any port = 80 $fks
# Allow out secure www function https over TLS SSL
pass out quick on $oif proto tcp from $myip to any port = 443 $fks
EOF
################## End of IPF rules script ########################
The rules are not important in this example as it instead  focuses on how the
symbolic substitution fields are populated.  If this example was in a file named
 
/etc/ipf.rules.script, these rules could  be reloaded
by running:
# sh /etc/ipf.rules.script
There is one problem with using a rules file with embedded  symbolics: IPF does
not understand symbolic substitution, and  cannot read such scripts directly.
This script can be used in one of two ways:
Now, when the system boots, the IPF rules will be  loaded.
 
IPF Rulesets
A ruleset contains a group of IPF rules which pass or  block packets based on the
values contained in the packet.  The bi-directional exchange of packets between hosts
comprises  a session conversation. The firewall ruleset processes both  the
packets arriving from the public Internet, as well as the  packets produced by the
system as a response to them.  Each 
TCP/IP service is predefined by its  protocol and listening port.
Packets destined for a specific  service originate from the source address using an
 unprivileged port and target the specific service port on the  destination
address. All the above parameters can be used as  selection criteria to create rules
which will pass or block  services.
Warning: When working with the firewall rules, be very   careful. Some configurations
can   lock the administrator
out of the server. To be   on the safe side, consider performing the
initial firewall   configuration from the local console rather than doing it  
remotely over ssh.
 
 
Rule Syntax
The rule syntax presented here has been simplified to  only address the modern
stateful rule context and “first  matching rule wins” logic. For the
complete legacy  rule syntax, refer to 
ipf(8).
A 
# character is used to mark the  start of a comment and
may appear at the end of a rule line  or on its own line. Blank lines are
ignored.
Rules contain keywords which must be written in a specific  order from left to
right on the line. Keywords are identified  in bold type. Some keywords have
sub-options which may be  keywords themselves and also include more sub-options. Each
 of the headings in the below syntax has a bold section header  which expands on
the content.
ACTION IN-OUT OPTIONS SELECTION STATEFUL   PROTO
SRC_ADDR,DST_ADDR OBJECT PORT_NUM TCP_FLAG   STATEFUL
ACTION = block | pass
IN-OUT = in | out
OPTIONS = log | quick | on  interface-name
SELECTION = proto value |  source/destination
IP | port = number | flags  flag-value
PROTO = tcp/udp | udp | tcp |  icmp
SRC_ADD,DST_ADDR = all | from  object to
object
OBJECT = IP address |  any
PORT_NUM = port number
TCP_FLAG = S
STATEFUL = keep state
ACTION
The action keyword indicates what to do with the packet   if it matches the rest
of the filter rule. Each rule   must have an action. The following   actions are
recognized:
block indicates that the packet   should be dropped if
the selection parameters match the   packet.
pass indicates that the packet should   exit the firewall
if the selection parameters match the   packet.
IN-OUT
A mandatory requirement is that each filter rule   explicitly state which side of
the I/O it is to be used   on. The next keyword must be either in   or out and one or the other has to be
  included or the rule will not pass syntax checks.
in means this rule is being applied   against an inbound
packet which has just been received on   the interface facing the public
Internet.
out means this rule is being applied   against an
outbound packet destined for the interface facing   the public Internet.
OPTIONS
Note: These options must be used in the order shown   here.
 
log indicates that the packet header   will be written to
the 
ipl(4) packet log
pseudo-device   if the selection parameters match the packet.
quick indicates that if the selection   parameters match
the packet, this rule will be the last   rule checked, and no further processing of
any following   rules will occur for this packet.
on indicates the interface name to   be incorporated into
the selection parameters. Interface   names are as displayed by 
ifconfig(8). Using this
  option, the rule will only match if the packet is going   through that
interface in the specified direction.
When a packet is logged, the headers of the packet are   written to the 
ipl(4) packet logging
pseudo-device.   Immediately following the 
log keyword,
  the following qualifiers may be used in this order:
body indicates that the first 128   bytes of the packet
contents will be logged after the   headers.
first. If the 
log   keyword is
being used in conjunction with a 
keep   state option, this
option is recommended so that   only the triggering packet is logged and not every
packet   which matches the stateful connection.
 
SELECTION
The keywords described in this section are used to   describe attributes of the
packet to be checked when   determining whether or not rules match. There is a  
keyword subject, and it has sub-option keywords, one of   which has to be selected.
The following general-purpose   attributes are provided for matching, and must be
used in   this order:
PROTO
proto is the subject keyword which   must include one of
its corresponding keyword sub-option   values. The sub-option indicates a specific
protocol to be   matched against.
tcp/udp | udp | tcp | icmp or any   protocol names found
in 
/etc/protocols   are recognized and may be used. The
special protocol   keyword 
tcp/udp may be used to match
  either a 
TCP or a 
UDP   packet, and has been added as a convenience to
save   duplication of otherwise identical rules.
 
SRC_ADDR/DST_ADDR
The all keyword is equivalent to   “from any to
any” with no other match   parameters.
from | to src to dst: the   from
and to   keywords are used to match against IP addresses.
Rules   must specify both the
source and   destination parameters. any is a special  
keyword that matches any IP address. Examples include:   from any
to any, from 0.0.0.0/0   to any, from any to   0.0.0.0/0, from 0.0.0.0 to  
any, and from any to   0.0.0.0.
There is no way to match ranges of IP addresses which   do not express themselves
easily using the dotted numeric   form / mask-length notation. The net-mgmt/ipcalc port may be   used to ease the calculation.
Additional information   is available at the utility's web page: http://jodies.de/ipcalc.
PORT
If a port match is included, for either or both of   source and destination, it is
only applied to   
TCP and 
UDP packets.   When composing port comparisons, either
the service name   from 
/etc/services or an integer port
  number may be used. When the port appears as part of the   
from object, it matches the source port   number. When it appears as
part of the   
to object, it matches the destination  
port number. An example usage is 
from any to any   port =
80
Single port comparisons may be done in a number of ways,   using a number of
different comparison operators. Instead   of the 
= shown in
the example above,   the following operators may be used: 
!=,   
<, 
>,
  
<=, 
>=,   
eq, 
ne,   
lt,
gt,   
le, and 
ge.
To specify port ranges, place the two port numbers   between 
<> or   
>< 
TCP_FLAG
Flags are only effective for 
TCP  
filtering. The letters represent one of the possible flags   that can be matched
against the 
TCP   packet header.
The modernized rules processing logic uses the   
flags S
parameter to identify the TCP   session start request.
 
STATEFUL
keep state indicates that on a pass   rule, any packets
that match the rules selection parameters   should activate the stateful filtering
facility.
 
Stateful Filtering
Stateful filtering treats traffic as a bi-directional  exchange of packets
comprising a session. When activated,  
keep-state
dynamically generates  internal rules for each anticipated packet being exchanged
 during the session. It has sufficient matching capabilities  to determine if a
packet is valid for a session. Any packets  that do not properly fit the session
template are  automatically rejected.
IPF stateful filtering will also allow  
ICMP packets related to an existing  
TCP or 
UDP session. So,  if
an 
ICMP type 3 code 4 packet is a
 response in a session started by a keep state rule, it will  automatically be
allowed. Any packet that IPF can be certain  is part of an active session, even if it
is a different  protocol, will be allowed.
Packets destined to go out through the interface connected  to the public Internet
are first checked against the dynamic  state table. If the packet matches the next
expected packet  comprising an active session conversation, it exits the
 firewall and the state of the session conversation flow is  updated in the
dynamic state table. Packets that do not  belong to an already active session, are
checked against the  outbound ruleset.
Packets coming in from the interface connected to the  public Internet are first
checked against the dynamic state  table. If the packet matches the next expected
packet  comprising an active session, it exits the firewall and the  state of the
session conversation flow is updated in the  dynamic state table. Packets that do not
belong to an already  active session, are checked against the inbound
 ruleset.
When the session completes, it is removed from the  dynamic state table.
Stateful filtering allows one to focus on blocking/passing  new sessions. If the
new session is passed, all its  subsequent packets are allowed automatically and any
impostor  packets are automatically rejected. If a new session is  blocked, none
of its subsequent packets are allowed. Stateful  filtering provides advanced matching
abilities capable of  defending against the flood of different attack methods
 employed by attackers.
 
Inclusive Ruleset
Example
The following ruleset is an example of an inclusive type  of firewall which only
allows services matching  
pass rules and blocks all others
by  default. Network firewalls intended to protect other machines  should have at
least two interfaces, and are generally  configured to trust the 
LAN and to not  trust the public Internet.
Alternatively, a host based  firewall might be configured to protect only the system
it is  running on, and is appropriate for servers on an untrusted  network or a
desktop system not protected by firewall on the  network.
FreeBSD uses interface 
lo0 and IP  address 
127.0.0.1 for internal  communication within the operating system. The
firewall rules  must contain rules to allow free movement of these internally
 used packets.
The interface which faces the public Internet is the one  specified in the rules
that authorize and control access of  the outbound and inbound connections.
In cases where one or more NICs are cabled to private  network segments, those
interfaces may require rules to allow  packets originating from those LAN interfaces
transit to each  other or to the Internet.
The rules should be organized into three major  sections: the trusted interfaces,
then the public  interface outbound, and lastly, the public untrusted interface
 inbound.
The rules in each of the public interface sections should  have the most
frequently matched rules placed before less  commonly matched rules, with the last
rule in the section  blocking and logging all packets on that interface and
 direction.
The outbound section in the following ruleset only  contains 
pass rules which uniquely identify  the services that are authorized
for public Internet access.  All the rules use 
quick,
 
on, 
proto,  
port, and 
keep state.  The 
proto tcp rules include  
flag to identify the
session start request  as the triggering packet to activate the stateful
 facility.
The inbound section blocks undesirable packets first, for  two different reasons.
The first is that malicious packets  may be partial matches for legitimate traffic.
These packets  have to be discarded rather than allowed, based on their  partial
matches against the 
allow rules.  The second reason is that
known and uninteresting rejects may  be blocked silently, rather than being logged by
the last rule  in the section.
The ruleset should ensure that there is no response  returned for any undesirable
traffic. Invalid packets should  be silently dropped so that the attacker has no
knowledge if  the packets reached the system. Rules that include a  
log first option, will only log the event  the first time they are
triggered. This option is included in  the sample 
nmap OS
fingerprint rule. The  
security/nmap utility is  commonly used by attackers who attempt
to identify the  operating system of the server.
Any time there are logged messages on a rule with  the 
log
first option,  
ipfstat -hio should be executed  to
evaluate how many times the rule has been matched. A  large number of matches usually
indicates that the system is  being flooded or is under attack.
To lookup unknown port numbers, refer to  
/etc/services.
Alternatively, visit  http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers  and do a
port number lookup to find the purpose of a  particular port number.
Check out this link for port numbers used by Trojans  http://www.sans.org/security-resources/idfaq/oddports.php.
The following ruleset creates an  
inclusive firewall
ruleset which can be  easily customized by commenting out  
pass rules for services that should not  be authorized.
To avoid logging unwanted messages, add a  
block rule in
the inbound section.
Change the 
dc0 interface name in  every rule to the
interface name that connects the system to  the public Internet.
The following statements were added to  
/etc/ipf.rules:
#################################################################
# No restrictions on Inside LAN Interface for private network
# Not needed unless you have LAN
#################################################################
#pass out quick on xl0 all
#pass in quick on xl0 all
#################################################################
# No restrictions on Loopback Interface
#################################################################
pass in quick on lo0 all
pass out quick on lo0 all
#################################################################
# Interface facing Public Internet (Outbound Section)
# Match session start requests originating from behind the
# firewall on the private network
# or from this gateway server destined for the public Internet.
#################################################################
# Allow out access to my ISP's Domain name server.
# xxx must be the IP address of your ISP's DNS.
# Dup these lines if your ISP has more than one DNS server
# Get the IP addresses from /etc/resolv.conf file
pass out quick on dc0 proto tcp from any to xxx port = 53 flags S keep state
pass out quick on dc0 proto udp from any to xxx port = 53 keep state
# Allow out access to my ISP's DHCP server for cable or DSL networks.
# This rule is not needed for 'user ppp' type connection to the
# public Internet, so you can delete this whole group.
# Use the following rule and check log for IP address.
# Then put IP address in commented out rule & delete first rule
pass out log quick on dc0 proto udp from any to any port = 67 keep state
#pass out quick on dc0 proto udp from any to z.z.z.z port = 67 keep state
# Allow out non-secure standard www function
pass out quick on dc0 proto tcp from any to any port = 80 flags S keep state
# Allow out secure www function https over TLS SSL
pass out quick on dc0 proto tcp from any to any port = 443 flags S keep state
# Allow out send & get email function
pass out quick on dc0 proto tcp from any to any port = 110 flags S keep state
pass out quick on dc0 proto tcp from any to any port = 25 flags S keep state
# Allow out Time
pass out quick on dc0 proto tcp from any to any port = 37 flags S keep state
# Allow out nntp news
pass out quick on dc0 proto tcp from any to any port = 119 flags S keep state
# Allow out gateway & LAN users' non-secure FTP ( both passive & active modes)
# This function uses the IPNAT built in FTP proxy function coded in
# the nat rules file to make this single rule function correctly.
# If you want to use the pkg_add command to install application packages
# on your gateway system you need this rule.
pass out quick on dc0 proto tcp from any to any port = 21 flags S keep state
# Allow out ssh/sftp/scp (telnet/rlogin/FTP replacements)
# This function is using SSH (secure shell)
pass out quick on dc0 proto tcp from any to any port = 22 flags S keep state
# Allow out insecure Telnet
pass out quick on dc0 proto tcp from any to any port = 23 flags S keep state
# Allow out FreeBSD CVSup
pass out quick on dc0 proto tcp from any to any port = 5999 flags S keep state
# Allow out ping to public Internet
pass out quick on dc0 proto icmp from any to any icmp-type 8 keep state
# Allow out whois from LAN to public Internet
pass out quick on dc0 proto tcp from any to any port = 43 flags S keep state
# Block and log only the first occurrence of everything
# else that's trying to get out.
# This rule implements the default block
block out log first quick on dc0 all
#################################################################
# Interface facing Public Internet (Inbound Section)
# Match packets originating from the public Internet
# destined for this gateway server or the private network.
#################################################################
# Block all inbound traffic from non-routable or reserved address spaces
block in quick on dc0 from 192.168.0.0/16 to any    #RFC 1918 private IP
block in quick on dc0 from 172.16.0.0/12 to any     #RFC 1918 private IP
block in quick on dc0 from 10.0.0.0/8 to any        #RFC 1918 private IP
block in quick on dc0 from 127.0.0.0/8 to any       #loopback
block in quick on dc0 from 0.0.0.0/8 to any         #loopback
block in quick on dc0 from 169.254.0.0/16 to any    #DHCP auto-config
block in quick on dc0 from 192.0.2.0/24 to any      #reserved for docs
block in quick on dc0 from 204.152.64.0/23 to any   #Sun cluster interconnect
block in quick on dc0 from 224.0.0.0/3 to any       #Class D & E multicast
##### Block a bunch of different nasty things. ############
# That I do not want to see in the log
# Block frags
block in quick on dc0 all with frags
# Block short tcp packets
block in quick on dc0 proto tcp all with short
# block source routed packets
block in quick on dc0 all with opt lsrr
block in quick on dc0 all with opt ssrr
# Block nmap OS fingerprint attempts
# Log first occurrence of these so I can get their IP address
block in log first quick on dc0 proto tcp from any to any flags FUP
# Block anything with special options
block in quick on dc0 all with ipopts
# Block public pings
block in quick on dc0 proto icmp all icmp-type 8
# Block ident
block in quick on dc0 proto tcp from any to any port = 113
# Block all Netbios service. 137=name, 138=datagram, 139=session
# Netbios is MS/Windows sharing services.
# Block MS/Windows hosts2 name server requests 81
block in log first quick on dc0 proto tcp/udp from any to any port = 137
block in log first quick on dc0 proto tcp/udp from any to any port = 138
block in log first quick on dc0 proto tcp/udp from any to any port = 139
block in log first quick on dc0 proto tcp/udp from any to any port = 81
# Allow traffic in from ISP's DHCP server. This rule must contain
# the IP address of your ISP's DHCP server as it is the only
# authorized source to send this packet type. Only necessary for
# cable or DSL configurations. This rule is not needed for
# 'user ppp' type connection to the public Internet.
# This is the same IP address you captured and
# used in the outbound section.
pass in quick on dc0 proto udp from z.z.z.z to any port = 68 keep state
# Allow in standard www function because I have apache server
pass in quick on dc0 proto tcp from any to any port = 80 flags S keep state
# Allow in non-secure Telnet session from public Internet
# labeled non-secure because ID/PW passed over public Internet as clear text.
# Delete this sample group if you do not have telnet server enabled.
#pass in quick on dc0 proto tcp from any to any port = 23 flags S keep state
# Allow in secure FTP, Telnet, and SCP from public Internet
# This function is using SSH (secure shell)
pass in quick on dc0 proto tcp from any to any port = 22 flags S keep state
# Block and log only first occurrence of all remaining traffic
# coming into the firewall. The logging of only the first
# occurrence avoids filling up disk with Denial of Service logs.
# This rule implements the default block.
block in log first quick on dc0 all
################### End of rules file #####################################
 
NAT
NAT stands for 
Network   Address Translation. In
Linux®, NAT is called  “IP
Masquerading”. The IPF  
NAT
function enables the private LAN behind  the firewall to share a single ISP-assigned
IP address, even  if that address is dynamically assigned. NAT allows each
 computer in the LAN to have Internet access, without  having to pay the ISP for
multiple Internet accounts or IP  addresses.
NAT will automatically translate the
 private LAN IP address for each system on the LAN to the  single public IP
address as packets exit the firewall bound  for the public Internet. It also performs
the reverse  translation for returning packets.
According to RFC 1918, the following IP address ranges are  reserved for private
networks which will never be routed  directly to the public Internet, and therefore
are available  for use with NAT:
- 
10.0.0.0/8.
 
- 
172.16.0.0/12.
 
- 
192.168.0.0/16.
 
 
IPNAT
NAT rules are loaded using  
ipnat. Typically, the  
NAT
rules are stored in  
/etc/ipnat.rules. See 
ipnat(8) for
 details.
When the file containing the 
NAT rules
 is edited after 
NAT has been started,
run  
ipnat with 
-CF to delete
 the internal in use 
NAT rules and flush
the  contents of the translation table of all active  entries.
To reload the 
NAT rules, issue a
 command like this:
# ipnat -CF -f
   /etc/ipnat.rules
To display some 
NAT statistics, use
 this command:
# ipnat -s
To list the 
NAT table's current
 mappings, use this command:
# ipnat -l
To turn verbose mode on and display information relating  to rule processing and
active rules/table entries:
# ipnat -v
 
IPNAT Rules
NAT rules are flexible and can
 accomplish many different things to fit the needs of  commercial and home
users.
The rule syntax presented here has been simplified to  what is most commonly used
in a non-commercial environment.  For a complete rule syntax description, refer to
 
ipnat(5).
The syntax for a 
NAT rule looks like
 this:
map IF LAN_IP_RANGE -> PUBLIC_ADDRESS
The keyword 
map starts the rule.
Replace 
IF with the external  interface.
The 
LAN_IP_RANGE is used by the  internal
clients use for IP Addressing. Usually, this is  something like 
192.168.1.0/24.
The 
PUBLIC_ADDRESS can either  be the static
external IP address or the special keyword  
0/32 which uses
the IP address assigned to  
IF.
 
How NAT Works
In IPF, when a packet arrives at the firewall from the LAN  with a public
destination, it passes through the outbound  filter rules. 
NAT gets its turn at the  packet and applies its rules top down,
where the first  matching rule wins. 
NAT
tests each of its  rules against the packet's interface name and source IP
 address. When a packet's interface name matches a  
NAT rule, the packet's source IP address in  the private LAN is
checked to see if it falls within the IP  address range specified to the left of the
arrow symbol on the  
NAT rule. On a
match, the packet has its  source IP address rewritten with the public IP address
 obtained by the 
0/32 keyword.  
NAT posts an entry in its internal  
NAT table so when the packet returns from  the public Internet it
can be mapped back to its original  private IP address and then passed to the filter
rules for  processing.
 
Enabling IPNAT
To enable IP
NAT, add these statements
 to 
/etc/rc.conf.
To enable the machine to route traffic between  interfaces:
gateway_enable="YES"
To start IP
NAT automatically each
 time:
ipnat_enable="YES"
To specify where to load the IP
NAT
 rules from:
ipnat_rules="/etc/ipnat.rules"
 
NAT for a Large LAN
For networks that have large numbers of systems on the LAN  or networks with more
than a single LAN, the process of  funneling all those private IP addresses into a
single public  IP address becomes a resource problem that may cause problems
 with the same port numbers being used many times across many  connections,
causing collisions. There are two ways to  relieve this resource problem.
Assigning Ports to
Use
A normal NAT rule would look like:
map dc0 192.168.1.0/24 -> 0/32
In the above rule, the packet's source port is unchanged   as the packet passes
through IP
NAT. By   adding the 
portmap keyword,   IP
NAT
can be directed to only use   source ports in the specified range. For example, the
  following rule will tell IP
NAT to
modify   the source port to be within the range shown:
map dc0 192.168.1.0/24 -> 0/32 portmap tcp/udp 20000:60000
Additionally, the 
auto keyword tells   IP
NAT to determine which ports are   available for
use:
map dc0 192.168.1.0/24 -> 0/32 portmap tcp/udp auto
 
Using a Pool of Public
Addresses
In very large LANs there comes a point where there are   just too many LAN
addresses to fit into a single public   address. If a block of public IP addresses is
available,   these addresses can be used as a “pool”, and  
IP
NAT may pick one of the public IP  
addresses as packet addresses are mapped on their way   out.
For example, instead of mapping all packets through a   single public IP
address:
map dc0 192.168.1.0/24 -> 204.134.75.1
A range of public IP addresses can be specified either   with a netmask:
map dc0 192.168.1.0/24 -> 204.134.75.0/255.255.255.0
or using CIDR notation:
map dc0 192.168.1.0/24 -> 204.134.75.0/24
 
 
Port Redirection
A common practice is to have a web server, email server,  database server, and DNS
server each segregated to a different  system on the LAN. In this case, the traffic
from these  servers still has to undergo 
NAT, but there  has to be some way to direct the inbound traffic to the
 correct server. For example, a web server operating on LAN  address 
10.0.10.25 and using a single public  IP address of 
20.20.20.5, would  use this rule:
rdr dc0 20.20.20.5/32 port 80 -> 10.0.10.25 port 80
or:
rdr dc0 0.0.0.0/0 port 80 -> 10.0.10.25 port 80
For a LAN DNS server on a private address of 
10.0.10.33 that
needs to receive   public DNS requests:
rdr dc0 20.20.20.5/32 port 53 -> 10.0.10.33 port 53 udp
 
FTP and NAT
FTP has two modes: active mode and passive mode. The  difference is in how the
data channel is acquired. Passive  mode is more secure as the data channel is
acquired by the  ordinal ftp session requester. For a good explanation of FTP
 and the different modes, see http://www.slacksite.com/other/ftp.html.
IPNAT Rules
IP
NAT has a built in FTP proxy option
  which can be specified on the 
NAT map
  rule. It can monitor all outbound packet traffic for FTP   active or passive
start session requests and dynamically   create temporary filter rules containing the
port number   being used by the data channel. This eliminates the   security risk
FTP normally exposes the firewall to as it no   longer needs to open large ranges of
high order ports for   FTP connections.
This rule will handle all the traffic for the internal   LAN:
map dc0 10.0.10.0/29 -> 0/32 proxy port 21 ftp/tcp
This rule handles the FTP traffic from the   gateway:
map dc0 0.0.0.0/0 -> 0/32 proxy port 21 ftp/tcp
This rule handles all non-FTP traffic from the internal   LAN:
map dc0 10.0.10.0/29 -> 0/32
The FTP 
map rules go before the   
NAT rule so that when a packet matches an   FTP rule,
the FTP proxy creates temporary filter rules to   let the FTP session packets pass
and undergo   
NAT. All LAN packets that
are not FTP   will not match the FTP rules but will undergo   
NAT if they match the third rule.
 
IPNAT FTP Filter Rules
Only one filter rule is needed for FTP if the   
NAT FTP proxy is used.
Without the FTP proxy, the following three rules will be   needed:
# Allow out LAN PC client FTP to public Internet
# Active and passive modes
pass out quick on rl0 proto tcp from any to any port = 21 flags S keep state
# Allow out passive mode data channel high order port numbers
pass out quick on rl0 proto tcp from any to any port > 1024 flags S keep state
# Active mode let data channel in from FTP server
pass in quick on rl0 proto tcp from any to any port = 20 flags S keep state