Using a Firewall


It's undeniable that firewalls (machines that operate as routers with filters) are almost indispensable to Internet server maintenance. Bored "script kiddies" with nothing better to do than to try to break into systems with easily accessible hacking tools make it imperative that you protect your system. Most administrators need protection that goes beyond simply electing not to run certain services and keeping on top of security bulletins. You need a generalized shield at the kernel level that prevents your system from being accessed at all on certain ports, from certain hosts, or over certain protocols. Firewalls, particularly the IPFW firewall that comes with FreeBSD, provide an answer to this need.

A firewall can prevent the vast majority of casual attacks by only allowing traffic that you designate as valid to enter your system. Even the most expensive and robust firewall, however, can be made useless through a simple misconfiguration. Most ineffective firewalls are made that way through misconfigurations rather than poor quality or design.

Caution

There is no substitute for a properly designed and well-maintained security policy used in conjunction with a competent firewall; don't be fooled into thinking that if you just buy a more expensive firewall, your network security problems are solved. That's the type of thinking that leads to a great many security breaches on the Internet today.


A firewall enables you to configure your system to filter packets based on the criteria you specify, discarding unwanted traffic at the kernel level (before it reaches any critical system services). Firewalls also help you with administrative accounting, keeping statistics on the usage of your system and seeing how much traffic comes from where.

IPFW does both of these things; you can run it directly on your FreeBSD machine, or you can use it on a system acting as a gateway router protecting multiple hosts on the inside LAN. Figure 30.1 shows this latter case, with a FreeBSD machine with three Ethernet cards acting as a gateway router (as you saw in Chapter 28, "Configuring an Internet Gateway"), passing packets between the inside (LAN), "demilitarized zone" (DMZ), and outside (WAN) networks (you learned about gateway routers in Chapter 28).

Figure 30.1. A diagram of a gateway router providing firewall services, showing the LAN, DMZ, and WAN interfaces.


Note

The "demilitarized zone," or DMZ, is a network that is exposed to the WAN traffic directly, rather than being on the LAN. A DMZ is particularly useful in cases where the IP addresses on the LAN are translated (as you learned in "IP Addresses," in Chapter 22). A DMZ provides an enterprise or ISP with a network on which to place untranslated "edge" machines such as web servers, mail gateways, and other hosts that need to be accessible from the general Internet.

A DMZ may or may not be configured to be protected by the firewall rules in the gateway router. Usually this is desirable, but some specialized cases require that the DMZ be exempt from the LAN's firewall rules. Your network situation will dictate your needs.


Enabling the Firewall

IPFW is not supported in the GENERIC kernel. You can compile certain options into a custom kernel to enable IPFW, including IPFIREWALL, IPFIREWALL_VERBOSE, and IPFIREWALL_VERBOSE_LIMIT=10. You don't need to build a new kernel, however, in order to use IPFW; it's available as a kernel module, which is loaded automatically by the /etc/rc.network script. To enable the firewall without rebuilding the kernel, add the following lines to /etc/rc.conf:

firewall_enable="YES" firewall_type="open"


The second line is optional, and not recommended for highly secure networks. If you don't specify that the firewall type should be open, the only rule that IPFW will start with is the default one, with an index of 65535 (the maximum), specifying deny ip from any to any. In other words, if you reboot with IPFW in its default configuration, your machine will be completely blocked off from the network, and you'll have to have physical console access to it in order to get it back. For maximum security, it's best to leave the firewall in this configuration, and then add specific rules to allow traffic from certain hosts and on certain ports.

Caution

It's dangerous to experiment with IPFW if you don't have console access, because it's very easy to put your machine into an unreachable state. Until you are comfortable enough with IPFW to know exactly what you're doing, always make sure you can access the machine via the console in case something goes wrong.

If you do end up blocking your machine from the network through experimentation with IPFW, the only way to recover is to go to where the machine is physically located and log in from the console. From there, you can disable IPFW by removing the lines in /etc/rc.conf, or you can configure it properly and reboot.

One trick to prevent falling into this trap is to set up a cron job to turn off the firewall every five minutes (/etc/rc.d/ipfw stop); enable this automated command as a "safety net" whenever you experiment with the firewall. That way, if you end up locking yourself out, you just need to wait five minutes and the system should become available again.


The open setting changes the default rules so that IP traffic is passed (allowed) by default, rather than blocked. Blocking traffic by default creates a truly secure system, but it can be excessively restrictive for systems that exist within a secure environment. At the same time, allowing traffic by default (blocking only specified IP traffic) eliminates the possibility of having complete system security. Use the open setting if your system is in a network that's already behind a firewall; you probably don't need to apply the same kind of protection twice.

After your /etc/rc.conf is set up properly, reboot. Alternatively, you can issue the /etc/rc.d/ipfw start command from the physical console (not from a remote terminal, which is very dangerous because it can cause your machine to lose network connectivity and become inaccessible). You will know the firewall has been enabled properly if you see the following lines:

Kernel firewall module loaded Flushed all rules. 00100 allow ip from any to any via lo0 00200 deny ip from any to 127.0.0.0/8 00300 deny ip from 127.0.0.0/8 to any 65000 allow ip from any to any Firewall rules loaded, starting divert daemons:.


You can also use kldstat to check whether the IPFW module has been loaded automatically:

# kldstat Id Refs Address    Size   Name  1    3 0xc0100000 355be4 kernel  2    1 0xc0eee000 6000   ipfw.ko  3    1 0xc0f19000 12000  linux.ko


You now have full access to the ipfw command, which lets you set rules on what kinds of traffic to allow and view the accounting information accumulated by IPFW.

Designing IPFW Rules

The ipfw command is used to either add or delete rules from the kernel filter and accounting system. The rules are constructed in a syntax that flows somewhat like natural English; it's made up of an action (such as deny), a protocol to which the action applies (such as tcp), and an address specification involving a from clause and a to clause. A rule such as deny tcp from badhost.com to any, for example, blocks TCP traffic from a host called badhost.com. You would add this rule to the kernel firewall like this:

# ipfw add deny tcp from badhost.com to any


A number of variations on this theme are possible. You can specify an address based on a network mask either with a mask pattern (for example, 255.255.255.0) or with a CIDR bit-mask (for example, /24). You can also block individual ports rather than an entire system; this technique prevents hosts within a large ISP with unpredictable IP addresses from targeting a single service on your machine. Such a rule might look like this:

# ipfw add deny all from evil.isp.com/16 to www.example.com 80


Similarly, you can exempt hosts from earlier rules by adding allow rules as exceptions, like so:

# ipfw add allow all from goodhost.evil.isp.com to www.example.com 80


More usefully, you can block or allow traffic from any external host based on the TCP or UDP port it uses. For example, you might choose to allow only web and email traffic to reach the server, using TCP ports 80 and 25 respectively:

# ipfw add deny tcp from any to www.example.com # ipfw add allow tcp from any to www.example.com 80 # ipfw add allow tcp from any to www.example.com 25


Note that IPFW rules are entered in a "chain," in which each rule is evaluated in the order it was specified. Each rule has an index number, normally spaced by 100 from its neighbors, which you can control by specifying the index number after the add or deny keyword in an ipfw command; this is how you can indicate the execution order of your rules. View the existing rule set with ipfw -a list:

# ipfw -a list 00100    0      0 allow ip from any to any via lo0 00200    0      0 deny ip from any to 127.0.0.0/8 00300    0      0 deny ip from 127.0.0.0/8 to any 00400    0      0 deny tcp from badhost.com to any 00500    0      0 ipfw add deny all from evil.isp.com/16 to www.example.com 80 00600    0      0 ipfw add allow all from goodhost.evil.isp.com to www.example.com 80 65000 1214 79688 allow ip from any to any 65535    1    40 deny ip from any to any


The index number is shown in the first column; the number 65535 rule, as you saw earlier, is the default deny rule that rejects anything that falls through from above. The open setting puts an allow bucket above the deny rule; however, the allow rule has a high index number to help ensure that it comes after any other rules that you might add through regular usage.

The second and third columns show usage statistics, displaying the total number of packets and bytes that have matched each rule, respectively. This is how you can tell whether your rules are being effective.

Troubleshooting IPFW

You might find that what you think is a very straightforward configuration results in completely unpredictable results. For instance, you might have added a deny rule for all hosts and an allow rule for your own remote machine's IP address, but you find you still can't access the FreeBSD machine.

Always remember that IPFW rules are specified and applied in subsequent order. A rule that comes later in the list supersedes a rule specified earlier in the list; a packet is compared against each rule in the order specified by the index number. In most cases (although it depends to a certain extent on the action taken and the system settings), the packet continues to be checked against further rules that might match in a more specific manner; this is how "exception" rules work. However, the "default" rule, with index 65536, only matches packets that match no other rules.

Make sure your index numbers apply the rules in increasing order of specificity. To make configuration easier, consider using a firewall configuration file, as we'll discuss shortly.


You can specify a number of different firewall types in /etc/rc.conf. Each keyword has a different meaning, as shown in Table 30.2. The exact definitions of these profiles can be deciphered from the shell script code in /etc/rc.firewall.

Table 30.2. Available Firewall Types

Keyword

Meaning

open

Allows access to all, from all

closed

Disables all IPs except on the loopback (lo0) interface

client

Sets up rules designed to protect just this machine

simple

Sets up rules designed to protect the whole network

UNKNOWN

The default; loads no rules except for the default deny rule at index 65535

filename

Loads rules from filename


For your purpose, if your setup is uncomplicated, a "canned" IPFW profile such as client or simple might be appropriate. However, you're likely to need a specialized configuration as your system continues to evolve.

Using a Firewall Configuration File

Because firewall rules are not persistent (they are flushed with each reboot), you will want to maintain your firewall with a configuration file if you have customized firewall settings. This also has the benefit of being easier to maintain and faster to troubleshoot than working with IPFW from the command line.

Put your specialized rule set into a file of your choice; for this example, call it /etc/firewall.conf. List your desired rules in that file, omitting the ipfw command itself:

add deny tcp from badhost.com to any add deny all from evil.isp.com/16 to www.example.com 80 add allow all from goodhost.evil.isp.com to www.example.com 80 add 65000 allow all from any to any


Now, change the firewall_type in your /etc/rc.conf file:

firewall_type="/etc/firewall.conf"


The next time you reboot or run /etc/netstart or /etc/rc.d/ipfw start, the rules from /etc/firewall.conf will be loaded with indexes of 100, 200, 300, and so on. An allow all rule at index 65000 provides a default behavior of passing traffic rather than denying it, which is desirable in most cases (unless you only want specified hosts to be able to access your machine).

For further reading on IPFW, see the man ipfw page and the online FreeBSD Handbook at http://www.freebsd.org/handbook.




FreeBSD 6 Unleashed
FreeBSD 6 Unleashed
ISBN: 0672328755
EAN: 2147483647
Year: 2006
Pages: 355
Authors: Brian Tiemann

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