IPFW2

IPFW2 is the default packet-filtering system on FreeBSD. It is referred to as IPFW; the IPFW2 distinction denotes improvements over the original IPFW1. The switch to IPFW2 occurred in the middle of 2002, so you shouldn't need to worry about the distinction. You can find it on BSD variants, including Mac OS X. Certain options will need to be compiled into your kernel to make IPFW work, primarily the IPFIREWALL and IPFIREWALL_VERBOSE options. If you want to use other popular IPFW features, you'll need the IPDIVERT and DUMMYNET options.

Implementation

An important thing to note is that FreeBSD's configuration files will automatically make use of IPFW whether you've explicitly told it to or not. By default, the system will parse the /etc/rc.firewall script as part of the bootup process. The rc.firewall script is extremely user friendly as it allows novice users to specify single descriptive words to configure the firewall (such as open or closed). It also enables more advanced users to define startup firewall rules so they will be loaded every time the system boots. By default, the rc.firewall should have a policy that denies all traffic. That means if you are first configuring and setting up IPFW from a remote location, there's a good chance you lock yourself out. The solution to this is to compile your kernel with the IPFIREWALL_DEFAULT_TO_ACCEPT option or to specify an open firewall type in the /etc/rc.conf startup script by saying firewall_type=open .

Unlike ipchains and iptables, IPFW doesn't have a concept of multiple chains through which each packet travels . With IPFW, rules are added to a single chain. You can specify an index for each rule that places the rule in a certain point in the chain. The lack of multiple chains simplifies IPFW's usage. Rules can be grouped into sets for easier configuration. This allows you to separate certain groups of related rules so that you can disable or enable certain groups under different circumstances.

IPFW has several actions that can be performed on a packet:

  • accept, allow, pass, permit Allow the packet to traverse. These are synonymous. This is a terminal action.

  • reset, unreach Block the packet and inform the sender of the rejection with an ICMP port unreachable message. This is a terminal action.

  • deny, drop Drop the packet altogether, with no information send to the packet's origin. This is a terminal action.

  • count Update the byte counter for the rule. Continue to the next rule.

  • log Log the match to syslog. Continue to the next rule.

IPFW also has stateful inspection capabilities. You can use the setup and established keywords to distinguish between new TCP connections and established TCP connections. All these two keywords really do, however, is check the TCP flags set on TCP packets. IPFW also has a keep-state keyword that can be used in combination with a check-state rule to make for a truly stateful packet filter.

Before we delve into IPFW's rule syntax, Table 13-4 will briefly discuss the available command-line options for IPFW.

Table 13-4: IPFW Options

Flag

Description

-a

When used as ipfw a list to list rules, displays the byte counters for each rule. The ipfw show command is the same as ipfw a list .

-c

Shows rules in compact format without unnecessary information. This suppresses redundant or implied information such as "ip from any to any."

-d

When used as ipfw d list to list rules, shows dynamic rules as well (such as keep-state and check-state ).

-e

When used as ipfw e list to list rules, shows any expired dynamic rules (rules expire using the limit keyword).

-f

Never ask for confirmation.

-N

Resolves addresses and port names .

-q

Doesn't output anything when manipulating rules; implies f .

-S

When used as ipfw S list to list rules, shows to which set each rule belongs, if any.

-t

When used as ipfw t list to list rules, shows the date and time of the last match on a rule.

Using IPFW Rules IPFW provides seven different commands for manipulating rules. They are briefly described in Table 13-5.

Table 13-5: IPFW Commands

Command

Description

ipfw add <index> <rule>

Adds the rule, placing it in the position specified by <index> . Use the N flag if you want to resolve addresses and port names.

ipfw delete <index>

Deletes the rule at position <index> .

ipfw flush

Flushes all rules except for the default policy (which is at the end of the chain on index 65535). The default policy will be to deny all packets unless you configured your kernel with IPFIREWALL_DEFAULT_TO_ACCEPT , so be careful using this command remotely as you can firewall yourself out of the system.

ipfw list

The list command lists the currently defined rules. You can use several command-line options for controlling the output format (discussed in Table 13-4).

ipfw show

Just like the list command but it also shows the byte counters for each rule.

ipfw zero [index]

Resets the packet counters for all rules or the rule specified by [index] .

ipfw resetlog

If a logamount is specified when logging packets to syslog and that logamount is reached, this command resets it, allowing packets matching that rule to be logged again.

We're mostly concerned with adding and deleting rules here. Let's add a very basic rule:

 ipfw add 100 allow ip from any to any out via ed1 

This rule says that we should allow any kind of IP packet to go out our external interface, ed1. We've specified that this rule be placed in position 100. If we don't specify an index, IPFW automatically spaces rules apart by increments of 100. Therefore, a subsequent IPFW rule without an explicit index would be placed at position 200.

So far, we've only allowed outgoing traffic to get out. We need to add rules that will let some traffic in. Let's write a rule that allows only web traffic in to our internal web server.

 ipfw add 200 allow tcp from any to 192.168.1.50 80 in via ed1 

What if we wanted to explicitly deny certain inbound traffic so that we could also log it, such as attempted telnets and FTPs?

 ipfw add 300  log  deny tcp from any to {me or 192.168.1.0/24} 23 in via ed1 ipfw add 400  log  deny tcp from any to {me or 192.168.1.0/24} 21 in via ed1 

Notice we've added the log keyword to the beginning of our rule definition. Also notice how we've specified the destination. In addition to the any keyword (which matches all IP addresses), the me keyword can be used to match any of the IP addresses configured on the system. As with other firewalls, hosts can be specified one at a time, in CIDR notation, or in an "{a or b}" block like the one just shown. You can also precede any host with a not to negate the match. Ports can be specified individually, as a range, or as a comma-delimited list. To illustrate all of these concepts, let's write a rule that allows inbound access to ports 22 and 443 from all hosts except those on the 192.168.69.0 network.

 ipfw add 500 allow tcp from not 192.168.69.0/24 to {me or 192.168.1.0/24}                    22,443 

We mentioned earlier that rules can be divided into different sets. This is done by specifying a set number after the rule index:

 ipfw add 600 set 2 allow udp from any to any 

The advantage with sets is that they can easily be turned on and off using the ipfw set command. For example, to quickly allow all UDP traffic, we would type this:

 ipfw set enable 2 

When we wanted to close that hole, we would type this:

 ipfw set disable 2 

This ability becomes extremely advantageous when you're dealing with multiple rules that you'd like to be able to turn on and off at will. You can also move rule numbers from one set to another or swap sets. The following commands move rule 600 from set 2 to 3 and then swap set 3 with set 2:

 ipfw set move 600 to 3 ipfw set swap 3 2 

What about statefulness? Placing the check-state rule action at the beginning of the chain forces any dynamic (stateful) rules currently in existence to be checked first.

 ipfw add 1 check-state 

We establish dynamic rules using the keep-state rule option. For example, if we want to let DNS responses to come back through, we'd add a command such as this:

 ipfw add 50 allow udp from 192.168.1.0/24 to any 53 via ed1 keep-state 

The keep-state keyword creates a dynamic rule upon a match. As soon as a machine on 192.168.1.0 makes a DNS request, IPFW will create a dynamic rule that will allow the DNS server to respond. This effectively allows only incoming DNS packets that are part of an already established conversation.

These are the types of rules you will probably use most often; however, we haven't discussed a lot of available rule formats and options. IPFW also allows you to do bandwidth limiting and traffic weighting , but that is beyond the scope of this chapter. Table 13-6 details some of the rule actions used at the beginning of a rule command (such as allow , deny , and reject ), and Table 13-7 details some of the rule options used at the end of a rule command (such as in , via , and keep-state ).

Table 13-6: IPFW Prefix Rules

Rule Action

Description

allow accept pass permit

Allows packets that match this rule.

check-state

Turns on matching for dynamic rules created by keep-state or limit rule actions.

count

Updates the counter for that rule, continues to pass the packet down the chain.

deny drop

Drops packets that match this rule without acknowledgment.

divert <port>

Diverts packets that match this rule to a divert socket on <port> . This is how IPFW handles Network Address Translation by diverting packets to a natd divert socket.

fwd forward <ipaddr>[,port]

Matching packets will be forwarded to the IP address and port specified. Can be used for port forwarding or transparent proxies.

pipe <n>

Used for bandwidth limiting.

queue <n>

Used for bandwidth limiting.

Reset

Matching packets will be dropped and a TCP RST packet will be sent in return.

skipto <n>

Matching packets will jump ahead in the rule list to index n .

tee <port>

Sends a copy of the packet to a divert port. This allows for advanced routing and traffic monitoring.

unreach <code>

Like reject , except you can specify any ICMP unreachable code you wish (see Appendix A for a table of ICMP unreachable codes).

Table 13-7: IPFW Suffix Rules

Rule Option

Description

bridged

Only matches bridged packets.

dst-ip <IP Address>

Only matches if the destination IP address is one of the addresses defined in <IP Address> .

dst-port <ports>

Only matches if the destination port is one of the ports defined in <ports> .

established

Only matches TCP packets with RST or ACK flags set.

frag

Only matches IP fragments not the first fragment.

gid < group >

Only matches packets transmitted or received by a user in a particular Unix group.

icmptypes <types>

Only matches ICMP packets with a type defined in <types> .

in out

Only matches packets that are coming in or out on an interface. Can be used in conjunction with the via option.

ipid <id>

Only matches packets with an IP ID number of <id> .

iplen <len>

Only matches packets with a length of <len> .

ipoptions <options>

Only matches packets with the options defined in <options> set. Can be used to drop nasty loose source routing (lsrr) packets that tools such as Netcat (see Chapter 1) might be able to use to spoof IP addresses.

ipprecedence <prec>

Only matches packets whose IP header has a precedence of <prec> .

ipsec

Matches packets affiliated with some IPsec session, such as packets that have been decapsulated.

iptos <tos>

Only matches packets with a type of service specified in <tos> .

ipttl <ttl>

Only matches packets with a time to live of <ttl> .

ipversion <ver>

Only matches packets with an IP version of <ver> (such as 4 or 6).

keep-state

Matches will tell the firewall to create a dynamic rule to allow return traffic from the destination IP and port for a certain amount of time.

layer2

Matches layer 2 packets.

limit <num>

Only allows <num> number of matching connectionsthen all other matching packets will be dropped. Used with the stateful rules to limit the amount of connections the state machine has to track.

MAC mac <dst> <src>

Only matches packets with the specified <dst> and <src> MAC addresses.

mac-type <mac type>

Matches packets with a specific Ethernet type field.

proto <protocol>

Matches packets with the IPv4 <protocol>.

recv xmit via <if>

Options for matching traffic heading a particular direction on a network interface <if> . The via keyword means either recv or xmit .

setup

Only matches TCP packets with the SYN flag set but no ACK flag.

src-ip <ipaddrs>

Only matches if the source IP address is one of the addresses defined in <ipaddrs> .

src-port <ports>

Only matches if the source port is one of the ports defined in <ports> .

tcpack <ack>

Only matches TCP packets with an acknowledgment number of <ack> .

tcpflags <flags>

Only matches TCP packets with the flags in <flags> set. <flags> is a comma-separated list of flags and can consist of fin , syn , rst , psh , ack , and urg .

tcpseq <seq>

Only matches TCP packets with a sequence number of <seq> .

tcpwin <win>

Only matches TCP packets with a window size of <win> .

tcpoptions <options>

Only matches TCP packets with the options in <options> set, such as maximum segment size (mss) or window advertisement (window).

uid <user>

Only matches packets transmitted or received by a particular Unix user.

verrevpath

Anti-spoofing capability. Make sure the source IP address of the packet matches the IP address range associated with the interface.

Using rc.Firewall As mentioned earlier, the /etc/rc.firewall script that comes with FreeBSD does most of the dirty work for you. All you have to do is define some variables , such as your internal network range, network interfaces, and so on. Then add any other rules you might want, and you're done. Using rc.firewall as a basis is the best way to avoid firewalling problems and caveats.

Before you can use rc.firewall, you have to set up your system startup file (/etc/rc.conf) to use it. The following lines can be added to your rc.conf file to get basic firewall and NAT functionality working:

 firewall_enable="YES"        # Set to YES to enable firewall functionality firewall_type="open"         # Firewall type (see /etc/rc.firewall) firewall_script="/etc/rc.firewall" # Which script to run to set up the firewall firewall_logging="YES" gateway_enable="YES" natd_enable="YES"                # Enable natd (if firewall_enable == YES). natd_interface="ed1"             # Public interface or IPaddress to use. 

The first four lines turn on the firewall, indicate an open firewall (a definition used by the rc.firewall file), set the startup firewall script (rc.firewall), and turn on firewall logging. The last three lines are necessary if your firewall is protecting a multi- homed machine that will be passing traffic between two networks and performing NAT on the external interface. The ed1 interface is the external interface in this example.

Now, we've specified an open firewall type. Let's look into rc.firewall and see what this means:

 case ${firewall_type} in [Oo][Pp][Ee][Nn])         setup_loopback         ${fwcmd} add 65000 pass all from any to any         ;; 

You'll need a little Bourne shell scripting experience to understand exactly what's going on here. Basically, the open firewall type only calls the setup_loopback function (which sets up a few rules to protect the loopback interface from illegitimate traffic) and then adds a rule to allow all traffic from anywhere to anywhere . The ${fwcmd} variable is defined earlier in the script as the path to the IPFW program (usually /sbin/ipfw), so don't let that part of the command confuse you.

Chances are, you'll probably want your firewall to be a bit more secure. The rc.firewall file comes with a few other modes you can choose from: client, simple, and closed. The client mode is meant to protect the system; it is not meant for multi-homed hosts that are protecting networks. For that scenario, you want to use the simple mode. The closed mode will deny everything except loopback trafficand isn't useful to you unless you don't want to use a network at all.

For our purposes, let's use the simple mode. The first thing we have to do is define variables for our internal and external network values, as shown in the file snippet:

 [Ss][Ii][Mm][Pp][Ll][Ee])         ############         # This is a prototype setup for a simple firewall.  Configure this         # machine as a named server and ntp server, and point all the machines         # on the inside at this machine for those services.         ############         # set these to your outside interface network and netmask and ip         oif="ed1"         onet="10.180.192.0"         omask="255.255.255.0"         oip="10.180.192.229"         # set these to your inside interface network and netmask and ip         iif="ed0"         inet="192.168.1.0"         imask="255.255.255.0"         iip="192.168.1.1" 

The variables we have defined tell the script that the firewall's external IP is 10.180.192.229 on ed1, its internal IP is 192.168.1.1 on ed0, and the firewall is protecting a 192.168.1.0/24 network from the 10.180.192.0/24 network. After running the setup_loopback function, the script then executes some general protection rules:

 # Stop spoofing         ${fwcmd} add deny all from ${inet}:${imask} to any in via ${oif}         ${fwcmd} add deny all from ${onet}:${omask} to any in via ${iif}         # Stop RFC1918 nets on the outside interface         ${fwcmd} add deny all from any to 10.0.0.0/8 via ${oif}         ${fwcmd} add deny all from any to 172.16.0.0/12 via ${oif}         ${fwcmd} add deny all from any to 192.168.0.0/16 via ${oif}          # Stop draft-manning-dsua-03.txt (1 May 2000) nets (includes RESERVED-1,          # DHCP auto-configuration, NET-TEST, MULTICAST (class D), and class E)          # on the outside interface          ${fwcmd} add deny all from any to 0.0.0.0/8 via ${oif}          ${fwcmd} add deny all from any to 169.254.0.0/16 via ${oif}          ${fwcmd} add deny all from any to 192.0.2.0/24 via ${oif}          ${fwcmd} add deny all from any to 224.0.0.0/4 via ${oif}          ${fwcmd} add deny all from any to 240.0.0.0/4 via ${oif} 

Can you make sense of the rules? The first two basically say that we shouldn't be seeing traffic from internal addresses coming in to the external interface and the same with external addresses coming in on the internal interface. The next three rules protect us from any reserved private network range traffic (see the "Understanding Network Address Translation (NAT) and Port Forwarding" section near the beginning of the chapter) that has somehow been routed to us. And finally, the remaining rules protect us from any kind of auto-configuration or multicast packets on the external interface.

We've yet to talk about IPFW and NAT. Remember the natd_enable line from rc.conf? That turns on FreeBSD's natd. The natd program listens on a special kind of socket called a divert socket. By default, natd binds the divert socket to port 8668, which is defined as the natd port in /etc/services. By using an IPFW divert rule action, we can force packets to pass through the divert socket to natd. Natd will handle all the NAT details. The divert rule looks like this and is already written into rc.firewall:

 case ${natd_enable} in   [Yy][Ee][Ss])       if [ -n "${natd_interface}" ]; then          ${fwcmd} add divert natd all from any to any via ${natd_interface}       fi       ;;   esac 

The rule says to divert packets to the natd socket for all protocols from anywhere to anywhere on our natd_interface (which should have been defined in rc.conf as our external interface, or ed1). NAT is as simple as that.

The rc.firewall file then adds a few rules that will allow basic communication as well as incoming mail, DNS, and web traffic to the external IP address of the firewall. For our purposes, let's say we're only running a web server that should accessible from the Internet. We can comment the mail and DNS rules out using a # sign.

 # Allow TCP through if setup succeeded         ${fwcmd} add pass tcp from any to any established         # Allow IP fragments to pass through         ${fwcmd} add pass all from any to any frag         # Allow setup of incoming email #        ${fwcmd} add pass tcp from any to ${oip} 25 setup         # Allow access to our DNS #        ${fwcmd} add pass tcp from any to ${oip} 53 setup #        ${fwcmd} add pass udp from any to ${oip} 53 #        ${fwcmd} add pass udp from ${oip} 53 to any         # Allow access to our WWW         ${fwcmd} add pass tcp from any to ${oip} 80 setup 

After that, any initial TCP connections coming in on the external interface are dropped and logged, while anything else will be let through.

 # Reject&Log all setup of incoming connections from the outside         ${fwcmd} add deny log tcp from any to any in via ${oif} setup         # Allow setup of any other TCP connection         ${fwcmd} add pass tcp from any to any setup 

Finally, there are rules for allowing DNS queries through. The keep-state keyword will ensure that dynamic rules get created so only proper DNS responses come back through.

 # Allow DNS queries out in the world         ${fwcmd} add pass udp from ${oip} to any 53 keep-state 

If you want to add any of your own rules, you need to be careful where you do it. For example, adding a line to allow incoming web traffic to an internal web server (192.168.1.50) at the end of this section wouldn't work, because it would get dropped as soon as it hit the Reject&Log rule shown earlier. We would have to put this rule in before that Reject&Log rule.

On the Internet, you can find many customized rc.firewall scripts available for download. You may find one that serves as a better basis or template for your needs. Simply change the firewall_script variable in your rc.conf file to point to your new firewall script.

Network Address Translation and Port Forwarding We've already been over how easy it is to use NAT with IPFW's divert rule action and the natd daemon.

 ipfw add divert natd all from any to any via ed1 

What about port forwarding? In Table 13-6, we mentioned the forward rule action can be used to do either port forwarding or transparent proxy. The following rule would forward port 443 on our firewall's external IP to port 443 on our internal web server 192.168.1.50.

 ipfw add forward 192.168.1.50,443 tcp from any to 10.180.192.229 443          in via ed1 

If you were looking for a rule that would transparently forward outbound web traffic to a local proxy server on port 3128, try the following rule:

 ipfw add forward 127.0.0.1,3128 tcp from any to any 80 out via ed1 

Summarizing IPFW As with the other firewall products we've covered, many more IPFW capabilities ( especially in the area of bandwidth limiting) were not covered here. IPFW's strength is that it can be very easy for the novice to use, but it has such an extensive array of options that it can still be of use to the networking expert. FreeBSD's IPFW framework makes it relatively easy to turn a FreeBSD box into a packet filtering firewall gateway.

Still Others

Other freely available packet-filtering packages haven't been discussed. One particular package that comes to mind is ipfilter , which also comes with the BSD systems and is an alternative to IPFW. Its functionality and capabilities are similar to those that we've already discussed, but we encourage you to check it out at http://coombs.anu.edu.au/~avalon/.

Other supplemental tools can be used to help you implement and augment your firewall capabilities. For example, Firewall Builder (http://www.fwbuilder.org/index.html) is a graphical user interface for Unix variants that can assist you in building firewall rules for iptables, ipfilter, Cisco PIX, and others. Use the GUI to set up your rules, and then generate the appropriate firewall configuration file. Another program, called Guardian (http://www. chaotic .org/guardian/), can allow you to integrate your firewall with an IDS. Guardian works with the freeware IDS Snort (see Chapter 16) so that alerts from snort can automatically trigger "accept" or "deny" rules on your firewall. This allows you to block traffic dynamically from someone who might be port scanning you. Guardian supports ipchains, iptables, ipfw, ipfilter, Checkpoint Firewall-1, and Cisco PIX.

Our goal in this chapter was not to cover in detail every firewall product available, but instead to give you a solid background and knowledge of firewall concepts. If you know the concepts, it's usually not too difficult to apply those concepts to a new firewall package; it's usually just a matter of learning the syntax. That being said, we still feel we should briefly cover a few of the more popular commercial firewall products before moving on.



Anti-Hacker Tool Kit
Anti-Hacker Tool Kit, Third Edition
ISBN: 0072262877
EAN: 2147483647
Year: 2006
Pages: 175

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net