The Mason HOWTO: Advanced scenarios

## 8. Advanced scenarios

## 8.1 General approach

Once you've gone through the Quick Start, what now? Now we learn how to use this to match your security policy.

The first lesson to learn about packet filtering rules is that they are only useful if you have a mix of accept and deny (equivalent to reject in this discussion) rules. Think about it. If all of your rules are allow rules and your default policy is also allow, this setup is no different from having no rules at all; the system is completely open.

At the other end of the spectrum, if all of your rules are deny and the default policy is also deny, well, it's going to be pretty hard to use TCP/IP at all. :-)

This means that putting a firewall together involves deciding what should be allowed _and_ what should not be allowed.

The first thing for you to decide is what your default policy should be. In the next few minutes we'll be looking at what you specifically want to allow and what you specifically want to disallow. What should the firewall do with the rest of the packets? That depends on how you view your firewall.

If you primarily want your firewall to block a relatively small amount of malicious things, but want users on both sides of the firewall to have relatively unencumbered access to the opposite side, you'd probably want to use a default policy of accept. This tends to be a good choice in the case where there are a large number of types of TCP/IP traffic that should be allowed to pass through the firewall.

If, on the other hand, you tend more toward the paranoid and want very fine grained control over _exactly_ what passes through your firewall, you'll probably want to use a default policy of deny. This tends to work well when there are a relatively small number of protocols that should be allowed.

Choosing a policy becomes difficult when you want fine grained control but there are a large number of protocols used by your users. You'll still choose a default policy of deny, but you'll have to create a large number of rules to accomodate them. Good thing you've got Mason to give you a hand!

Now that you've chosen a policy, what goes next? Here's where you can become an artist.

With the help of Mason, your job is to decide what should be allowed and what should not be allowed.

[More to be added as time allows...]

## 8.2 Ordering rules

Here are a couple of guidelines about how to order your rules. I refer to policy below; for this discussion, there are 6 possible policies: accept, deny, reject, accept and log, deny and log, and reject and log.

As there is no way that input rules and output rules could ever overlap, the rulesets for those can be considered seperately. The same logic holds true for input and forwarding and output and forwarding. Effectvely, even though you might have them all mixed together in your firewall creation shell script, you can work with the input rules according to the principles below, then come back and work with the forwarding rules, and then come back one last time for the output rules.

- I suggest placing dns (also called domain; port 53/tcp and 53/udp) rules at the top of your firewall if you're using the default mode of HOSTLOOKUP=FULL. The other rules in your firewall may require dns lookups; if those requests can't get through because the dns rules aren't in place yet, the early rules may not get put in place.
- If your ruleset contains a block of 2 or more rules with the same policy (accept, deny, or reject) that immediately follow each other, the order of the rules in that block has no functional difference to the operation of the firewall. If you are very concerned about performance, you might want to put the rules that process the largest number of packets at the top of this block and the rules that process the least number of packets near the bottom of this block. See the SORTMODE option in /etc/masonrc (not available in iptables).
- If two consecutive rules do not have any overlapping cases in the patterns they match, they can appear in either order without affecting the operation of the firewall. As long as no two rules in the set overlap, this can be extended to a set with more than two rules.
- If two rules overlap in the patterns they match and have different policies, they _cannot_ be reordered without affecting the functional operation of the firewall. Specifically, the packets in the overlapping case will have their policy changed.
- If two consecutive rules have the same policy and one is subset of the other, the more specific rule can be discarded and the more general rule can be kept without affecting the functional operation of the firewall. One common case of this is when your default policy is, say, accept, and the last rule just before the default policy rule also has a policy of accept. This more specific rule (not the policy, of course) can be discarded.
- Your default policy always comes at the end.

I've referred to discarding rules above. One reason why you might _not_ want to discard a particular rule rule is when you're using your firewall to do accounting as well as blocking. You might want to be able to have seperate accounting for the packet traffic in the rule that would have been discarded.

## 8.3 Tips and tricks

The following are tools and techniques I use. They may not be appropriate for you. Please consider whether they are appropriate for you before using them.

- If you want to see which rules in your running firewall are actually carrying traffic, try this:

      ( ipfwadm -lenI ; ipfwadm -lenF ; ipfwadm -lenO ) | grep -v '^ *0 *0 ' | less -S

  or

      ipchains -L -n -x -v | grep -v '^ *0 *0 ' | less -S

  or

      iptables -L -n -x -v | grep -v '^ *0 *0 ' | less -S

  The "grep -v ..." removes all packets with 0's in the count and bytes columns. If the number of rules returned is still too large, flush the firewall and restart it; this clears out all the packet counts. Then you can rerun whatever test you've been doing and run the above command again to see what rules are carrying your traffic. This is especialy useful if you've got a deny rule somewhere blocking a certain connection:

      ( ipfwadm -lenI ; ipfwadm -lenF ; ipfwadm -lenO ) | grep -v '^ *0 *0 ' | less -S

  or

      ipchains -L -n -x -v | grep -v '^ *0 *0 ' | egrep '(Chain|target|DENY|REJECT)' | less -S

- If you don't want to go through the above process, but just want to convert a few log entries to rules, you can do the feed yourself. For example:

      tail --lines=1000 /var/log/messages | grep 'kernel.*I=' | DOCOMMAND="none" mason >afewrules

  Any other options can be placed on the command line or in /etc/masonrc.
- If you want rules that will run under ipfwadm and ipchains kernels, you have two good choices. Create ipfwadm rules no matter what kind of kernel you have (put ECHOCOMMAND="ipchains" in /etc/masonrc or on the command line). The first choice is to use the ipfwadm-wrapper (part of the ipchains-scripts package) as a front end to either ipfwadm or ipchains, as appropriate. The second choice is to take all of the ipfwadm rules and create the following file as your real firewall:

      if [ -f /proc/net/ip_fwchains ]; then
              #Convert your ipfwadm rules to ipchains rules and place the converted rules here.
              /sbin/ipchains...
      elif [ -f /proc/net/ip_input ]; then
              #Place your ipfwadm rules here:
              /sbin/ipfwadm....
      fi

  The above conversion is actually darn simple:

      cat ipfwadmfile | ipfwadm2ipchains >ipchainsfile

  The ipfwadm2ipchains script is available at http://www.stearns.org/i2i/ . This site also holds ipchains2iptables, a similar script that gives a first pass output in iptables format from a given ipchains firewall. Note that this output won't use any of the advanced features of iptables, but you can add these.
- If you have a number of interfaces that all get the same rules, replace the if0, if1, if2, etc rules with if+ . I believe this is ipchains only.
- (Diald users only). The packets leaving your system on sl+ (or tap+) may have different source addresses (0.0.0.0/32, some dummy ip address, an old ppp address...). You might want to replace them with 0/0 to say I don't care what the source address is.
- To see what program is using a particular port, try:

      ps axf | grep "^ *`fuser port_number/proto | awk '{print $2}'` "