此一節的內容仍在陸續補充、更新,所以本節內容可能並未完全符合現況。.
The IPFIREWALL (IPFW) is a FreeBSD sponsored firewall software application authored and maintained by FreeBSD volunteer staff members. It uses the legacy stateless rules and a legacy rule coding technique to achieve what is referred to as Simple Stateful logic.
The IPFW sample rule set (found in
/etc/rc.firewall
) in the standard FreeBSD
install is rather simple and it is not expected that it used
directly without modifications. The example does not use
stateful filtering, which is beneficial in most setups, so it
will not be used as base for this section.
The IPFW stateless rule syntax is empowered with technically sophisticated selection capabilities which far surpasses the knowledge level of the customary firewall installer. IPFW is targeted at the professional user or the advanced technical computer hobbyist who have advanced packet selection requirements. A high degree of detailed knowledge into how different protocols use and create their unique packet header information is necessary before the power of the IPFW rules can be unleashed. Providing that level of explanation is out of the scope of this section of the handbook.
IPFW is composed of seven components, the primary component is the kernel firewall filter rule processor and its integrated packet accounting facility, the logging facility, the 'divert' rule which triggers the NAT facility, and the advanced special purpose facilities, the dummynet traffic shaper facilities, the 'fwd rule' forward facility, the bridge facility, and the ipstealth 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. You do not
need to compile IPFW into the FreeBSD kernel unless you want
NAT function enabled.
After rebooting your system with
firewall_enable="YES"
in
rc.conf
the following white highlighted
message is displayed on the screen as part of the boot
process:
The loadable module does have logging ability
compiled in. To enable logging and set the verbose logging
limit, there is a knob you can set in
/etc/sysctl.conf
by adding these
statements, logging will be enabled on future reboots:
It is not a mandatory requirement that you enable IPFW by compiling the following options into the FreeBSD kernel unless you need NAT function. It is presented here as background information.
This option enables IPFW as part of the kernel
Enables logging of packets that pass through IPFW and have the 'log' keyword specified in the rule set.
Limits the number of packets logged through syslogd(8) on a per entry basis. You may wish to use this option in hostile environments which you want to log firewall activity. This will close a possible denial of service attack via syslog flooding.
This option will allow everything to pass through the firewall by default, which is a good idea when you are first setting up your firewall.
These options are exactly the same as the IPv4 options but they are for IPv6. If you do not use IPv6 you might want to use IPV6FIREWALL without any rules to block all IPv6
This enables the use of NAT functionality.
If you do not include IPFIREWALL_DEFAULT_TO_ACCEPT or set your rules to allow incoming packets you will block all packets going to and from this machine.
If you do not have IPFW compiled into your kernel you will
need to load it with the following statement in your
/etc/rc.conf
:
Set the script to run to activate your rules:
Enable logging:
The only thing that the
firewall_logging
variable will do is
setting the net.inet.ip.fw.verbose
sysctl
variable to the value of 1
(see 節 28.6.1, “Enabling IPFW”). There is no
rc.conf
variable to set log limitations,
but it can be set via sysctl variable, manually or from the
/etc/sysctl.conf
file:
If your machine is acting as a gateway, i.e. providing
Network Address Translation (NAT) via natd(8), please
refer to 節 29.9, “Network Address Translation” for information
regarding the required /etc/rc.conf
options.
The ipfw command is the normal vehicle for making manual single rule additions or deletions to the firewall active internal rules while it is running. The problem with using this method is once your system is shutdown or halted all the rules you added or changed or deleted are lost. Writing all your rules in a file and using that file to load the rules at boot time, or to replace in mass the currently running firewall rules with changes you made to the files content is the recommended method used here.
The ipfw command is still a very useful to display the running firewall rules to the console screen. The IPFW accounting facility dynamically creates a counter for each rule that counts each packet that matches the rule. During the process of testing a rule, listing the rule with its counter is the one of the ways of determining if the rule is functioning.
To list all the rules in sequence:
#
ipfw list
To list all the rules with a time stamp of when the last time the rule was matched:
#
ipfw -t list
To list the accounting information, packet count for matched rules along with the rules themselves. The first column is the rule number, followed by the number of outgoing matched packets, followed by the number of incoming matched packets, and then the rule itself.
#
ipfw -a list
List the dynamic rules in addition to the static rules:
#
ipfw -d list
Also show the expired dynamic rules:
#
ipfw -d -e list
Zero the counters:
#
ipfw zero
Zero the counters for just rule
NUM
:
#
ipfw zero NUM
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 twice: 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 (i.e. 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 progress 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 parameters, the rules 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 search continues after count
,
skipto
and tee
rules.
The instructions contained here are based on using rules that contain the stateful 'keep state', 'limit', 'in'/'out', and via 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, much more secure than exclusive firewall rule sets and is the only rule set type covered here in.
When working with the firewall rules be careful, you can end up locking your self 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 ipfw(8) manual page.
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 them selves 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 lines. Blank lines are ignored.
CMD RULE_NUMBER ACTION LOGGING SELECTION
STATEFUL
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 at this rule.
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 criterion. 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.
log
or
logamount
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.
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 is up to you to decide which rules you want to enable logging on.
The keywords described in this section are used to describe attributes of the packet to be interrogated when determining whether rules match the packet or not. 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 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 FreeBSD system to represent the PC the
firewall is running on (i.e. 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 is 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. The in and out are keywords and it is mandatory that you code one or the other as part of your rule matching criterion.
via IF
Matches packets going through the interface specified
by exact name. The via
keyword causes
the interface to always be checked as part of the match
process.
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' can not 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.
'check-state' 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, FreeBSD version 4.5 added another new option named limit. This option is used to limit the number of simultaneous session conversations by interrogating the rules 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: it provides the ability to review after the fact the rules you activated logging on which provides information like, what packets had been dropped, what addresses they came from, where they were going, giving you a significant edge in tracking down attackers.
Even with the logging facility enabled, IPFW will not generate any rule logging on it's 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 is 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 are not careful, you can lose yourself in the over abundance of log data and fill your disk up with growing log files. DoS attacks that fill up disk drives is one of the oldest attacks around. These log message 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, five 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:
All logged packets 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 without 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 substitution 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 to "double quotes".
Start your rules file like this:
That is 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, you could reload
these rules by entering on the command line.
#
sh /etc/ipfw.rules
The /etc/ipfw.rules
file could be
located anywhere you want and the file could be named any
thing you would like.
The same thing could also be accomplished by running these commands by hand:
#
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
The following non-NATed rule set is an example of how to code a very secure 'inclusive' type of firewall. An inclusive firewall only allows services matching pass rules through and blocks all other by default. All firewalls have at the minimum two interfaces which have to have rules to allow the firewall to function.
All UNIX® flavored operating systems, FreeBSD included, are
designed to use interface lo0
and IP
address 127.0.0.1
for internal
communication with in the operating system. The firewall
rules must contain rules to allow free unmolested movement of
these special internally used packets.
The interface which faces the public Internet, is the one
which you code your rules to authorize and control access out
to the public Internet and access requests arriving from the
public Internet. This can be your ppp
tun0
interface or your NIC that is
connected to your DSL or cable modem.
In cases where one or more than one NIC are connected to a private LANs behind the firewall, those interfaces must have rules coded to allow free unmolested movement of packets originating from those LAN interfaces.
The rules should be first organized into three major sections, all the free unmolested interfaces, public interface outbound, and the public interface inbound.
The order of the rules in each of the public interface sections should be in order of the most used rules being placed before less often used rules with the last rule in the section being a block log all packets on that interface and direction.
The Outbound section in the following rule set only contains 'allow' rules which contain selection values that uniquely identify the service that is authorized for public Internet access. All the rules have the, proto, port, in/out, via and keep state option coded. The 'proto tcp' rules have the 'setup' option included to identify the start session request as the trigger packet to be posted to the keep state stateful table.
The Inbound section has all the blocking of undesirable packets first for two different reasons. First is these things being blocked may be part of an otherwise valid packet which may be allowed in by the later authorized service rules. Second reason is that by having a rule that explicitly blocks selected packets that I receive on an infrequent bases and do not want to see in the log, this keeps them from being caught by the last rule in the section which blocks and logs all packets which have fallen through the rules. The last rule in the section which blocks and logs all packets is how you create the legal evidence needed to prosecute the people who are attacking your system.
Another thing you should take note of, is there is no
response returned for any of the undesirable stuff, their
packets just get dropped and vanish. This way the attackers
has no knowledge if his packets have reached your system.
The less the attackers can learn about your system the more
secure it is. When you log packets with port numbers you do
not recognize, look the numbers up in
/etc/services/
or go to http://www.securitystats.com/tools/portsearch.php
and do a port number lookup to find what the purpose of that
port number is. Check out this link for port numbers used by
Trojans: http://www.simovits.com/trojans/trojans.html.
The following non-NATed rule set is a complete inclusive type ruleset. You can not go wrong using this rule set for you own. Just comment out any pass rules for services you do not want. If you see messages in your log that you want to stop seeing just add a deny rule in the inbound section. You have to change the 'dc0' interface name in every rule to the interface name of the NIC that connects your system to the public Internet. For user ppp it would be 'tun0'.
You will see a pattern in the usage of these rules.
All statements that are a request to start a session to the public Internet use keep-state.
All the authorized services that originate from the public Internet have the limit option to stop flooding.
All rules use in or out to clarify direction.
All rules use via interface name to specify the interface the packet is traveling over.
The following rules go into
/etc/ipfw.rules
.
There are some additional configuration statements that need to be enabled to activate the NAT function of IPFW. The kernel source needs 'option divert' statement added to the other IPFIREWALL statements compiled into a custom kernel.
In addition to the normal IPFW options in
/etc/rc.conf
, the following are
needed.
Utilizing stateful rules with divert natd rule (Network Address Translation) greatly complicates the rule set coding logic. The positioning of the check-state, and 'divert natd' rules in the rule set becomes very critical. This is no longer a simple fall-through logic flow. A new action type is used, called 'skipto'. To use the skipto command it is mandatory that you number each rule so you know exactly where the skipto rule number is you are really jumping to.
The following is an uncommented example of one coding method, selected here to explain the sequence of the packet flow through the rule sets.
The processing flow starts with the first rule from the top of the rule file and progress one rule at a time deeper into the file until the end is reach or the packet being tested to the selection criteria matches and the packet is released out of the firewall. It is important to take notice of the location of rule numbers 100 101, 450, 500, and 510. These rules control the translation of the outbound and inbound packets so their entries in the keep-state dynamic table always register the private LAN IP address. Next notice that all the allow and deny rules specified the direction the packet is going (IE outbound or inbound) and the interface. Also notice that all the start outbound session requests all skipto rule 500 for the network address translation.
Lets say a LAN user uses their web browser to get a web page. Web pages use port 80 to communicate over. So the packet enters the firewall, It does not match 100 because it is headed out not in. It passes rule 101 because this is the first packet so it has not been posted to the keep-state dynamic table yet. The packet finally comes to rule 125 a matches. It is outbound through the NIC facing the public Internet. The packet still has it's source IP address as a private LAN IP address. On the match to this rule, two actions take place. The keep-state option will post this rule into the keep-state dynamic rules table and the specified action is executed. The action is part of the info posted to the dynamic table. In this case it is "skipto rule 500". Rule 500 NATs the packet IP address and out it goes. Remember this, this is very important. This packet makes its way to the destination and returns and enters the top of the rule set. This time it does match rule 100 and has it destination IP address mapped back to its corresponding LAN IP address. It then is processed by the check-state rule, it's found in the table as an existing session conversation and released to the LAN. It goes to the LAN PC that sent it and a new packet is sent requesting another segment of the data from the remote server. This time it gets checked by the check-state rule and its outbound entry is found, the associated action, 'skipto 500', is executed. The packet jumps to rule 500 gets NATed and released on it's way out.
On the inbound side, everything coming in that is part of an existing session conversation is being automatically handled by the check-state rule and the properly placed divert natd rules. All we have to address is denying all the bad packets and only allowing in the authorized services. Lets say there is a apache server running on the firewall box and we want people on the public Internet to be able to access the local web site. The new inbound start request packet matches rule 100 and its IP address is mapped to LAN IP for the firewall box. The packet is them matched against all the nasty things we want to check for and finally matches against rule 425. On a match two things occur. The packet rule is posted to the keep-state dynamic table but this time any new session requests originating from that source IP address is limited to 2. This defends against DoS attacks of service running on the specified port number. The action is allow so the packet is released to the LAN. On return the check-state rule recognizes the packet as belonging to an existing session conversation sends it to rule 500 for NATing and released to outbound interface.
Example Ruleset #1:
The following is pretty much the same as above, but uses a self documenting coding style full of description comments to help the inexperienced IPFW rule writer to better understand what the rules are doing.
Example Ruleset #2:
本文及其他文件,可由此下載: ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/。
若有 FreeBSD 方面疑問,請先閱讀
FreeBSD 相關文件,如不能解決的話,再洽詢
<questions@FreeBSD.org>。
關於本文件的問題,請洽詢
<doc@FreeBSD.org>。