FreeBSD Stable Release 4.11 Installer Guide
Home______________________________________________________________________
A rule set is a group of ipfw rules coded to allow or deny packets based on the values contained in the packet. The bi-directional exchange of packets between hosts comprises a session conversation. The firewall rule set processes the packet two times, once on its arrival from the public Internet host and again as it leaves for its return trip back to the public Internet host. Each TCP/IP service (IE: telnet, www, mail, etc.) is predefined by its protocol and port number. This is the basic selection criteria used to create rules which will allow or deny services.
When a packet enters the firewall it is compared against the first rule in the rule set and progresses one rule at a time, moving from top to bottom of the set in ascending rule number sequence order. When the packet matches a rule selection parameter, the rule's action field value is executed and the search of the rule set terminates for that packet. This is referred to as the 'first match wins' search method. If the packet does not match any of the rules, it gets caught by the mandatory ipfw default rule, number 65535 which denies all packets and discards them without any reply back to the originating destination.
The instructions contained in this section of the Installers Guide is based on using rules that contain the stateful ‘keep state’ and ‘limit’ options. This is the basic framework for coding an inclusive type firewall rule set.
An inclusive firewall only allows services matching the rules through. This way you can control what services can originate behind the firewall destine for the public Internet and also control the services which can originate from the public Internet accessing your private network. Everything else is denied by default design. Inclusive firewalls are much more secure than exclusive firewall rule sets and are the only rule set type covered here in.
Installers Note: Warning, when working with the firewall rules, always, always do it from the root console of the system running the firewall or you can end up locking yourself out.
The rule syntax presented here has been simplified to what is necessary to create a standard inclusive type firewall rule set. For a complete rule syntax description see the online ‘man ipfw’ page at
Rules contain keywords. These keywords have to be coded 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.
# 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.
Syntax = CMD RULE# ACTION LOGGING SELECTION STATEFUL
CMD Each rule has to be prefixed with the following to add the rule to the internal table,
ipfw add
RULE# Coding rule numbers is not a mandatory requirement. Rule numbers will automatically be assigned when the rules are loaded into the internal IPFW tables. Coding your own rule numbers means the numbers will not change during loading and gives you a fixed rule number which is listed in the log along with other information about the packet being logged. The rule number is how you relate the logged packet back to the rule that caused the packet to be logged. If a rule is entered without a number, ipfw will assign one.
ACTIONS
A rule can be associated with one of the following actions which will be
executed when the packet matches the selection criterion of the rule.
allow | accept | pass | permit
These all mean the same thing which is to allow
packets that match the rule to exit the firewall
rule processing. The search terminates.
check-state
Checks the packet against the dynamic rules table.
If a match is found, execute the action associated with
the rule which generated this dynamic rule, otherwise move
to the next rule. The check-state rule does not have
selection criteria. If no check-state rule is present in
the rule set, the dynamic rules table is checked at the
first keep-state or limit rule.
deny | drop
Both words mean the same thing which is to discard packets
that match this rule. The search terminates.
LOGGING
log or logamount number
When a packet matches a rule with the log keyword, a message will be
logged to syslogd with a facility name of SECURITY. The logging only occurs
if the number of packets logged so far for that particular
rule does not exceed the logamount parameter. If no logamount is
specified, the limit is taken from the sysctl variable
net.inet.ip.fw.verbose_limit. In both cases, a value of zero removes
the logging limit. Once the limit is reached, logging can be
re-enabled by clearing the logging counter or the packet counter for
that rule. See the ipfw reset log command.
Note: logging is done after all other packet matching conditions have
been successfully verified and before performing the final action
(accept, deny) on the packet. It’s up to you to decide which rules
you want to enable logging on.
SELECTION
The keywords described in this section are used to describe attributes of the packet to be interrogated when determining whether rules match or don't match the packet. The following general-purpose attributes are provided for matching and must be used in this order:
udp | tcp | icmp
or any protocol names found in /etc/protocols are recognized
and may be used. The value specified is the protocol to be matched
against. This is a mandatory requirement.
from src to dst
The from and to keywords are used to match against IP addresses.
Rules must specify BOTH source and destination parameters.
any is a special keyword that matches any IP address.
me is a special keyword that matches any IP address configured
on an interface in your FBSD system to represent the PC
the firewall is running on. (IE: this box)
As in from me to any or from any to me or from 0.0.0.0/0 to any
or from any to 0.0.0.0/0 or from 0.0.0.0 to any or
from any to 0.0.0.0 or from me to 0.0.0.0 IP addresses are
specified as a dotted IP address numeric form/mask-length or
as single dotted IP address numeric form.
This is a mandatory requirement. See this link for
help on writing mask-lengths. http://jodies.de/ipcalc
port number
For protocols which support port numbers (such as TCP and UDP).
It’s mandatory that you code the port number of the service
you want to match on. Service names (from /etc/services) may be
used instead of numeric port values.
in | out
Matches incoming or outgoing packets, respectively. in and out
are keywords and it’s mandatory that you code one or the other
as part of your rule matching criterion.
via IFN
Matches packets going through the interface specified by exact
name. IFN = interface-name. The via keyword causes the interface
to always be checked as part of the match process.
via is mandatory.
setup
This is a mandatory keyword that identifies the session start
request for TCP packets.
keep-state
This is a mandatory keyword. Upon a match, the firewall will
create a dynamic rule whose default behavior is to match
bidirectional traffic between source and destination IP/port using
the same protocol.
limit {src-addr | src-port | dst-addr | dst-port}
The firewall will only allow N connections with the same set of
parameters as specified in the rule. One or more of source
and destination addresses and ports can be specified.
The ‘limit’ and 'keep-state’ cannot be used on same rule.
Limit provides the same stateful function as ‘keep-state’
plus its own functions.
Stateful filtering treats traffic as a bi-directional exchange of packets comprising a session conversation. It has the interrogation abilities to determine if the session conversation between the originating sender and the destination are following the valid procedure of bi-directional packet exchange. Any packets that do not properly fit the session conversation template are automatically rejected as impostors. This interrogation ability works for all the protocols.
The 'check-state' <action> is used to identify where in the IPFW rules set the packet is to be tested against the dynamic rules facility. On a match the packet exits the firewall to continue on its way and a new rule is dynamic created for the next anticipated packet being exchanged during this bi-directional session conversation. On a no match the packet advances to the next rule in the rule set for testing.
The dynamic rules facility is vulnerable to resource depletion from a SYN-flood attack which would open a huge number of dynamic rules. To counter this attack, FBSD version 4.5 added another new option named limit. This option is used to limit the number of simultaneous session conversations by interrogating the rule's source or destinations fields as directed by the limit option and using the packet's IP address found there. In a search of the open dynamic rules counting the number of times this rule and IP address combination occurred, if this count is greater that the value specified on the limit option, the packet is discarded.
The benefits of logging are obvious, provides information like, what packets have been dropped, what addresses they came from, and where they were going. This gives you a significant edge in tracking down attackers.
Even with the logging facility enabled, IPFW will not generate any rule logging on its own. The firewall administrator decides what rules in the rule set he wants to log and adds the log verb to those rules. Normally only deny rules are logged, like the deny rule for incoming icmp pings. It's very customary to duplicate the ipfw default deny everything rule with the log verb included as your last rule in the rule set. This way you get to see all the packets that did not match any of the rules in the rule set.
Logging is a two edged sword. If you're not careful, you can lose yourself in the over abundance of log data and fill all your free disk space with growing log files. DoS attacks that fill up disk drives is one of the oldest attacks around. These log messages are not only written to syslogd, but also are displayed on the root console screen and soon become very annoying.
The IPFIREWALL_VERBOSE_LIMIT=5 kernel option limits the number of consecutive messages sent to the system logger syslogd concerning the packet matching of a given rule. When this option is enabled in the kernel, the number of consecutive messages concerning a particular rule is capped at the number specified. There is nothing to be gained from 200 log messages saying the same identical thing. For instance, 5 consecutive messages concerning a particular rule would be logged to syslogd, the remainder identical consecutive messages would be counted and posted to the syslogd with a phrase like this:
last message repeated 45 times
All logged packet messages are written by default to /var/log/security file, which is defined in the /etc/syslog.conf file.
Most experienced IPFW users create a file containing the rules and code them in a manner compatible with running them as a script. The major benefit of doing this is the firewall rules can be refreshed in mass with out the need of rebooting the system to activate the new rules. This method is very convenient in testing new rules as the procedure can be executed as many times as needed. Being a script, you can use symbolic substitution to code frequent used values and substituting them in multiple rules. You will see this in the following example.
The script syntax used here is compatible with the 'sh', 'csh', 'tcsh' shells.
Symbolic substitution fields are prefixed with a dollar sign $.
Symbolic fields do not have the $ prefix
The value to populate the symbolic field must be enclosed in "double quotes".
Start your rules file with this.
############### start of example ipfw rules script #############
#
ipfw –q -f flush # Delete all rules
# Set defaults
oif="tun0" # out interface
odns="192.0.2.11" # ISP's dns server IP address
cmd="ipfw -q add " # build rule prefix
ks="keep-state" # just too lazy to key this each time
$cmd 00500 check-state
$cmd 00502 deny all from any to any frag
$cmd 00501 deny tcp from any to any established
$cmd 00600 allow tcp from any to any 80 out via $oif setup $ks
$cmd 00610 allow tcp from any to $odns 53 out via $oif setup $ks
$cmd 00611 allow udp from any to $odns 53 out via $oif $ks
################### End of example ipfw rules script ############
That's all there is to it. The rules are not important in this example; how the symbolic substitution field are populated and used are.
If the above example was in /etc/ipfw.rules file, I could reload these rules by entering on the FBSD command
sh /etc/ipfw.rules
The /etc/ipfw.rules file could be located anywhere you want and the file could be named anything you wanted.
The same thing could also to accomplished doing it this way as a text file
ipfw -q -f flush
ipfw -q add check-state
ipfw -q add deny all from any to any frag
ipfw -q add deny tcp from any to any established
ipfw -q add allow tcp from any to any 80 out via tun0 setup keep-state
ipfw -q add allow tcp from any to 192.0.2.11 53 out via tun0 setup keep-state
ipfw -q add 00611 allow udp from any to 192.0.2.11 53 out via tun0 keep-state
______________________________________________________________________
This FreeBSD Installer Guide is an public domain HOW-TO. This content may be reproduced, in any form or by any means, and used by all without permission in writing from the author.
Recent comments