Chaining up networks with Linux - La page d'accueil du P:L:O:U:G

installing and configuring ipchains, an open-source and free Linux firewall package that can handle speeds up to a ..... The source (-s) and destination (-d) have the same format. ..... "Securing Linux, Part 1," in LinuxWorld magazine, May 1999.
454KB taille 2 téléchargements 232 vues
developerWorks : Linux : Library - Papers

http://www-4.ibm.com/software/developer/library/linux-firewall/index.html

Search IBM : developerWorks : Linux overview : Library - papers

Chaining up networks with Linux Using your old Pentiums and Linux to create a Firewall Rawn Shah Independent technologist and freelance journalist September 1999 Hey, you with that old Pentium machine! Don't toss it away because it looks underpowered compared to all the fancy Contents: new hardware. It can have a second life as a firewall for your small business or home office. Here's the step-by-step on Ipchains & firewalling installing and configuring ipchains, an open-source and free Linux firewall package that can handle speeds up to a T-1 Setting up the firewall connection on an old Pentium. Rather than spending several thousand dollars on a custom product from a firewall Configuring the vendor, get the real deal at the best price of all: free and reliable. Contrary to popular belief, old Pentium computers are not just good for doorstops and footrests. They can even be used for...(drum roll)...computing! In fact, a small machine with 32 MB of RAM and a 200 MB - 400 MB disk drive is all you need to set up a firewall for your small-office network. By installing a compact version of Linux with only the important system applications, no graphical user interface, and no user applications, you can create the perfect footprint to turn your old machine into a firewall.

firewall Example configurations Application protocols Resources About the author

The little wonder that accomplishes this is an open-source package called ipchains, from Paul "Rusty" Russell. The program provides many of the same features as a commercial firewall product: It allows you to define policies on where network traffic can go and who is allowed in and out. It replaces the earlier firewalling software ipfwadm (IP Firewall Administration) available for Linux kernel 2.0.x and below. Ipchains currently works with all 2.1.x and 2.2.x versions of Linux and will be replaced with an evolved form of itself known as "netfilter" for verion 2.3.x and above. The reason for these changes in the major Linux version is that packet filtering is built into the kernel itself and thus has to follow the major kernel modifications. This article discusses what ipchains is, what it can do, and how you can implement it for different scenarios.

Ipchains and firewalling Ipchains is essentially a packet filter. It looks at IP packets coming over a network interface, and based upon a defined ruleset, modifies the packet in some way and sends it out over an interface. Every IP packet has a header that contains information defining where the packet is to go, and how its supposed to be processed (see the next figure). The data to be carried by this IP packet is contained in the payload or body of the packet. Often this payload contains another higher-level packet inside. For example, a TCP packet is actually contained within the payload of the IP packet, and has its own header and payload. The software can change the values within a number of the fields shown in the IP header, TCP header, UDP header (not shown), and ICMP header (not shown), as we will see soon.

The name ipchains comes from the nature of this filtering product. It creates logical filtering steps that each process a packet according to a

1 of 10

1/13/00 10:22 AM

developerWorks : Linux : Library - Papers

http://www-4.ibm.com/software/developer/library/linux-firewall/index.html

user-defined rule. These steps are then "chained" together to create the entire set of rules for packet processing. The chains can be associated with individual IP addresses, or the networks of addresses. There can be any number of chains on a system to process every incoming IP packet as shown:

A machine running ipchains can have a number of network interfaces and each interface can connect to a different network. At minimum, any reasonable firewall should have two separate interfaces: one to connect to the internal network and another to the external. The packets come in through one interface, pass through the chain of filters, and go out the other interface. In the simplest form, ipchains processes three types of rules: accept, deny, and reject. The first accepts any packets coming from an indicated IP address or network source. The deny rule discards any packets that it gets from a particular source. The reject rule discards the packet and informs the source that the attempted connection has been refused. There are three primary categories for chains: the input chain, the forward chain, and the output chain. The input and output chains handle the processing rules for incoming and outgoing packets to an interface, respectively. The forward chain is responsible for directly sending traffic (after it has been processed through the input chain) to another machine. This other machine in most cases is a router. Ipchains itself isn't intended to be a full-scale routing engine, and thus can pass off packets to a real software router on the same machine or a hardware router on another node. The overall engine for ipchains is presented in the flowchart below:

2 of 10

1/13/00 10:22 AM

developerWorks : Linux : Library - Papers

3 of 10

http://www-4.ibm.com/software/developer/library/linux-firewall/index.html

1/13/00 10:22 AM

developerWorks : Linux : Library - Papers

http://www-4.ibm.com/software/developer/library/linux-firewall/index.html

A firewall is a common name for the type of device that can manipulate incoming traffic and select which traffic is allowed to go out. In doing this it may change the state of the incoming or outgoing traffic to hide the identity of machines or prevent unauthorized access. Ipchains runs on the system in one of two ways: as a proxy service or as a network address translator. The former takes traffic from any machine on the network behind the firewall and applies user-defined rules to it before choosing to send it to the outside world. The proxy controls which internal machines are allowed out and vice versa. A network address translator (NAT) or IP Masquerader (Masqing) is used when you do not have enough addresses or do not want to use public Internet addresses for your internal network. It translates the internal private address into an assigned public address and can multiplex many internal addresses to one external one. At the same time it provides security for the internal network because outsiders cannot directly access those machines.

Setting up the firewall Setting up a Linux machine to become a firewall isn't trivial. To be careful, you should always do a fresh install of a stable -- in other words, not the latest and greatest -- version of Linux (try version 2.2.12), rather than convert an existing Linux machine. During the installation, make sure you install only the necessary system applications for running a bare-bones machines. For example, don't install Web servers, NFS servers, or compilers on the machine unless you have no other choice, or unless it is required as part of another firewall service you plan to run. You shouldn't even have Telnet services running on the machine. If you have to log into the machine over the network, install the Secure Shell (ssh) remote login system instead. A firewall should never be tasked with any job other than handling packet and network security. Ipchains may come with the distribution of Linux you use. If you're paranoid, you shouldn't use the default version that comes with the distribution unless you know the distribution has been certified by a major Linux vendor. The first thing you need to do is figure out if firewalling is already on your machine. Check the directories /etc/rc.d/init.d for any startup/shutdown scripts named packetfilter, ipchains, ipfwadm, firewall, or proxy. If such a file exists and there is a symbolic link to it from /etc/rc.d/rc2.d or /etc/rc.d/rc3.d, then you probably already have a firewall installed on your system. It is possibly even running right now without any specific rules established. To confirm, type the following command: # cat /proc/sys/net/ipv4/ip_forward If it does not recognize the file, then you don't have a firewall installed. If you get the value 0, then it is installed but not running. A a value of 1 indicates it is running. You can download the source code for ipchains and compile it yourself as well. When you download the file, make sure it is the authentic version by running a checksum against the downloaded file (usually with the command md5sum ). The ipchains Web site also lists the proper values of checksum; your value should match exactly. The current version of ipchains is 1.3.9. If the values don't match, you have to make sure that your kernel is compiled with Masquerading turned on. By default Linux is now compiled with these options turned on, but if you decide to compile the kernel yourself (not for the weak-hearted), you have to say "YES" to the following options under Linux 2.2.x, during the build: CONFIG_EXPERIMENTAL CONFIG_MODULES CONFIG_NET CONFIG_FIREWALL CONFIG_INET CONFIG_IP_FORWARD CONFIG_IP_MASQUERADE CONFIG_IP_MASQUERADE_IPPORTFW CONFIG_IP_MASQUERADE_IPAUTOFW CONFIG_IP_MASQUERADE_ICMP CONFIG_IP_ALWAYS_DEFRAG CONFIG_DUMMY CONFIG_IP_MASQUERADE_MFW Once you have the kernel built, you need to install the firewall as a system service that will be launched during system initialization time. System services are run by the system init process during startup, and different services are run depending on the init level of the system. Init level 0 is when the system is totally brought down and ready for power to be turned off. Init level 1 is single-user mode without any network activity. Init levels 2 and 3 are commonly used to run multi-user mode with network activity, and the state in which most machines run. There are other init levels as well, but they aren't used as often. To create a startup script for the service and install it for levels 2 and 3, first create the system startup/shutdown script for ipchains in a text file as shown below. Save this to the directory /etc/rc.d/init.d or /etc/init.d (depending on your version of Linux).

4 of 10

1/13/00 10:22 AM

developerWorks : Linux : Library - Papers

http://www-4.ibm.com/software/developer/library/linux-firewall/index.html

#!/bin/sh # Firewalling with ipchains, startup/shutdown script PATH=/sbin:/bin:/usr/sbin:/usr/bin [ -f /etc/packetfiler.rules ] || exit 0 case "$1" in start) echo -n "Starting ipchains firewall:" /sbin/depmod -a # Comment the following line if you do not intend to support # using FTP through the firewall /sbin/modprobe ip_masq_ftp # Insert lines to support other application protocols here /sbin/ipchains-restore < /etc/firewall.rules || exit 1 echo "1" > /proc/sys/net/ipv4/ip_forward # If you do NOT use PPP, SLIP or DHCP for any of your network # interfaces on this machine, comment the following line echo "1" > /proc/sys/net/ipv4/ip_dynaddr echo "." ;; stop) echo -n "Shutting down ipchains firewall:" echo "0" > /proc/sys/net/ipv4/ip_forward # Comment the following line if you do NOT use PPP, SLIP or DHCP echo "0" > /proc/sys/net/ipv4/ip_dynaddr /sbin/ipchains /sbin/ipchains /sbin/ipchains /sbin/ipchains /sbin/ipchains echo "." ;;

-X -F -P input ACCEPT -P output ACCEPT -P forward ACCEPT

*) echo "Usage: /etc/rc.d/init.d/packetfilter {start|stop}" exit 1 ;; esac exit 0

You then have to make symbolic links to run packet filtering from the different init levels. You want to make sure the packet filter is running in init levels 2 and 3 when the network is operational. # ln -s /etc/rc.d/init.d/packetfilter /etc/rc.d/rc2.d/S09packetfilter # ln -s /etc/rc.d/init.d/packetfilter /etc/rc.d/rc3.d/S09packetfilter The above two commands make a symbolic link to the script file to start the packet filter before the network on Red Hat Linux. You should always start the packet filter first before network services are operational on your system. A network service can have a name SXXnetwork, where XX is a number indicating the order in which it is to be started. Pick a number for XX that is lower than, but does not conflict with, the numbers on other startup scripts listed. In the above example, the network startup script on this system was S10network. Similarly, you should create symbolic links to shut down the packet filter when network services are shut down. The packet filter should be shut down after the network interfaces are brought down (in the script K90network, in this example). Thus the packet filter script is linked as K91packetfilter. # ln -s /etc/rc.d/init.d/packetfilter /etc/rc.d/rc0.d/K91packetfilter

5 of 10

1/13/00 10:22 AM

developerWorks : Linux : Library - Papers

http://www-4.ibm.com/software/developer/library/linux-firewall/index.html

# ln -s /etc/rc.d/init.d/packetfilter /etc/rc.d/rc1.d/K91packetfilter Finally, on Red Hat systems you want to make sure the following entry appears in the file /etc/sysconfig/network: FORWARD_IPV4="yes" Once you reboot the machine, the packet filter will be running. You don't have any filtering rulesets defined yet, but that comes next.

Configuring the firewall If you use a firewall, you should use a block of addresses that are not valid on the public Internet, and use an NAT. This way, the major routers on the backbones will discard those private addressed packets as illegal. These blocks of addresses have been defined in the Internet document RFC 1918 and are listed in Table 1. There are three sets of address blocks to choose from. For most companies the 192.168.0.0 block is sufficient, and we'll use this block for the rest of our examples. Table 1: Internet-assigned addresses for private networks Start Address

End Address

CIDR Block prefix

# of separate addresses

10.0.0.0

10.255.255.255

10.0.0.0/8

~ 16 million

172.16.0.0

172.31.255.255

172.16.0.0/12

~ 4 million

192.168.0.0

192.168.255.255

192.168.0.0/16

~ 65,000

All your machines in the internal network should be numbered from this block; for example, 192.168.1.22. The internal interface on the firewall should be 192.168.0.1, the very first address, just as a common practice. The numbers .0.0, .0, .255, and .255.255 are reserved for system use, so do not assign them to any machine. The rest of the addresses can be assigned according to your preference. The example in the next figure shows eight computers, four desktops, and four servers. The desktop with the hostname stranger is not allowed to access the firewalled network, but the desktop familiar is allowed in. One server, Freedom, is within the company network but not behind a firewall, as is common for a public access Web site. The addresses for the machines are only examples, but they delineate the different network address groups (192.168.x.x for firewall-internal, 216.19.15.x for company-internal but firewall-external, and 198.102.x.x for Internet-public addresses).

Table 2: Commands for manipulating chains

6 of 10

1/13/00 10:22 AM

developerWorks : Linux : Library - Papers

http://www-4.ibm.com/software/developer/library/linux-firewall/index.html

Command

Description

ipchains -N

Create a new chain with the given name

ipchains -X

Delete and existing chain of the given name

ipchains -L

List all the rules assigned to the named chain

ipchains -F

Clear this named chain of all rules, but do not delete the chain

ipchains -Z

Clear all the statistics associated with this named chain

ipchains -P

Set the overall policy (ACCEPT, DENY, REJECT, MASQ, REDIRECT, RETURN) of this chain

ipchains -M -L

List all chains that use masquerading

ipchains -M -S

Assign several timeout values for different protocols, for all chains that use masquerading

Table 3: Commands for defining rules in chains Command

Description

ipchains -A

Append this rule to the named chain

ipchains -D

Delete the specified rule by its position in the named chain

ipchains -R

Replace the specified rule by its position in the named chain, with this new rule

ipchains -I

Insert a new rule into the specified position in the named chain

ipchains -C

Run the packet specified in protocol-info through the rules in the named chain to test it

The rules that go into the commands listed in Table 3 are created by specifying the source or destination address, the protocol type and associated port number, other IP protocol flags, and the policy to apply to them. Each of these rule components can be listed one after the other and can vaguely or precisely describe the type of packets to filter. The source (-s) and destination (-d) have the same format. You can specify either a single host address or a group of hosts from a network. For the former, you simply insert the host address. For the latter, you need to specify a network address and a netmask or a bitmask for all hosts in the group. A bitmask is the same as the netmask, but instead of indicating four decimal values, you simply count the bits starting from the left. For example, the netmask 255.255.255.0 is the same as the bitmask 24, and 255.255.224.0 is the same as the bitmask 19. Unfortunately, you cannot specify an arbitrary range of addresses for the network -- such as all machines from 192.168.1.1 through 192.168.1.133 -- because you cannot fit this into an appropriate netmask. The software works this way because it is difficult to make the system filter packets efficiently when using an arbitrary range. Rule

Description

-d 192.168.1.24 -j ACCEPT

Accept all packets going to the destination 192.16.1.24 (Jane)

-d 192.168.0.0/255.255.224.0 -j DENY

Refuse all packets attempting to go to the destination network including all addresses from 192.168.1.0 through 192.168.31.255. This closes off the hosts Bob, Fred and Jane, but not Olivia.

-d 192.168.0.0/19 -j DENY

Same as previous line but uses a bitmask to indicate the value.

The above example shows destination address specifics (with the -d), but is identical for source addresses (with -s, instead). The next rule component is the protocol type. Ipchains understands the three common IP transport protocol types TCP, UDP and ICMP. All the other protocols are experimental use only, so we needn't bother with them.

7 of 10

1/13/00 10:22 AM

developerWorks : Linux : Library - Papers

http://www-4.ibm.com/software/developer/library/linux-firewall/index.html

-p TCP -s 192.168.1.24 -j ACCEPT

Accept any TCP packets coming from Jane (192.168.1.24)

-p TCP -d 192.168.0.0/19 -j DENY

Deny all TCP packets going to Bob, Fred and Jane

-p TCP -d 192.168.1.24 80 -j ACCEPT

Accept all TCP packets going to port 80 on Jane

-p TCP -d 192.168.1.24 www -j ACCEPT

Same as previous line but uses the port name www rather than the number 80, to indicate the default Web server port. These named ports are defined in /etc/services

-p TCP -d 192.168.1.24 0:1024 -j DENY

Deny all TCP packets going to the range of ports from 0 to 1024 on Jane. This range of ports happen to be used commonly by server applications run by the system

-p TCP -d 192.168.1.24 www -j ACCEPT

Accept any TCP packets going to server Jane on the port named www (by default, port 80).

-p TCP -d 192.168.1.24 ! www -j DENY

Deny all TCP packets going to any port on Jane other than the www port (by default, port 80). The exclamation point here indicates inversion of the value, or in this case any value other than that associated with www.

-p TCP -d ! 192.168.1.24 www -j DENY

Deny all TCP packets going to any machine other than Jane, on port www. This is NOT the same as the previous line

-p TCP -d ! 192.168.1.24 ! www -j DENY

Deny all TCP packets going to any machine other than Jane, and going to any port other than www. In other words, do not deny any TCP packets going to Jane on port 80. Do not use this rule method, it gets confusing.

-p ! TCP -d 192.168.1.24 -j DENY

Deny any packet other than a TCP one going to Jane.

The method works similarly for the UDP protocol. The ICMP protocol, used by the ping and traceroute command, requires specific port numbers. -p ICMP -d 192.168.1.24 0 -j ACCEPT -p ICMP -d 192.168.1.24 8 -j ACCEPT

Accept pings to the server Jane. Both these rules (ICMP port 0 and 8) have to be applied, in separate statements, for ping to work correctly

-p ICMP -d 192.168.1.24 3 -j ACCEPT

Accept the ICMP destination unreachable message, if sent from the remote machine that a user on Jane is trying to access. This should normally be allowed if you intend to connect outside from that machine or your telnet or other remote connection program will hang.

-p ICMP -d 192.168.1.24 11 -j DENY

Deny packets from a traceroute command executed from outside the firewall network.

Aside from address and protocol information, you can also specify the network interface driver that the packet is coming through. This may be an easier way to think about the direction the traffic is coming from, or it can be useful to indicate the specific network interface to which you meant the rule to apply. -i eth0 -s 192.168.1.24 -j ACCEPT

Accept all packets coming from Jane on the first Ethernet interface (eth0)

-i eth+ -s 192.168.1.24 -j ACCEPT

Accept all packets coming from Jane on any Ethernet interface (eth+)

-i ppp0 -p TCP -s 198.102.68.2 1025:65535 -j ACCEPT

Accept all TCP packets coming from the host familiar (198.102.68.2), from any port number between 1025 and 65535, over the PPP interface.

Two special rule components specify the TCP_SYN flag (-y) and the fragmented packet (-f). The flag TCP_SYN is set when a TCP client first tries to connect to a remote TCP server. Unfortunately, crackers have used this as a form of attack to disable a remote system by flooding the remote server with TCP_SYN messages but not following through properly with a connection. This locks up server processes until no more are left, slowing down or effectively freezing the server machine. By specifying this component with the -p TCP component, you can prevent TCP_SYN attacks from specific machines.

8 of 10

1/13/00 10:22 AM

developerWorks : Linux : Library - Papers

http://www-4.ibm.com/software/developer/library/linux-firewall/index.html

The fragments packet rule component is needed because IP packets often go through different size network connections. Sometimes they have to be broken down into a group of smaller packets called fragments so they can go through a small-sized connection. This is particularly common if you use a modem to connect with PPP. For example, Ethernet can contain an IP packet 1500 bytes long, but a modem (serial line) packet is usually 256 bytes; thus the Ethernet-sized packet has to be broken down into six smaller modem-sized fragments. These fragments are then reassembled when they reach the destination computer. You should specify this rule component if you use a modem connection through PPP or SLIP so the firewall looks at the packet as a whole rather than at the individual fragments. Only then can it look at the transport layer protocol (TCP, UDP, ICMP) information properly to apply other rules. These rules should be run at the command line and then checked with /sbin/ipchains -L to see that everything is in proper order. You then need to save them to the file indicated for the startup/shutdown script (in our example, this is /etc/firewall.rules). The system will then use these same rules the next time it boots up. This command needs to be executed each time you define a new set of rules: # /sbin/ipchains-save > /etc/firewall.rules The next section gives some examples on using these rules.

Some example configurations The simplest model is where you need to allow only your clients behind the firewall to access the outside world but not allow any outside machine to connect into the firewalled network. All you need to do, in this case, is first close off all outgoing packets through all interfaces, and then let through only the ones to the outgoing Internet connection once it has had the address information converted: # /sbin/ipchains -P forward DENY # /sbin/ipchains -A forward -f -i ppp0 -j MASQ With the above rule, all firewalled machines (Bob, Fred, Jane, and Olivia) will be masqueraded before their packets go out. The router is really not a part of the picture in this case, and in fact, the firewall uses a locally connected modem to establish a PPP connection to the Internet. These rules, however, will not allow machines outside the firewall to contact those inside. It is not uncommon to find firewall code built into the router. So in many cases, the firewall and the router can be the same machine. On the other hand, with a PPP modem scenario, your firewall is the router itself, with the route command directed to send all non-local traffic to the PPP port. A more complex example is where you want all firewalled machines to access the outside but you want specific machines to connect in. The following example allows the machine familiar (198.102.68.2) to access the firewall-internal machines only on specific ports (telnet, FTP, and WWW). # /sbin/ipchains -P forward DENY # /sbin/ipchains -A forward -f -i eth0 -j MASQ # /sbin/ipchains -A input -i eth0 -s 198.102.68.2 -j ACCEPT # /sbin/ipchains -A output -i eth1 -s 198.102.68.2 -d 0/0 -j DENY # /sbin/ipchains -A output -i eth1 -s 198.102.68.2 -d 0/0 telnet -j MASQ # /sbin/ipchains -A output -i eth1 -s 198.102.68.2 -d 0/0 ftp -j MASQ # /sbin/ipchains -A output -i eth1 -s 198.102.68.2 -d 0/0 ftp-data -j MASQ # /sbin/ipchains -A output --i eth1 s 198.102.68.2 -d 0/0 www -j MASQ In our scenario, there is a separate server called Freedom that is outside the firewalled network but within the company. This is a public Web server that anyone can access. This machine should be treated as any other public Internet computer because it may be subject to attack and subversion from the outside world, without the protection of a firewall. However, let's say the machine is secured enough to be allowed to connect into our firewalled area. You would need to add the following additional rules: # /sbin/ipchains -A input -i eth0 -s 216.19.15.32 -j ACCEPT # /sbin/ipchains -A output -i eth1 -s 216.19.15.32 -d 0/0 -j MASQ

Application protocols Application-layer protocols can sometimes embed network or host address information within their packets. The packet filter normally does not look within the contents of a TCP or UDP packet, unless specifically directed to do so. The application requires that the protocol contain the appropriate address information for the host or it will fail to work. Thus, there are several other modules that need to be loaded into the kernel if they are to also filter these application protocols. Some of these modules include support for protocols used by FTP, RealAudio, IRC, VDO Live, CU SeeMe, and even the popular game, Quake. To load these modules you can add any of the following lines for the particular protocol to the startup/shutdown script defined earlier: /sbin/modprobe ip_masq_raudio /sbin/modprobe ip_masq_irc /sbin/modprobe ip_masq_cuseeme /sbin/modprobe ip_masq_vdolive /sbin/modprobe ip_masq_quake /sbin/modprobe ports=ip_masq_quake 26000,27000,27910 Ipchains is quite powerful when you look at its ability to chain groups of rules at a time. The ability to create multiple chains becomes more important when you have large numbers of nodes internally, and have to define network traffic policies for many of these nodes. These chains can be assigned to specific network interfaces to change the security policies should that interface go up or down (that network link gets

9 of 10

1/13/00 10:22 AM

developerWorks : Linux : Library - Papers

http://www-4.ibm.com/software/developer/library/linux-firewall/index.html

connected or disconnected, for example). Ipchains is continuing to evolve. With the next version of the kernel (version 2.3.x and 2.4.x) comes a new version of the software, called netfilter. The new version will be able to do some other tricky elements such as reverse NATs, which are used for load-balancing a group of internal machines to one address. In any case, the effective use of ipchains will allow you to create an equitable firewall that protects your internal network from prying eyes outside. It can turn your not-so-fast machine of yesteryear into a useful subject of your network, and give it a new purpose in its short life.

Resources The ipchains home page and official download site The Ipchains HOW-TO document by Rusty Russell (a little more complex than it should be) Rusty Russell's various Linux firewall projects "Securing Your Linux Box," Linux Gazette, November 1998 "Securing Linux, Part 1," in LinuxWorld magazine, May 1999 "Securing Linux, Part 2," in LinuxWorld magazine, July 1999

About the author Rawn Shah has served as a network manager, a systems programmer, a Web architect, and an Internet service entrepreneur. Since 1993 he has written for nearly a dozen national and international magazines, published in English and other languages. He has just finished writing his most recent book, UNIX and Windows 2000 Integration Toolkit (John-Wiley & Sons, 1999). He is currently an independent technologist based in Tucson, Arizona, writing on topics of networking and cross-platform integration. He can be reached at [email protected]. What do you think of this article? Killer!

Good stuff

So-so; not bad

Needs work

Lame!

Comments?

Submit feedback

10 of 10

1/13/00 10:22 AM