|
2.Enabling Ipfirewall(4)
Ipfirewall(4) can be enabled in two ways: add the appropriate options into your kernel configuration file and rebuild the kernel, or use
kldload(8) to dynamically load the basic ipfw.ko module into the kernel. Either approach works well for enabling basic ipfirewall(4) operations,
however, only the former allows you to add additional configuration options, such as logging.
To dynamically load ipfw one can simply issue the following command:
(root@nu)~># kldload ipfw
(root@nu)~>#
Enabling ipfirewall(4) statically, the equivalent would be to add the following line into your kernel configuration file:
optionsIPFIREWALL
Then, rebuilding and rebooting would enable ipfirewall(4) in the kernel statically.
However, things are not as simple as they may seem; one can only
do things exactly as above when one is in front of the console. Additional options are necessary to make the box usable. If you recall the discussion
above concerning firewall policies (open and closed), you will understand why things can get very messy when you realize that the default firewall
policy is closed. As such, if you simply enable ipfirewall(4) without any further actions, all network traffic will be blocked. This can become a
nightmare when enabling ipfirewall(4) remotely. Diasaster can be avoided, although, it is never recommened to remotely enable ipfirewall(4), either dynamically or statically.
If you wish to dynamically load ipfirewall(4) remotely, anyhow, the follow command is recommended:
(root@nu)~># kldload ipfw && \
ipfw -q add 65000 allow all from any to any (root@nu)~>#
This will automatically set a rule to allow all traffic instead of
blocking it, so you don't cut yourself off from your remote box. Likewise, this is recommended on local boxes as well if they are connected to a network and you don't want to lose your connexion.
Enabling ipfirewall(4) in the kernel statically in a remote box takes a little extra work. Once one has added the kernel option specified
earlier, in the kernel configuration file, and rebuilt the kernel, one has to then set at least two ipfirewall(4) options in rc.conf so that when the
box reboots, it will not be locked out by its own firewall with the default-to-close policy.
firewall_enable="YES" firewall_type="OPEN"
There are other firewall types defined in /etc/rc.firewall, but we will concern ourselves with those later. For now, a default open policy is
good practice for the beginner. Alternatively, one can enable a default open policy for ipfw(8) in the kernel, instead, by also adding the following option into the kernel configuration file:
optionsIPFIREWALL_DEFAULT_TO_ACCEPT
In this case, the rc.conf options noted above will not be *necessary* as we will not *need* to use /etc/rc.firewall to enable an
open policy because it will be enabled by default in the kernel. However, even if one chooses to enable this in the kernel, it is good practice to
enable the /etc/rc.conf options anyhow, because later we will be using /etc/rc.firewall to load custom rulesets. This also applies if one loads
the kernel dynamically, because eventually one will reboot, and the kernel ipfw.ko module will not be automatically loaded. The /etc/rc.conf firewall
enabling functions allow for a convenient place to load the ipfw.ko module.
With the additional options for ipfirewall(4) that are available
for enabling statically in the kernel, one soon realizes this is the better method for enabling ipfirewall(4), at least as FreeBSD is designed currently. Aside from IPFIREWALL_DEFAULT_TO_ACCEPT, we also have:
options IPFIREWALL_VERBOSE options IPFIREWALL_FORWARD options IPFIREWALL_VERBOSE_LIMIT=#
IPFIREWALL_VERBOSE allows one to log traffic with ipfirewall(4) by verbosely printing packet activity to syslogd(8) for every rule that has
the "log" keyword. This will be more clearly explained later.
IPFIREWALL_FORWARD allows one to forward packets to other hosts
with the 'fwd' command for ipfirewall(4), which will be dealt with in more depth later.
IPFIREWALL_VERBOSE_LIMIT=# specifies a limit to logging packets
from a particular rule. With this, syslogd(8) and one's console (unless disabled in /etc/syslog.conf, as will be shown later) will not be
overwhelmed with messages from ipfirewall(4) activity. The "#" is replaced with the number of consecutive times one wishes to log a given rule being activated.
If one has IPv6 enabled, then the following rules will apply to the corresponding firewall actions on IPv6 packets:
options IPV6FIREWALL
options IPV6FIREWALL_VERBOSE options IPV6FIREWALL_VERBOSE_LIMIT=100 options IPV6FIREWALL_DEFAULT_TO_ACCEPT
In addition, there are four more options associated with ipfirewall(4) that can be enabled in the kernel, but will not be discussed at this moment as they are not necessary for the basic firewall
activities, and involve more complex routing situations.
2.1.rc.firewall and OPEN firewalls
Whether one specifies a firewall type or not, once
firewall_enable="YES" is put into rc.conf and the system reboots, /etc/rc.firewall is started from rc.conf, and the following two commands are issued to ipfw(8) from within it:
${fwcmd} add 100 pass all from any to any via lo0 ${fwcmd} add 200 deny all from any to 127.0.0.0/8
{fwcmd} is defined early on in the rc.firewall script, depending
on whether one specified that ipfw(8) run quietly (with the -q option) or not. The first rule allows all traffic via the loopback device (lo0) to
pass, and the second rule blocks all traffic aimed at the localhost (127.0.0.0) network. The first rule is necessary to allow local IPC (inter-process communication) traffic, and the second rule is necessary so
that no external packets can ever be allowed to reach the localhost address, which is the address on the loopback device, thus protecting
one's local traffic. If these rules are missing, and the firewall defaults to a closed policy, you will see RPC(3) services break during startup, among other things.
Next, when one specifies a firewall type of "OPEN" in rc.conf, the following line in rc.firewall is activated:
${fwcmd} add 65000 pass all from any to any
This allows all external traffic in (except to the localhost), and all internal traffic out. It fulfills the same task as enabling the IPFIREWALL_DEFAULT_TO_ACCEPT in the kernel. If the open policy is enabled
in the kernel, then rule # 65535 will be automatically set to "allow ip from any to any" instead of "deny ip from any to any," thus making rule #
65000 as set in rc.firewall for the open policy redundant. As such, it is more apropos to indicate firewall type "UNKNOWN" if one enables an open
policy in the kernel, and does not wish to enable any other rules. For one wishes to, for instance, simply enable the firewall to play with and see
how it work,s or simply block packets from a single host, then leaving the firewall type open like this is sufficient and one can safely skip to section 3.
However, if one wishes to use one of the pre-built rulesets in rc.firewall, or create one's own custom rulesets, then neither options (OPEN or UNKNOWN) are sufficient.
2.2.Loading Rulesets
There are two generally different things that can be done concerning rulesets: use one of the pre-built ones in rc.firewall, or create your own. The author recommends the latter for two reasons:
- You can customize the firewall rules to your liking and needs without touching rc.firewall, which can be kept as a general reference.
- You will be forced harder to become familiarized with
ipfw(8) syntax, and as such, will become more comfortable with using ipfw(8).
2.2.1.Pre-defined Firewall Types
Of course, the final decision is the administrator's. If one
wishes to use one of the pre-built rulesets, then one should read through each of them in rc.firewall to become familiar with them before activating any of them. Which ruleset is loaded is controlled by the
firewall_type="" option in rc.conf. Aside from the "OPEN" type, there are three more predefined types available:
"CLIENT" This ruleset enables some basic rules. It allows all
traffic from the local network (which could be a private network behind NAT) to itself. It blocks fragmented packets. It allows mail, DNS and NTP
packets in and out of the network, and does not allow any host outside the private network to initiate TCP connexions with internal hosts. This would
already be impossible if the network was behind a vanilla NAT configuration without any special proxies. This configuration will work with both a default open or closed policy.
"SIMPLE" This ruleset is somewhat of any oxymoron - it is more complex than the CLIENT configuration and requires some knowledge of
internet RFCs to make sense of at first glance. It will attempt to stop spoofing by not allowing in external packets that have return addresses the same as that of any internal host. It will block all
private-net-addressesed packets as defined by RFC 1918 from leaking in or out, and will block all additional non-routable networks as defined in the Manning internet draft ( http://www.ietf.org/internet-drafts/draft-manning-dsua-03.txt ). It will allow mail, www, DNS, NTP traffic and fragmented
packets to pass through, and will not only block attempts for connexions to be initiated by outside hosts, like CLIENT, but will also log these attempts.
"CLOSED" This is technically not a rulest, because it does not enable any rules. In fact, it does everything we've been warning not to
do: allow the default closed policy to take hold over all traffic (except for traffic via lo0 as controlled by the rules explained earlier). It will
essentially disable all IP services, unless, one enabled the default open policy in the kernel. Don't do this.
2.2.2.Custom Firewall Types
If one has decided to instead load one's oen ruleset(s), then one should specify a file instead of one of the above types in the firewall_type option in rc.conf. For instance, one might have the
following in their rc.conf:
firewall_enable="YES" firewall_type="/etc/rc.firewall.rules"
This will allow one to define one's custom ipfirewall(4) ruleset
in /etc/rc.firewall.rules and have it run everytime during bootup. Furthermore, if one wanted to have the rules start quietly, one could also include the following in rc.conf:
firewall_quiet="YES"
The format of the ruleset in this file will be slightly different from that which is encountered in rc.firewall. This is because rc.firewall
is an sh(1) script designed to run on its own. The ipfirewall(4) rule file is there solely to be processed by ipfw(8). The primary difference will be
that where the shell variable {fwcmd} is invoked in rc.firewall, you will see nothing corresponding to it invoked in the ipfirewall(4) rule file -
simply the rules on their own. Later on, when we construct a sample rule file, we will go through this step by step.
3.Basic Ipfw(8) Rule Syntax
The rule syntax for ipfw(8) is pretty simple. Any rule can be enabled from the console with the ipfw(8) command. Before we delve into the rule syntax, however, we will quickly overview how to list the
ipfirewall(4) rules that have been activated.
3.1.Listing Rules
In its simplest form, we can list the rules with:
ipfw list
This will list all of the rules ordered by their rule number. To also list the timestamp of the last moment a packet was matched on a specific rule, the following command will accomplish this:
ipfw -t list
Finally, if we wish to list the packet count for matched rules along with the rules themselves, we can issue the following:
ipfw -a list
OR
ipfw show
Both will display the same information in the same way. The first column is the rule number, followed by the number of outgoing matched packets, followed by the number of incoming matched packets, and finally
followed by the rule itself.
3.2.Basic Commands and Actions
We will now gradually go through the various options available for
the construction of a stateless filtering ruleset. In our examples we will only state the rule not including the firewall control utility (/sbin/ipfw) which must precede each one if we're manually setting these
rules from the command prompt; otherwise, if we're construction a rule file to be passed to ipfw(8) we can use the sample lines as-is.
add 1000 allow all from any to any
This is the most benign example of a rule. We have already encountered the same rule, except for the rule #, in section 2.1 when
discussing the OPEN firewall type. Note: the "pass" parameter used in that rule, as written in rc.firewall, is synonym for "allow" and "permit" -
they are interchangable. In this rule, "all" packets from "any" source to "any" destination are allowed to pass.
With ipfirewall(4), under most circumstances, the moment a rule
matches a particular packet, then ruleset examination halts there.
As we see, the simplest syntax for ipfw(4) is:
<command> [<rule #>] <action> <proto> from <source> to
<destination>
The important commands are "add" and "delete." They are self-explanatory. Rule numbers start count at 0 and end at 65535. The last
rule number is always defined by the default firewall policy in the kernel. Even if you have an open policy defined in rc.conf, the last rule
will always reflect the kernel policy. This is fine because ruleset search halts at the first matching rule (usually), so if the penultimate (second
to last) rule is number 65000 and defined by rc.firewall to allow all packets, all packets will be allowed by default even if the last rule (65535) defines a closed kernel firewall policy, because the last rule
will never be reached.
"action" can be one of a number of things:
"allow" | "pass" | "permit" - Any packets matching a rule with
this action are allowed to pass through the firewall, and search of ruleset terminates.
"deny" | "drop" - Any packets matching a rule with this action are
silently blocked by the firewall and search of ruleset terminates.
add 1100 deny all from any to any
This would deny all packets from anywhere to anywhere.
"reset" - Any packets matching a rule with this action are blocked and the ipfirewall(4) attempts to send a TCP reset (RST) notice to the
source. The ruleset search is terminated. Naturally, because this only applies for TCP packets, the protocol must be "tcp," which matches only
TCP packets, and not "all," which matches all IP packets.
This action is sometimes useful for fooling network scanners that
would otherwise be able to detect a service behind a filtered port. On the other hand, it can become a liability if one is flooded at a particular IP
and port for which ipfirewall(4) is set to reply with a RST packet, thus doubling the usage of your bandwidth.
add 1200 reset tcp from any to any
This would deny all TCP packets from any to anywhere, and sent a TCP RST responce packet to the source for each.
"count" - Any packets matching a rule with this action will prompt
ipfirewall(4) to increment its packet counter. Search through the ruleset continues.
add 1300 count all from any to any
This would increment the packet counter for this rule, which
matches all packets coming from anywhere and going anywhere.
"skipto <number>" - Any packets matching a rule with this action
will prompt ipfirewall(4) to continue its search through the ruleset starting with the rule number equal to or greater than that which is indicated by <number>.
add 1400 skipto 1800 all from any to any
This would skip ruleset search to rule 1800 for any packets that matched this rule in the first place.
3.3.Specifying Protocols
The "proto" is the protocol that is desired to be matched. The keywords "ip" or "all" are catch-alls that match all protocols. The
commonly matched packet procotols are icmp, udp, and tcp, although, that is by no means an exhaustive list. For the complete list of possible protocols one can match, 'more /etc/protocols'.
3.4.Specifying the Source and Destination Addresses
The "source" and "destination" both take on the same format. They
can be a name, as defined in /etc/hosts or through DNS, an IP address, a network address with bitmask (or netmask), and can be optionally followed
by one or more ports numbers if the protocol is udp or tcp. Using names or IPs is straightforward, for instance:
add 1000 allow all from myhost to hishost add 1100 deny all from 10.0.0.5 to any
The first rule will allow all traffic from "myhost" to "hishost," and the second rule will deny all traffic from 10.0.0.5 to any host. Once
a packet matches one of these, ruleset examination for that packet ceases, and it is either passed or dropped, according to the action specified in
the rule it matched. This is a simple example of host-based filtering; that is, of filtering according to which hosts a packet is destined for,
or arriving from. Network-based filtering works similarly, and the network notation there utilizes either bitmasks or netmasks, for instance:
add 2000 allow all from 192.168.0.0/16 to any
add 2100 deny all from any to 10.0.0.0:255.0.0.0
The first rule allows all traffic from the network whose IP range is 192.168.0.0-192.168.255.255. It uses a bitmask to indicate this. A
bitmask specifies how many bits from the network address (192.168.0.0) should remain the same for matching packets. In this instance, the first
16 bits out of the 32 bit address will remain the same, and as the first 16 bits happen to be the first two octets, 192.168, all addresses whose
source addresses have the first two octets as 192.168 will be matched by this rule. The second rule accomplishes a similar thing using netmasks.
The netmask indicate how many bits from the indicated network address should be used for rule matching. In the above example, for rule two, the
netmask is 255.0.0.0. Its first octet is set with high bits; in other words, the first 8 bits are set high. This indicates to ipfw(8) that only
packets with the first 8 bits of the network address (10.0.0.0) should be matched. As the first 8 bits of the network address equal 10, then all
packets whose destination address have a 10 for the first octet (all addresses between 10.0.0.0 and 10.255.255.255) will be matched by this rule, and then dropped, as indicated by the action.
Rule matches can also be inverted with the "not" keyword. For instance, in the following ipfw(8) commands, all packets not from 192.168.0.3 are dropped:
add 1000 deny all from not 192.168.0.3
3.4.1.Introduction to Bitmasks and Netmasks
The principle behind bitmasks and netmasks is simple, but often confusing to new users, as it requires knowledge of binary numbers. It
makes far more sense if one worked with IP addresses in their binary form, however, the confounding of decimal and binary concepts easily throws
newcomers off. For a quick reference, the following table illustrates what network ranges are indicated by the corresponding bitmasks/netmasks up to
a default class C netmask and a couple quick examples of additional bitmask/netmask entries for larger networks:
BitmaskNetmaskTotal IPs / Usable IPs
32255.255.255.25511 31255.255.255.25421
30255.255.255.25242 29255.255.255.24886 28255.255.255.2401614 27255.255.255.2243230 26255.255.255.1926462 25255.255.255.128128126 24255.255.255.0256254
...
22255.255.192.01632016318
20255.255.128.03276832766 16255.255.0.06553665534 12255.128.0.08.388608+e6 8.388606+e6 8255.0.0.0256^3(256^3)-2 00.0.0.0(all IPs)256^4(256^4)-2
As you can see, there is a definite pattern. The number if total IPs always doubles, and the number of usable IPs is always total - 2. This
is because for every IP network/subnet there are two IPs reserved for the network and broadcast addresses. The netmask's last octet starts at 255
and constantly decreases by multiples of 2, while the bitmask decreases by multiples of 1, because in binary, each shift over to the left halves the
number, not divides by ten, like in the decimal number system. This same pattern goes for all possible netmasks and bitmasks.
For a quick example in using the above table/pattern, let us
figure out the IP range for the subnet indicated by:
172.16.100.32/28
First we notice that the network address is 172.16.100.32, so we
know that the subnet begins with this address. Second, we notice that the bitmask of 28 indicates that the last 4 bits (32-28) are set low and 28
bits set high. Because there are far less bits set low, it'll be easier to compute this using them. Because each bit has two possible values, 2^4
indicates how many hosts are referenced by this bitmask. In this case, 16. 172.16.100.32 + 16 = 172.16.100.48, so the IP range is 172.16.100.32 -
172.16.100.48. Looking at the table, we see that 16 IPs correspond to a bitmask of 28, so we could've used that to add to our network address and
avoided the other math, but it's so much better to know how to do it all on your own - learn once and use always.
3.4.2.Specifying Ports and Port Ranges
One can also do port-based filtering along with host and network-based filtering. Ports can be simply specified following the address of either a source of destination. Port ranges can be specified with a
dash, be comma-separated, or use a bitmask to specify a range. Most importantly, one can not use the "all" protocol when specifying ports because not all protocols are port-sensitive.
add 1000 allow tcp from any to 172.16.0.5 25 add 1100 allow tcp from any to 172.16.0.5 1021-1023 add 1200 allow tcp from any to 172.16.0.5 21,22,23 add 1300 deny udp from any to 192.168.0.5 1024:8
In the first rule all TCP packets which are destined for port 25 on 172.16.0.5 are matched. In the second rule, all TCP packets which are
destined for ports 1021 through 1023, inclusive, on host 172.16.0.5 are matched. In the third rule, all TCP packets which are destined for ports
21, 22 or 23 on host 172.15.0.5 are matched; and finally, in the fourth rule, all UDP packets which are destined for ports 1024 through 1028 on
host 172.16.0.5 are matched. The last rule can be tricky as it uses a bitmask on the port to make matches. The port 1024 contains 10 bits. The
bitmask indicates that all hosts matching the last 8 bits on that port, destined for host 192.168.0.5, are matched. 10 - 8 gives one 2 bits which
can be anything. 2^2 = 4, so we have 4 port numbers, starting with 1024, that can be the destination ports for packets aiming for that host, and will result in a match.
Bitmasks for ports are rarely used and are even trickier than bitmasks or netmasks for IP addresses, because the number of bits in a port varies depending on the port specified before the mask. As such, it
is recommended that one stick to specifying port ranges with a dash ( - ) or separate the list of ports with commas.
4.Advanced ipfw(8) Rule Syntax
Although the above overview of ipfw(8) rule creation will cover many of the simple scenarios, it sorely falls short for many more complex
situations, such as when a system has more than one network interface, one wishes to make special responces to certain matches, or one wants more
control over the direction of traffic flow. We will first expand the template for the ipfw(8) syntax to the follow:
<command> [<rule #>] <action> [log [logamount <number>]] <proto> from <source> to <destination> [<interface-spec>] [<options>]
Everything in brackets comprises new functionality we will discuss in this section. We will also cover an additional "action" that was not
covered earlier. The syntax may suddenly seem daunting, but we will take it slowly, and add each part as we go along, so as not to overwhelm you.
4.1."unreach" Action
Firstly, we will introduce a new "action:"
"unreach <code>" - Any packet which matches a rule with this action will reply with an ICMP unreach code, after which time the ruleset
search will terminate. The possible unreach codes can be indicated by number or name. The following is a quick list of ICMP unreach codes and
corresponding names. If you don't know what these are used for, you won't have a reason to use them:
net0net-prohib9 host1host-prohib10 protocol2tosnet11 port3toshost12 needfrag4filter-prohib13
srcfail5host-precedence14 net-unknown6precedence-cutoff15 host-unknown7 isolated8
4.2.Interface and Flow Control
One important functionality missing from the basic description of
ipfw(8) syntax in part 3 was interface and flow control; that is, the ability to match packets according to which interface (if you have a multihomed system) packets are moving through, and in which direction
they're moving. Up until now, direction was only loosely gauged by using the source and destination addresses, but using just them to guesstimate
whether a packet is really coming or going when it moves through the firewall is unreliable. If you wish to match packets only coming in or
going out, the keywords "in" and "out" can be used. Both correspond to the "interface-spec" area of the syntax template given earlier, and therefore,
are placed near the end of every rule, prior to any posible options. For instance, if we wish to match all packets coming in from anywhere and going anywhere, we could have:
add 1000 allow all from any to any in
To match packets going through a particular interface, use the "via" option followed by the interface name. For instance, if you are
using a PCI 3Com 3c59x, then your interface device will be xl0. To match all packets coming in through that interface specifically, sourced from anywhere and destined anywhere, the following would suffice:
add 1100 allow all from any to any in via xl0
Or, perhaps, if one has a multihomed system and wishes to match any packets coming from anywhere and going anywhere at least moving
outside through *some* interface, he can do the following:
add 1200 allow all from any to any out via any
One will notice, when listing firewall rules, that when using
either "in" or "out" in combination with "via" the rule as it actually looks does not contain a "via" but either "recv" or "xmit," depending on
whether an "in" or "out" was specified, respectively. For instance:
(root@nu)~># ipfw add 7000 allow all from any to any out via xl0 (root@nu)~># ipfw list | grep 7000
07000 allow ip from any to any out xmit xl0 (root@nu)~>#
Indeed, one can use either "recv" or "xmit" in place of "via" when using
"in" or "out," however, doing so is not required, and can add to some confusion for the newcomer.
In all, these options allow a lot more control over network
traffic on a multihomed system and any system in general, by allowing one to filter packets specifically coming into the firewall, exiting it, and moving through a specified interface.
4.3.Matching specific ICMP and TCP Packet Types
ICMP, TCP, and IP packets come in various types. These types are defined by the various flags that each of those packets sets. We can match
each of those types by using one of the following ipfw(8) options at the end of our rules.
4.3.1.icmptypes
"icmptypes <type>" - This will match the specified ICMP packet
<type>, and conversely, if a '!' is put before the <type> then all ICMP packets that are not of this type are match. There are currently 15
different ICMP packet types that can be matched; each is specified by the correct number. Ranges can be specified with dashes or be comma-separated. The 15 possible ICMP types are:
0-Echo Reply
3-Destination Unreachable 4-Source Quench 5-Redirect 8-Echo Request 9-Router Advertisement 10-Router Silicitation 11-Time-to-Live Exceeded 12-IP header bad 13-Timestamp Request
14-Timestamp Reply 15-Information Request 16-Information Reply 17-Address Mask Request 18-Address Mask Reply
If one is curious how these ICMP type, specifically type 3, correspond with the
Unreach codes that can be generated with the "unreach" action, then, simply type 3 matches any of those Unreach codes. Filtering
ICMP packet types can be very useful for controlling ping; specifically, for allowing internal hosts to ping out while blocking outside hosts from
pinging the gateway or any other host. The following three rules can accomplish this easily:
1000 allow icmp from any to any out icmptypes 8 1100 allow icmp from any to any in icmptypes 0
1200 deny icmp from any to any in icmptypes 8
The first rule allows all icmp packets of type 8 (echo request) to go out. The second rule allows all icmp packets of type 0 (echo reply) in,
and the final rule blocks all icmp packets of type 8 from entering. In short, it allows echo requests to go out and echo replies to come in, but
blocks echo requests from coming in. As such, hosts behind the firewall can ping anyone on the outside, while hosts on the outside can't ping
anyone behind the firewall. Naturally, this option can only be specified when the indicated procotol is "icmp."
4.3.2.tcpflags, setup and established
"tcpflags <flag>" - This will match any TCP packet whose header contains one of the following flags, or conversely, if '!' is presented
before the <flag>, match all TCP packets that do not have the <flag> set:
fin-Request for connexion termination syn-Request for connexion initiation rst-Reset Connexion psh-Push Flag
ack-Acknowledgement urg-Indicate Urgent OOB data
The SYN flag is of most interest as it is sent for initiation of TCP connecions. Because it is so important, there is a separate
ipfw(8) option dedicated specifically for matching TCP packets with the SYN flag set. This is called "setup." Naturally, this option can only be
specified when the indicated protocol is "tcp."
"setup" - Any rule containing this option will match any TCP packet with the SYN flag set. For instance, if we wished to deny all
incoming TCP SYN packets, we coul issue the following:
add deny tcp from any to any in tcpflags syn
OR
add deny tcp from any to any in setup
On either count, the same action is performed: all TCP SYN packets from "any" destined to "any" will be matched, and denied. As stated above
for "tcpflags", this option can only be used for rules when the indicated protocol is "tcp."
"established" - Just as there is a special option for indicating
the request for TCP connexion initiation ("setup") there is a special option for matching an already established TCP connexion. Because it is of
paramount important to easily control TCP connexions, "established" and "setup" are available for quick rule formation. Given these options (or
their corresponding "tcpflags" incarnations) we can have some simplistic control of TCP connexion activity. This is the very base of stateful
firewall functionality, which shall be dealt with in more detail later.
4.3.3.ipoptions
"ipoptions <flag>" - Finally, we can match for some specific IP packet flags, namely, for
SSRR (Strict Source Route), LSRR Loose Source Route, RR Record Packet Route, and TS (Timestamp) flags. If you do not know what any of these IP options do then you will not need to match for
them specifically.
4.4.Catching Fragmented Packets
Fragmented packets are matched with the "frag" ipfw(8) option. Under most circumstances fragmented packets should be blocked.
Receiving many fragmented packets may indicate a DoS (Denial of Service) attack, although FreeBSD and most other UNIX and UNIX-like systems will not be
phased by such attacks, Windows systems are often quite vulnerable. As such, if one has one or more Windows systems on their network behind the firewall, it is avisable to block fragmented packets.
When using the "frag" option to match [and block] fragmented packets, there are a couple guidelines that must be followed. Firstly, one
can not use the "frag" option when also specifying "tcpflags." Secondly, one can not use "frag" if also specifying any TCP or UDP ports. Given
these guidelines, we can easily issue a rule to block all incoming fragmented packets:
add deny all from any to any in frag
4.5.UID and GID Based Filtering
One powerful function that IPFilter does not have is UID/GID-based filtering. Ipfirewall(4) is able to filter packets according to the UID and/or the GID of the process from which they are arriving. Naturally,
this can only be used to match packets which originate from processes on the local host, however, it still offers a powerful functionality. The
options to be used are "uid" and "gid" followed by the UID/GID or name of the user or group by which we will be filtering.
One potential use is to restrict the use of IP vhosts on a shell server. If one wants to ensure that one or more vhosts can not be used by anyone else, one can easily use UID-based filtering to block everyone's
but one's own traffic from that vhost:
add allow tcp from any to 172.16.0.10 in add allow tcp from 172.16.0.10 to any out uid george add deny tcp from 172.168.0.10 to any
With the above rules, only user george would be able to use the aliased IP (IP vhost) 172.168.0.10 to establish TCP connexions to the outside. No one else would be able to bind bots, IRC chat clients, or what
have you, to that IP and establish connexions with anything that required TCP (most things). Likewise, the UDP protocol can be used with UID/GID-based filtering, however, no other protocol can be.
Another possible use of UID/GID-based filtering would be to enable bandwidth limiting on a per-user basis, as opposed to per-host or per-network basis. As such, one could, for example, have a group of users
that all have fast FTP accounts, and only moderately limit their GID, while on the other hand, have another group of shell users, who don't
require much bandwidth, and therefore significantly cap the bandwidth on the GID they all belong to. Such GID-based bandwidth capping will be illustrated later, once we cover the traffic shaping facilities of
ipfirewall(8).
For security purposes, one may wish to log the traffic of a particular user, and here too UID-based filtering would come in handy. In
short, whenever one would wish to conduct firewall behaviour differently for one or more users, UID/GID-based filtering would come in handy. Because, in general, once a rule is matched, search through the
ruleset stops, UID/GID matching rules must be invoked before other sweeping rules can match the traffic. So, when creating one's ruleset, one
must take this into careful account if one wishes to enable UID/GID-based filtering.
|
|