12.5 Firewalls with IP Tables and DMZIP Tables is the third generation of firewall technology for Linux and is the successor to IP Chains. As of the publication of this book, different UNIX vendors use one of several different firewall packages, none of which is IP Tables or IP Chains. Their concepts and techniques are similar, though, so UNIX SysAdmins should find this section useful. The syntax and amount of granularity will vary. Some primarily UNIX SysAdmins may find, as have some of the more advanced mostly Windows SysAdmins,, that a single Linux system operating as a firewall may be the most secure and most easily implemented solution. IP Tables has some innovative features, not available with IP Chains, which are of particular interest to large shops. The most important new feature is a general connection-tracking (or stateful) feature for tracking regular TCP sessions and UDP and ICMP communication. There is a lot of misinformation about this connection-tracking security compared with IP Chains. This is addressed in depth in "IP Tables Connection Tracking: Fact and Myth" on page 465. 12.5.1 Cut to the Chase: Protecting a Simple SOHO NetworkHere we create a set of IP Tables rules to protect a simple small office or home office (SOHO) network. In this common configuration, the Linux firewall will connect directly to the Internet via eth0 connected to a cable modem, though eth0 could be replaced with ppp0 for PPP via a telephone modem or DSL. The second interface, usually eth1, will be on a switch or hub connected to one or more "inside" systems. These could be any combination of Linux, Mac, UNIX, or Windows systems. This will provide a quick hands-on experience with IP Tables while protecting one's home network before it gets broken into, and buy time while the subtle art and exact science of firewalls is discussed.
When the Linux kernel first starts all packets are allowed to all available interfaces. Prior to enabling the networking feature, unacceptable packets must be blocked. (Most distributions enable the firewall rules before bringing up interfaces, which offers protection from the get go. Unlike route commands, firewall rules referring to a particular interface may be added before that interface is enabled and they are not removed after that interface goes down, so long as the system stays up.) However, the IP address, network address, and broadcast address of each interface must be known for proper filtering. Most SOHO users suffer with a dynamic IP address and so this IP address cannot be known prior to activating the network. The best way to deal with this conflict is to have two different scripts.
The first script, which is called iptables_pre, will be invoked before networking is enabled. It will create rules to block all packets. The second one, called rc.fwsoho, will be invoked after networking is enabled. It will determine each interface's IP address and related settings and then will build up the firewall rules in a safe order. If you are using SuSE, Red Hat, and Mandrake systems, copy the script iptables_pre from the book/iptables directory of the CD-ROM to the /etc/rc.d/init.d directory of your system. Then create a symlink so that it will be invoked when your system enters its default run state, typically 3. (Some other distributions may have the rc3.d directory directly under /etc or may have a default run state of 2 instead of 3.) Scripts to be used with Slackware will be covered shortly. mkdir /mnt2 ; chmod 755 /mnt2 Mount the CD-ROM device on /mnt2 cd /etc/rc.d/rc3.d cp /mnt2/book/iptables/iptables_pre ../init.d/iptables_pre ln -s ../init.d/iptables_pre S00iptables Next, disable the existing IP Chains or IP Tables startup scripts in rc3.d. Note that SuSE has both an initialization script and a startup (setup) script. Red Hat and Mandrake have a startup script. Rename them so that they start with a lowercase s instead of an uppercase S to prevent them from being invoked on bootup. The shutdown scripts (seen in SuSE only) should be handled the same way. The file name varies between distributions and versions. For SuSE8.0, do: mv K02personal-firewall.final k02personal-firewall.final mv K18SuSEfirewall2_setup k18SuSEfirewall2_setup mv K23personal-firewall.initial k23personal-firewall.initial mv S01personal-firewall.initial s01personal-firewall.initial mv S06SuSEfirewall2_setup s06SuSEfirewall2_setup mv S22personal-firewall.final s22personal-firewall.final For RH7.3, do: mv S08ipchains s08ipchains mv S08iptables s08iptables For Mandrake8.2, do: mv S03iptables s03iptables mv S08ipchains s08ipchains Since Slackware uses the Berkeley startup scheme instead of the AT&T scheme, after copying the iptables_pre script to the /etc/rc.d directory, simply edit /etc/rc.d/rc.inet1. Near the top of it, before any network interfaces are enabled, have rc.inet1 invoke the first script, /etc/rc.d/iptables_pre Issue the following commands to prepare this: mkdir /mnt2 ; chmod 755 /mnt2 Mount the CD-ROM device on /mnt2 cd /etc/rc.d cp /mnt2/book/iptables/iptables_pre . favorite_editor rc.inet1 Now, regardless of the distribution, copy the rc.fwsoho from the CD-ROM to the /etc/rc.d directory and symlink it to rc.fw: cd /etc/rc.d cp /mnt2/book/iptables/rc.fwsoho . ln -s rc.fwsoho rc.fw The iptables_pre script looks like: #!/bin/sh # iptables_pre: pre-block IP Tables IPT=iptables $IPT -P INPUT DROP $IPT -P OUTPUT DROP $IPT -P FORWARD DROP $IPT -F # dhclient (DHCP client) uses a raw socket that # bypasses IP Tables. Thus, it works even if all # packets are blocked. If you use a different program # for DHCP to set the dynamic IP address of your # Internet interface, the following may be uncommented: # $IPT -I INPUT 1 -p UDP --sport 67 --dport 68 -j ACCEPT # $IPT -I OUTPUT 1 -p UDP --sport 68 --dport 67 -j ACCEPT $IPT -t nat -P PREROUTING DROP $IPT -t nat -P POSTROUTING DROP $IPT -t nat -P OUTPUT DROP $IPT -t nat -F
Now that the iptables_pre script will protect the system while the network interfaces are being brought up, it is time to arrange for the main script, rc.fwsoho (symlinked to rc.fw) to be invoked on bootup. While we could invoke it the same way we invoked iptables_pre, instead we will use a real rc.d-style script to invoke it. This rc.d-style script is based on the Red Hat 7.3 iptables startup script but has been modified to generate a message and error exit if IP Tables is not available. This could happen if IP Chains is loaded. You will want to correct such a situation, of course. On SuSE, Red Hat, and Mandrake systems, copy the script iptables.rh73 from the book/iptables directory of the CD-ROM to the /etc/rc.d/init.d directory of your system. Then create a symlink to it so that it will be invoked when your system enters its default run state, typically 3, after networking has been enabled. You already disabled the existing IP Chains or IP Tables startup scripts. (Scripts to be used with Slackware will be covered shortly.) cd /etc/rc.d/rc3.d cp /mnt2/book/iptables/iptables.rh73 ../init.d/iptables.rh73 ln -s ../init.d/iptables.rh73 S07iptables Since Slackware uses the Berkeley startup scheme instead of the AT&T scheme, Slackware users simply should edit /etc/rc.d/rc.inet2. Near the top of it, invoke the rc.fw script, which is a symbolic link to rc.fwsoho: /etc/rc.d/rc.fw Slackware users then should issue the following commands to prepare this: cd /etc/rc.d cp /mnt2/book/iptables/rc.fwsoho . ln -s rc.fwsoho rc.fw favorite_editor rc.inet2 Now, it is time to dive into the function of the rc.fwsoho script.
First, you need to specify the external and internal interface names. By convention, if the external interface is Ethernet, it is eth0 and the internal interface is eth1. (You can add alias commands to the /etc/modules.conf file to change the device to which eth0 and eth1 are assigned.) You will also define the path for the IP Tables and utility programs. Supplying absolute path names increases security slightly and is suggested. The following lines will do this: #!/bin/sh # rc.fwsoho: SOHO IP Tables rule set # uncomment to see each line as it is executed #set -v # External interface EXTIF=eth0 # Internal interface INTIF=eth1 IPT=iptables IFC=ifconfig G=grep SED=sed Second, securely clean out any existing rules. Many people botch this step, either causing their system to be insecure briefly or requiring them to reboot each time they tweak their rules. We set the policy of each chain to DROP and then flush any existing rules. This avoids the common error of flushing rules first while the policy is still ACCEPT, which would allow all packets through. We also can skip the common error of not flushing any existing rules before adding our rules. This error prevents someone from successfully reinvoking the firewall script after changing it because the existing rules will affect packets first. $IPT -P INPUT DROP $IPT -P OUTPUT DROP $IPT -P FORWARD DROP $IPT -F $IPT -t nat -P PREROUTING DROP $IPT -t nat -P POSTROUTING DROP $IPT -t nat -P OUTPUT DROP $IPT -t nat -F Third, we tweak the kernel for better protection against protocol-level attacks.[7] We turn on TCP SYN cookies to prevent harm from TCP SYN floods. We also turn on source address verification (rp_filter) so that the kernel will reject any packet arriving on an interface with an inappropriate address. This partially overlaps our rules to block source spoofing. We disable source routing (i.e., where the source system requests a specific route) and ICMP redirects (i.e., messages trying to alter our routing table). These are explained in detail in "Blocking IP Source Routing" on page 133 and "Blocking IP Spoofing" on page 134.
Now that we have stopped packets going through the FORWARD chain, it is safe to enable forwarding in the kernel (later, after we selectively allow forwarding, that proc setting will be real handy): echo 1 > /proc/sys/net/ipv4/tcp_syncookies echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts # Source Address Verification for f in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 1 > $f done # Disable IP source routing and ICMP redirects for f in /proc/sys/net/ipv4/conf/*/accept_source_route; do echo 0 > $f done for f in /proc/sys/net/ipv4/conf/*/accept_redirects; do echo 0 > $f done echo 1 > /proc/sys/net/ipv4/ip_forward Fourth, we must specify the details for our external interface that connects to the Internet, our internal interface that connects to our IP Masqueraded local area, and the loopback device: EXTIP="`$IFC $EXTIF|$G addr:|$SED 's/.*addr:\([^ ]*\) .*/\1/'`" EXTBC="`$IFC $EXTIF|$G Bcast:|$SED 's/.*Bcast:\([^ ]*\) .*/\1/'`" EXTMSK="`$IFC $EXTIF|$G Mask:|$SED 's/.*Mask:\([^ ]*\)/\1/'`" EXTNET="$EXTIP/$EXTMSK" echo "EXTIP=$EXTIP EXTBC=$EXTBC EXTMSK=$EXTMSK EXTNET=$EXTNET" INTIP="`$IFC $INTIF|$G addr:|$SED 's/.*addr:\([^ ]*\) .*/\1/'`" INTBC="`$IFC $INTIF|$G Bcast:|$SED 's/.*Bcast:\([^ ]*\) .*/\1/'`" INTMSK="`$IFC $INTIF|$G Mask:|$SED 's/.*Mask:\([^ ]*\)/\1/'`" INTNET="$INTIP/$INTMSK" echo "INTIP=$INTIP INTBC=$INTBC INTMSK=$INTMSK INTNET=$INTNET" LPDIF=lo LPDIP=127.0.0.1 LPDMSK=255.0.0.0 LPDNET="$LPDIP/$LPDMSK" Fifth, we create two user-defined chains to log and block unacceptable packets. Unlike IP Chains, IP Tables does not offer a -l flag that could be appended to a rule's target for this purpose. Our technique avoids the cumbersome but common practice of having a -j LOG before each -j DROP or -j REJECT rule that we want to log. # Do not complain if chain already exists # (so restart is clean) $IPT -N DROPl 2> /dev/null $IPT -A DROPl -j LOG --log-prefix 'DROPl:' $IPT -A DROPl -j DROP $IPT -N REJECTl 2> /dev/null $IPT -A REJECTl -j LOG --log-prefix 'REJECTl:' $IPT -A REJECTl -j REJECT The loopback device is a simulated device so that networking code can be used even on systems without an actual network. A peculiarity of Linux is that its process of wanting to send packets to the Internet commonly will show as inputting data from the loopback device but with the source IP address of the appropriate real device. This will occur even though the loopback network is supposed to be 127.0.0.0/8. To deal with this situation, we allow packets from this device if the source IP address matches any of our interfaces: $IPT -A INPUT -i $LPDIF -s $LPDIP -j ACCEPT $IPT -A INPUT -i $LPDIF -s $EXTIP -j ACCEPT $IPT -A INPUT -i $LPDIF -s $INTIP -j ACCEPT Next, we block broadcast packets. Usually, these are crackers trying to attack a whole range of systems with a single packet. Many ISPs do not bother to filter these out. Some broadcasts may be Windows chatter from the internal network but also could be a misconfigured or compromised system. Note that other than the loopback ACCEPT targets above, we will have most of our DROP and REJECT rules before we have any ACCEPT rules in each chain. This reduces the chance of allowing some ACCEPTs accidentally before we block all known evil packets. # Block broadcasts # (We could also do -s rules) $IPT -A INPUT -i $EXTIF -d $EXTBC -j DROPl $IPT -A INPUT -i $INTIF -d $INTBC -j DROPl $IPT -A OUTPUT -o $EXTIF -d $EXTBC -j DROPl $IPT -A OUTPUT -o $INTIF -d $INTBC -j DROPl $IPT -A FORWARD -o $EXTIF -d $EXTBC -j DROPl $IPT -A FORWARD -o $INTIF -d $INTBC -j DROPl Now, block packets sent to us through the external interface with a destination address other than our external interface's IP address. It is important to note that packets get to the INPUT and FORWARD chains after any IP Masquerading. Thus, we must not have a similar rule for the FORWARD chain. # Block Internet from trying to access internal or route thru us $IPT -A INPUT -i $EXTIF -d ! $EXTIP -j DROPl Next, block any internal system whose source address is not within our internal network. This is an absolutely critical part of Egress filtering. It will prevent a compromised internal system from possibly evading our IP Masquerading and attacking other systems on the Internet with an untraceable IP address:[8]
# Block internal with bad network address $IPT -A INPUT -i $INTIF -s ! $INTNET -j DROPl $IPT -A OUTPUT -o $INTIF -d ! $INTNET -j DROPl $IPT -A FORWARD -i $INTIF -s ! $INTNET -j DROPl $IPT -A FORWARD -o $INTIF -d ! $INTNET -j DROPl # One last Egress check for sanity $IPT -A OUTPUT -o $EXTIF -d ! $EXTNET -j DROPl It is critical to block all outbound ICMP packets except your ping requests in order to prevent crackers from mapping your network. Despite widely believed urban legends to the contrary, this will not cause your network access to suffer due to blocked messages begging for fragmentation. While it might be convenient to allow inbound pings, crackers usually use them as their first step in seeing what addresses have systems connected. A simple telnet to the service offered is an excellent test of system health and, in fact, will show sick systems as down. # Block outbound ICMP (except ping) $IPT -A OUTPUT -o $EXTIF -p icmp \ --icmp-type ! 8 -j DROPl $IPT -A FORWARD -o $EXTIF -p icmp \ --icmp-type ! 8 -j DROPl Hopefully, you will be using an intrusion detection system (IDS) such as the Cracker Trap or Portsentry to see who is trying to break into your network. (These are discussed in "Adaptive Firewalls: Raising the Drawbridge with the Cracker Trap" on page 559 and "Using PortSentry to Lock Out Hackers" on page 613, respectively.) In a short period of time you will have a list of repeat offenders that you will want to block. If you use the Adaptive Firewall called the Cracker Trap, it will generate this list automatically in the file fw.trouble. The mundane initial form of fw.trouble may be copied from the book/crackertrap directory of the CD-ROM. Even if you edit this file manually, we source its contents at this point in rc.fwsoho so that its blocking rules take effect. . /etc/rc.d/fw.trouble At this point most people would add rules to allow those services desired. However, I always go out of my way to block common attacks first. By having these blocking rules near the top of the rule list, there is a much smaller risk of letting these packets through accidentally. I see these attacks daily in monitoring my clients' networks. To make life easy, I suggest listing the forbidden ports in a pair of variables and using a loop for processing. Note that we forbid internal systems from launching similar attacks on the Internet. This protects everyone else on the Internet in the event one of your systems gets compromised, say, by a Windows e-mail virus. This is part of being a good Internet citizen and also reduces your chances of getting sued for negligence. Ports common to TCP and UDP: # Frequently attacked blocked services: COM blocks both TCP&UDP # Note that ALL UDP ports can be abused by attackers to have YOU do # a DoS attack against the third party of their choice; this is why # even benign UDP services are blocked # COMmon ports: # 0 is tcpmux; SGI had vulnerability, 1 is common attack # 13 is daytime # 98 is Linuxconf # 111 is sunrpc (portmap) # 137:139, 445 is Microsoft # SNMP: 161,2 # Squid flotilla: 3128, 8000, 8008, 8080 # 1214 is Morpheus or KaZaA # 2049 is NFS # 3049 is very virulent Linux Trojan, mistakable for NFS # Common attacks: 1999, 4329, 6346 # Common Trojans 12345 65535 COMBLOCK="0:1 13 98 111 137:139 161:162 445 1214 1999 \ 2049 3049 4329 6346 3128 8000 8008 8080 12345 65535" # TCP ports: # 98 is Linuxconf # 512-515 is rexec, rlogin, rsh, printer(lpd) # [very serious vulnerabilities; attacks continue daily] # 1080 is Socks proxy server # 6000 is X (NOTE X over SSH is secure and runs on TCP 22) # Block 6112 (Sun's/HP's CDE) TCPBLOCK="$COMBLOCK 98 512:515 1080 6000:6009 6112" # UDP ports: # 161:162 is SNMP # 520=RIP, 9000 is Sangoma T1/E1 card control # 517:518 are talk and ntalk (more annoying than anything) UDPBLOCK="$COMBLOCK 161:162 520 517:518 1427 9000" The following commands will add rules to block this evil: echo -n "FW: Blocking attacks to TCP port " for i in $TCPBLOCK; do echo -n "$i " $IPT -A INPUT -p tcp --dport $i -j DROPl $IPT -A OUTPUT -p tcp --dport $i -j DROPl $IPT -A FORWARD -p tcp --dport $i -j DROPl done echo "" echo -n "FW: Blocking attacks to UDP port " for i in $UDPBLOCK; do echo -n "$i " $IPT -A INPUT -p udp --dport $i -j DROPl $IPT -A FORWARD -p udp --dport $i -j DROPl done echo "" Now that we have blocked a lot of nastiness unconditionally, it is time to decide what services we want to allow. This part of the script should be altered to allow only the services that you want to use right now. This follows the important security policy of allowing only the minimum needed to get the job done. While you will assume that each internal system is allowed the same services, there is no requirement for this. For example, if you do not want your child to send e-mail, his system can be blocked from sending to TCP port 25. IP Tables' state capability solves the long-standing security problem of active FTP. When using the original FTP protocol, now called active FTP, data is transferred by having the server initiate a TCP connection back to the client to connect to a previously agreed-upon high port number on the client system. This is a very brain-damaged protocol. All firewalls should block most externally originating connections to client systems. Fortunately, IP Tables' state capability can open up only this agreed-upon port for the duration of this connection and then close it. To enable this special FTP connection tracking, it is necessary to do a modprobe (or an insmod) on the kernel modules ip_nat_ftp and ip_conntrack_ftp. The following code does this: MODULES="ip_nat_ftp ip_conntrack_ftp" for i in $MODULES; do echo "Inserting module $i" modprobe $i done There is a similar module for IRC. If you wish to handle another popular but brain-damaged protocol, even those supported under IP Chains, you are out of luck. It now is time to enable the services that inside systems (including the firewall itself) are allowed to use. FORWARD rules apply to systems other than the firewall itself, in case you want to make a distinction in which services are allowed where. We also introduce the --syn flag here. It will cause the rule to match only if the TCP SYN bit is set and the ACK and FIN bits are off. This combination of enabled bits is true only for the packet that starts a TCP connection. Note that OUTPUT rules will affect only packets originating from the firewall itself and that FORWARD rules will affect only packets originating from other systems. Another difference is that in IP Chains, you specified a target of MASQ in the forward chain to indicate that the source address should be altered for outbound packets. In IP Tables, you merely ACCEPT these packets and address altering is done in the new POSTROUTING chain. Let us assume that you want to allow ssh, http, https, ftp (passive mode), mail, pop, imap, pops, imaps, 11371 (PGP/GPG keyservers), DNS, time, and Network Time Protocol (NTP). These rules should be as specific as possible. Limiting the destination to only your ISP's DNS and mail servers by using the -d flag is an excellent idea. The following will allow this traffic: TCPSERV="domain ssh http https ftp ftp-data \ mail pop3 pop3s imap3 imaps 11371 time" UDPSERV="domain time ntp" echo -n "FW: Allowing inside systems to use service:" for i in $TCPSERV; do echo -n "$i " $IPT -A OUTPUT -i $EXTIF -p tcp -s $EXTIP \ --dport $i --syn -m state --state NEW -j ACCEPT $IPT -A FORWARD -i $INTIF -p tcp -s $INTNET \ --dport $i --syn -m state --state NEW -j ACCEPT done echo "" The following will let internal systems do a standard UDP DNS lookup. It is recommended that you further restrict DNS lookups to the ISP's DNS servers by specifying each system's IP address in the -d argument of a rule. echo -n "FW: Allowing inside systems to use service:" for i in $UDPSERV; do echo -n "$i " $IPT -A OUTPUT -i $EXTIF -p udp -s $EXTIP \ --dport $i -m state --state NEW -j ACCEPT $IPT -A FORWARD -i $INTIF -p udp -s $INTNET \ --dport $i -m state --state NEW -j ACCEPT done echo "" As it was with TCP and UDP, so it is with ICMP. Usually, the only ICMP type that initiates a connection is the echo request, used by the following ping command. # Allow to ping out $IPT -A OUTPUT -o $EXTIF -p icmp -s $EXTIP \ --icmp-type 8 -m state --state NEW -j ACCEPT $IPT -A FORWARD -i $INTIF -p icmp -s $INTNET \ --icmp-type 8 -m state --state NEW -j ACCEPT As part of our rings of security, we must accept the chance of the firewall being partially compromised. For example, a cracker may be able to become an ordinary user by breaking a nonroot program or password. Because of this risk, we chose not to allow the firewall to be able to access any ordinary services inside, in the previously mentioned rules. We choose to allow it to SSH into internal systems later on. Here, we allow it to ping internal systems, as the chance of compromise is remote: $IPT -A OUTPUT -o $INTIF -p icmp -s $INTNET \ --icmp-type 8 -m state --state NEW -j ACCEPT Do you want anyone on the Internet to use any of the servers on your firewall? The answer probably is yes. Most mail servers are configured to send an auth (or ident) request to any system trying to send it mail and then to wait between 30 seconds and five minutes for a reply before giving up and accepting the e-mail. If you do not reply to this request, you will suffer this delay for each piece of e-mail sent out. Commonly, you will accept such ident requests but configure the firewall so that the numeric UID of the user is sent rather than a user name, which might be useful for password guessing. Securely configuring the ident server is discussed in "The ident Service" on page 231. The following rule will allow the ident service: $IPT -A INPUT -p tcp --dport auth \ --syn -m state --state NEW -j ACCEPT An alternative that most mail servers will accept is to send an ICMP "get-lost" message thusly: $IPT -A INPUT -p tcp --dport auth -j REJECT The REJECT target means that an ICMP type 3, subtype 3 message should be sent to say "Port unreachable." If you have a static IP address or otherwise can determine your external interface's IP address, you may want to allow SSH from the Internet. If you have a really strong password, you could do: $IPT -A INPUT -i $EXTIF -p tcp --dport 22 \ --syn -m state --state NEW -j ACCEPT If you want to be more careful, you might allow yourself to SSH in from your office at Pentacorp and also allow your friend in from the University: $IPT -A INPUT -i $EXTIF -p tcp -s pentacorp.com/24 --dport 22 \ --syn -m state --state NEW -j ACCEPT $IPT -A INPUT -i $EXTIF -p tcp -s chemwiz.state.edu --dport 22 \ --syn -m state --state NEW -j ACCEPT In any case, if you want to allow SSH from hardened internal systems (hopefully only those running Linux or UNIX hardened as per the book) add: $IPT -A INPUT -i $INTIF -p tcp --dport 22 \ --syn -m state --state NEW -j ACCEPT To allow remote administration of your internal network, you may want to harden your internal system thoroughly, grant SSH access to the system from the firewall, and grant SSH access to the firewall from the trusted outside systems. Of course, you must be very careful with these systems to avoid a significant risk of endangering the security of the entire network. The following example will grant this access: # Connect only to hardened systems # (hopefully only those running Linux or UNIX hardened as per the book) $IPT -A OUTPUT -o $INTIF -p tcp --dport 22 \ -d 10.0.0.42 --syn -m state --state NEW -j ACCEPT As noted, our previously stated rules in the FORWARD chain (before the SSH rules) did not indicate that the source address of outbound packets needs to be changed from that of your IP Masqueraded internal network to that of the firewall's outside interface. Instead, this is done in a subsequent chain, the POSTROUTING chain. Somewhat logically, this chain processes packets after they have been routed to their outbound interface. This chain, along with the PREROUTING and OUTPUT chains, comprise the nat table of chains. To allow for the case where the firewall will be a proxy for servers, there is the new PREROUTING chain in the nat table. Packets are matched against this chain before routing, that is, before deciding whether they go on to the INPUT chain or to the FORWARD chain. This destination network address translation (DNAT) feature is useful even in some SOHO networks. If it is not being used, use just the following: $IPT -t nat -A PREROUTING -j ACCEPT For the SOHO rules, we need to do IP Masquerading, now called source network address translation, or SNAT. The MASQUERADE target, almost identical to the IP Chains MASQ target in the Chains' FORWARD chain, will do just fine. This must be followed by a general ACCEPT rule in the POSTROUTING chain so that other packets can be on their way. Leave out the rule that specifies a target of MASQUERADE if you do not want to Masquerade your internal network. $IPT -t nat -A POSTROUTING -o $EXTIF -s $INTNET -j MASQUERADE $IPT -t nat -A POSTROUTING -j ACCEPT It is "almost identical" because the MASQUERADE target has the additional feature that if the output interface goes down, active connection data is removed. While this is helpful for a dynamic PPP connection to prevent a very small risk of misdirected packets, I think that IP Tables again has missed the boat. This is because it fails to remove this connection data if the interface stays up but its address changes, such as may happen when a DHCP request from the ISP is received, changing the IP address (to prevent a customer from running a Web server without paying higher commercial rates). The OUTPUT chain allows altering locally generated packets. Unless you are getting exotic, the following is needed: $IPT -t nat -A OUTPUT -j ACCEPT The IP Tables documentation recommends for static external IP addresses where you should use the SNAT target instead of the MASQUERADE target. Just to punish anyone who follows this recommendation, the SNAT target is not smart enough to figure out that addresses should be mapped to the IP address of the outgoing interface. Instead, the address of the outgoing interface must be specified. If you want to use this target instead of MASQUERADE, it would look like: $IPT -t nat -A POSTROUTING -o $EXTIF -s $INTNET \ -j SNAT --to $EXTIP A consequence if you use the SNAT target with a DMZ is that a separate rule would be needed for packets from the internal network going to the DMZ. (Change EXT to DMZ for that rule.) Did we forget anything? What about all of those reply packets? What about the third packet of the initial TCP three-way handshake? With IP Chains, we would need a corresponding rule for each of these. With IP Tables, we just say "uh, allow all of the obvious related stuff, too": iptables -A INPUT -m state \ --state ESTABLISHED,RELATED -j ACCEPT iptables -A OUTPUT -m state \ --state ESTABLISHED,RELATED -j ACCEPT iptables -A FORWARD -m state \ --state ESTABLISHED,RELATED -j ACCEPT Finally, any packet that has not been otherwise handled should be logged and blocked. While a chain's policy (which takes effect if no rule in the chain matches the packet) would block the packet, the policy cannot be made to log it first. Thus, we do the following: $IPT -A INPUT -j DROPl $IPT -A OUTPUT -j REJECTl $IPT -A FORWARD -j DROPl As you recall, this complete script may be copied from the CD-ROM: cd /etc/rc.d cp /mnt2/book/iptables/rc.fwsoho . ln -s rc.fwsoho rc.fw It is time to reboot the system and test the firewall by exercising the allowed services and by using nmap and, possibly, Ethereal from outside and inside systems while running a tail -f /var/log/messages on the firewall. You would run nmap from a system on the Internet while running Ethereal on an inside system and then reverse the positions. On the Internet side, a basic set of nmap commands might be: nmap -P0 -sS -F -O -T Aggressive your_real_IP nmap -P0 -sU -F -O -T Aggressive your_real_IP nmap -sP -PI -T Aggressive your_real_IP Then, from an inside system, repeat the procedure but list the internal and external IP addresses of the firewall as well as the name of another system on the Internet that you are allowed to scan. Finally, repeat both scans from the firewall system itself. Now, on to all the other details of IP Tables for fancier networks. Yes, we have just touched the surface. 12.5.2 IP Tables' Advantages over IP ChainsThis connection-tracking feature can be used to prevent most hijackings of TCP connections for non IP Masqueraded clients that suffer from poor TCP sequence number randomization, such as Windows systems, some UNIX systems (notably SGI), some IBM configurations, and many older systems. It also can be used to prevent an attacker from hijacking a UDP conversation in the same way[9] and from injecting spurious ICMP packets for attacking and probing. IP Chains' IP Masquerading, the MASQ target, (and IP Tables' equivalent, MASQUERADE or SNAT) offers similar security and, in fact, IP Tables' connection tracking is based on IP Chains' IP Masquerading code. See "IP Tables Connection Tracking: Fact and Myth" on page 465 for an in-depth enlightening analysis.
A significant advantage of IP Tables over IP Chains is that Active FTP now can be safely enabled for clients behind a firewall. Recall that Active FTP requires the server to be able to initiate a connection back to the client using a high port number on the client. (Passive FTP can be selected in most interactive FTP clients with the passive command. Most browsers automatically use Passive FTP.) Active FTP cannot be securely enabled under IP Chains. It can be under IP Tables. Even the SOHO set of rules enables it. Other new features include being able to match packets based on a MAC address,[10] the local process's UID, Time To Live (TTL), or the rate of a class of packets being seen. These allow better detection and rejection of interlopers trying to inject packets or scan us. While it is easy to change the IP address of a system for spoofing, it is harder to change the MAC address, and some network interface cards (NICs) do not offer this option. While only root can open a port below 1024 for listening (for security purposes), a number of trusted services have port numbers above this and thus represent a security risk. These services include Socks (a general proxy port) and X (a general security risk). You now can restrict their use to root.
Incoming packets initiating TCP connections to your organization's servers can be randomly distributed among a set of servers to spread the load, with subsequent packets of a connection being routed to the same server. With IP Tables, you can specify a text string to precede the logged message. This makes understanding why the packet was logged easier. Logging of incoming packets includes logging the MAC address; this is very useful when DHCP or another dynamic IP assignment method is in use. IP Tables has the ability to REDIRECT packets originally addressed to other systems to instead be sent to the firewall system itself (as in IP Chains). IP Tables also has a generalized DNAT feature more capable than IP Chains' portfw facility. This allows arbitrary changing of the destination IP address and port number of packets before sending them on their way. Thus, if you wanted to enforce the use of Squid automatically for Web caching, it no longer must reside on the firewall system. Any packets destined for port 80 on the Internet now can be DNAT'ed to the Squid machine. 12.5.3 IP Tables' Disadvantages Compared to IP ChainsSadly, though, some questionable design changes were made in IP Tables. These changes make life more difficult for SysAdmins and were done for no reason that this author can fathom. I certainly am standing on my soapbox as I discuss these, but an important part of any development and one of the things that makes most Open Source software great is public review, open discussion of the advantages and disadvantages, and suggestions for improvement. These include the following, all of which easily could be corrected. I may do so and put the results on the book's Web site at www.realworldlinuxsecurity.com/ for all to enjoy.
The only real reason iptables is prevented from figuring out which rule applies to which table is the use of the same name (i.e., OUTPUT) both in the default table and the nat table. Certainly, recognizing natout as the name of the nat table's OUTPUT chain would be trivial to implement. This would eliminate the need to specify -t nat to manipulate these chains. By the way, you must name the correct table in which a user-defined chain should appear. If no table is named, the default table is assumed. The effort to eliminate these incompatibilities would have been a small fraction of the total development time and would have made life easier for SysAdmins converting from IP Chains. Certainly, a compatibility flag (or, better still, an environment variable) still could be added that would enable support of IP Chains syntax and semantics. Upward compatibility is an important feature in any engineering project because it allows users to avoid wasting their time and money redesigning and replacing their software, scripts, etc. If a program named, say, ipchains was provided that offered IP Chains syntax and semantics but interfaced with IP Tables, painless and gradual transition would be possible. 12.5.4 IP Tables Connection Tracking: Fact and MythAlmost all of the documentation that this author has read regarding IP Tables claims that the big advantage of IP Tables over IP Chains for most sites is the statefulness provided by its connection tracking. This means that it can be configured to allow your client systems to initiate TCP connections and UDP conversations, and for those clients to receive ICMP error messages related to these TCP and UDP packets while preventing external systems from attacking these same systems with unrelated packets. The biggest risk that connection tracking can prevent is an attack on the port on which a client is listening while awaiting a server's response. Some clients will accept packets from any IP address and port that sends packets to them and some are vulnerable to buffer overflow attacks. The only way to protect such a client is to ensure that only a server with which it initiates communication is allowed to send packets to it. Many SysAdmins do not realize that IP Chains' IP Masquerading (NAT) already has this state capability and will drop packets sent to its ports that were being forwarded to IP Masqueraded systems from someplace other than the IP and port with which the Masqueraded system initiated communication. Thus, if all vulnerable systems are IP Masqueraded with IP Chains, they already have this protection. I confirmed this both by inspecting the kernel's IP Chains code (in the 2.2 kernel) and by testing.[11] Once again, if all of your systems with weak network stacks are IP Masqueraded systems, you already have this protection. IP Tables' connection tracking's only apparent advantage is in protecting non IP Masqueraded systems with weak network stacks and in allowing Active FTP from clients behind it safely. At most sites, the only non IP Masquerading systems are servers in the DMZ. These servers must accept connections initiated by outside systems anyway; thus, connection tracking will not protect them. Most people use FTP from browsers (which use Passive FTP), and most command-line FTP programs accept the passive command to select this mode.
Neither IP Tables nor IP Chains filters out packets with bad TCP sequence numbers and, thus, both leave open the small vulnerability of an attack. Many platforms, including most Windows dialects, some UNIX versions, and even ancient Linux versions (prior to the 2.0 kernel) fail to randomize TCP sequence numbers. This vulnerability is explained in "TCP Sequence Spoofing Explained" on page 243, and defeating it is discussed in "Defeating TCP Sequence Spoofing" on page 246 and in "Fighting Connection Hijacking and ICMP Attacks" on page 468. Finally, many mail servers and some Web servers will use the ident (or auth) facility to identify what user on a client system is initiating a connection to them. They do this by sending a request to the client system's service (on TCP port 113) saying, for example, "What user has TCP port 56017 open?" They know what the client system's port number is because it is stored in the header of the TCP packet and is available to the application. Unfortunately, there is no checking of whether the system making the request is a server with an active TCP connection (or with recent UDP activity) with the port about which it is asking. Cracker scans of this port are quite common. I assert that a good stateful firewall should drop or reject these ident requests, except for those from servers contacted recently by one's clients. To date, IP Tables (and IP Chains) do not do this. I estimate that creating the necessary ip_conntrack_ident.c and ip_nat_ident.c for either of these from the existing ip_conntrack_ftp.c and ip_nat_ftp.c kernel modules would take a day or two. A partial solution would be to use identd's -n flag to return only a numeric UID. This still tells the cracker that this port is open and ripe for attack.
If Portsentry's Advanced Stealth mode is in use, one wrong guess will lock the attacking system out. The sharpest crackers will harvest this data generated by one system, then attack from an unrelated system that would not have been locked out by Portsentry. Note that a cracker scanning a firewall where all client systems are IP Masqueraded still will not be able to send packets to the clients unless he can guess the IP and port number of the server that each client currently is communicating with. Turning off ident entirely will result in slower access to some Web pages and slower mail delivery, typically by 30 300 seconds per connection. The ident service is discussed in detail in "The ident Service" on page 231 and also is addressed in "Cut to the Chase: Protecting a Simple SOHO Network" on page 446 and in "Basic IP Chains Firewall Usage" on page 527. 12.5.5 Fighting Connection Hijacking and ICMP AttacksTCP connection hijacking and UDP spoofing attempts actually are quite rare. Still, you should guard against them. ICMP attacks to break in or for DoS are rare as well, though the use of ICMP packets for scanning (or probing) are very common. Taking all of the following steps will provide an effective (but not 100 percent effective) defense:
12.5.6 Red Hat 7.3's Firewall ConfigurationRed Hat 7.3 was released as I was struggling to finish this manuscript. As with Red Hat's other 7.x series releases, it comes with a 2.4 kernel that supports IP Tables and mostly supports IP Chains. The "mostly" is because the kernel developers do not support port forwarding on the 2.4 version of IP Chains. Their rationale is that "it is not used enough" and IP Tables does not support IP Masquerading of all of the services that were supported under the 2.2 kernel. IP Masquerading support was dropped for raudio, ICQ, cuseeme, Quake, portfw, autofw, user, vdolive, and PPTP (Beta version available) in IP Tables. Those with a single externally visible IP address who want to distribute services among multiple systems either will need to use IP Tables or a proxy server[13] or stick with a 2.2 kernel to achieve this.
During installation of Red Hat 7.3, I was presented with a Firewall Configuration screen offering different levels of security (High, Medium, or No firewall), a button for default rules (I already had specified that this was to be a workstation), or a button for customization. If customization was selected I could click off which devices (interfaces) were considered trusted and click on checkboxes to enable incoming DHCP, SSH, telnet (boo, hiss), www or http, mail, or FTP (catcalls). I have become accustomed to digging through poor documentation in other systems that use such undefined quantities as "High" or "Medium." Usually, the time it takes to learn what the undefined quantities mean exceeds the time it takes to create my own script that I fully understand and document. Not here! Red Hat had an Online Help button right there in plain sight. Better still, the documentation was detailed and clearly written. For example, it explains what High Security is: High Security: By choosing High Security, your system will not accept connections that are not explicitly defined by you. By default, only the following connections are allowed:
Using this High Security will not allow the following:
If you are connecting your system to the Internet, but do not plan to run a server, this is the safest choice. It then points out that additional ports may be enabled via the Customize button and the checkboxes and that additional specific port numbers may be listed (it even explains that the syntax is port:protocol). Next, it defines medium security. Its choices of what to include in each of these security levels is very good. Clearly, they have studied past problems (such as break-ins via NFS and X) and closed these holes by default. This is a better design than Mandrake, whose highest security level makes the machine unusable. Red Hat 7.3 has another interesting feature. The service scripts, ipchains and iptables, accept a save argument that will cause the current rule set that the kernel is using to be stored in a file. This save is done when the system is shut down gracefully or on request with one of the following commands, depending on which firewall you are running: service ipchains save service iptables save When the system is rebooted or the respective firewall is started with start or restart, it will resume using these rules. As with SuSE 8.0's Firewall2 script, which will be looked at next, this feature is more for publicity and the simplest of firewalls. A major disadvantage of this technique is that it prevents the use of shell variables, loops, and comments. I do not see a significant advantage to offset this disadvantage. Both will get out of hand if just a little bit of complexity is needed. 12.5.7 SuSE 8.0's Firewall ConfigurationSuSE 8.0's Firewall2 script did not even do something as simple as correctly enabling FTP (active or passive in the DMZ). Debugging this problem was time-consuming and painful, both for an SuSE-experienced SysAdmin and for myself (I have a great deal of experience with IP Tables, FTP issues, and firewall techniques, but little experience with SuSE). This is the classic problem with fairly simple scripts (regardless of what platform they run on or what they create) intended to translate someone's intention into a program in a language considered too complex for the script's user to understand. One common result: the script is not powerful enough to do truly useful stuff, and the effort to understand both how the script works and what it is doing wrong far exceeds the effort simply to write an IP Tables script directly. While less impressive or less useful in its sales literature, SuSE might have served its customers better by following my procedure of providing clients with a well-written and well-commented IP Tables or IP Chains script that they can alter directly. I make liberal use of variables in a file that is separate from the main rules file. Clients then can edit the variables file to enable or disable specific features without needing to understand the rules set. This also allows me to supply tweaked versions of the rules file without affecting each client's customization. The time I spent determining that SuSE's script generated a decent but not great set of IP Tables commands, and trying to fix it to enable FTP exceeded the effort to customize my standard firewall script. I disagree with SuSE's suggestion that pings and traceroutes be allowed through both to the firewall itself and to any non IP Masqueraded systems. Many crackers first ping each address they are attacking and continue the attack only if they get a ping reply. Thus, disabling pings cuts down on attacks. Less sophisticated users will not know how to use pings or traceroutes anyway. More sophisticated users simply can do a telnet to the port of a supported TCP-based service (such as 80, 22, or 25) to test for the system and server running. It is important to note that a ping will work even on a very sick system[14] and, therefore, it is not a good status test anyway.
I found smoothwall to suffer similar problems to SuSE's Firewall2 when I last looked at it a year ago. In both cases, the machine-generated scripts were hard to understand and convoluted. My advice is to learn enough to "roll your own" and verify its effectiveness with nmap, as discussed in "The nmap Network Mapper" on page 592. The effort will be comparable to fighting with these scripts and you will build an understanding of how the rules work. This understanding is necessary for properly configuring almost any firewall, regardless of the platform. I am otherwise impressed with SuSE's 8.0 installation procedure as trouble-free, easy, and doable by someone without needing lots of hardware knowledge and other experience. 12.5.8 Firewall Tricks and TechniquesCreating, changing, and especially debugging firewalls is a difficult process. It often is confusing, frustrating, and difficult to get right. Failure can substantially diminish the security of your network and leave you with a false sense of security. Those of you setting up your first serious firewall will discover that you need to know far more about protocols and network traffic than you ever wanted to learn. This is true especially if more than a few simple services are used. Add and debug one or two services at a time. Do not be afraid of saying to management, "I recommend against allowing that service because of security risks." If certain users can show a need for certain services, allow those services to those users only, not to everyone. Achieving access to a desired service on the opposite side of the firewall does not necessarily mean that you have achieved security. Use of popular scripts or firewall rule-building GUIs, consultants, or even large vendors does not guarantee that the end result, your firewall, will be secure. Many tools are overly simplistic or too cryptic for use and analysis. Alternately, those you hire may have limited understanding of your requirements and of possible solutions for your security problems. Only your understanding, analysis, testing, and audit (or demonstration of the same by whoever does the work) will ensure a secure firewall. Here are some tips and techniques to make this work easier, faster, and more likely to be secure:
12.5.9 Building an IP Tables Based Firewall with DMZCertainly, you will want a firewall between the Internet and your clients' systems (your users). Linux makes a fine firewall platform. However, you also probably want a firewall between your public-use systems, such as your Web server and e-mail server, and the rest of your internal network, and between your internal network and the Internet. This is to protect your public-use systems from attacks but also to protect the rest of your systems in case your public-use systems are compromised. Larger sites should have intranet firewalls protecting different parts of their internal networks from each other in case of a breach, as discussed in "Intracompany Firewalls to Contain Fires" on page 84 A single system acting as a firewall can be used to protect both the internal network and the public-use systems simply by having three network cards. One card would connect to the Internet via the ISP or upstream router and may be an Ethernet card, a T1 card, a T3 card, a modem providing PPP, etc. A second card would connect to the internal network. The third card would connect to the public-use systems such as the Web server, public-use FTP server, and e-mail server. This usually is called a Demilitarized Zone or DMZ.
It also is possible to have additional subnets protected by this single Linux firewall. One client had me separate his organization into three classes of users with different security requirements, as well as a DMZ accessible from the Internet, and an internal DMZ accessible only from within the organization. This internal DMZ sees the actual internal IP addresses of the networks due to selective IP Masquerading, discussed later.
The IP Tables facility has been available starting with the 2.4 kernel. IP Tables is available with all major distributions. The now rather-obsolete older facility was called ipfwadm and will not be discussed here. (If you are worried about firewalls and are using an older kernel, then it is time to upgrade anyway to avoid various problems. If you are determined to stay with the older kernel and use ipfwadm then most of what is discussed here can be done with ipfwadm, too.) The basic concept is that you specify which packets will be allowed to continue on their journey. The restriction can be any combination of source and destination system IP addresses, protocol type, port numbers, if the packet is the "SYN" packet that initiates a TCP/IP connection, and which interface the packet came in on or would go out on. There are some settings that are important on the firewall system that typically are not done by default. They are necessary to prevent certain attacks. They include:
Be sure to review "Intracompany Firewalls to Contain Fires" on page 84 for some considerations for additional custom rules that you may need. 12.5.10 What IP Tables Cannot DoIP Tables implements what is called a stateful firewall. This means that the decision to allow a packet through is made not only by its source and destination addresses, port number, and protocol, but also by whether packets that properly should precede it through the firewall have been seen. It protects against a TCP SYN flood attack, also known as a half-open attack, because the attacker sends only one of the two TCP packets needed to complete an open-session sequence. If that final packet from the client does not arrive within a short period of time, the stateful firewall will forget that the first packet was received. This protects the servers against the SYN flood attack. Note that all Linux kernels since the early 2.2 kernels can protect themselves against this attack if configured to do so. The Linux implementation that defends against this attack is rather clever and so there is no significant loss of efficiency even when under intense attack. This attack is explained in "SYN Flood Attack Explained" on page 245 and the proper configuration to resist it is given in "Defeating SYN Flood Attacks" on page 245. Certainly, each Linux system that might receive TCP connections from untrusted systems should be configured to resist this attack. Another feature present in some commercial firewalls that goes beyond that in IP Tables is content filtering. However, as we just discussed, there are commercial products for Linux that do this filtering. This is where the firewall looks beyond the protocol headers, looks at the actual data in the packets, and does filtering based on the data. For example, to block viruses one might filter out any e-mail that contains an attachment that a Microsoft mail client might interpret as a visual basic (.vbs) or .exe program. Another possibility might be to block http traffic whose content or URL is considered inappropriate by management, Human Resources, or the Legal Department for the workplace or during working hours. This would be the inappropriate disclosure of confidential data, threatening or harassing e-mail, searching for jobs in other companies, visiting sites unrelated to the organization's goals during working hours, and the like. Many organizations are interested in this feature because the law in some jurisdictions holds them liable for the actions of their employees or for competitive reasons, rather than because they have an interest in being a moral arbiter. Squid and Squidguard offer content filtering of URLs but not of the information in the pages themselves. This seems to be a philosophical decision rather than a technical one. Sendmail has a limited filtering capability at present. Some Intrusion Detection Systems, such as Snort, have a filtering capability. See "Stateful Firewalls" on page 510, "Using Sendmail to Block E-Mail Attacks" on page 393, and "The Snort Attack Detector" on page 598. For URL-based content filtering, Cerberian (www.cerberian.com) offers a well-designed commercial product that interfaces with Squid and connects to its huge database of categorized sites. You can block any combination of categories, such as gambling, shopping, various classes of naked people, leisure activities, etc. I have researched this product and was impressed with its capabilities. Another content-filtering product comes from Surf Control (www.surfcontrol.com) and offers a business version for UNIX computers. There are others. Consult your favorite search engine for links to other content-filtering products. On the surface, all of the URL-based content-filtering products are roughly equivalent, so we will let their respective marketing departments flex their muscles to convince you of their superiority. The Cerberian product got the commercial product "Authors Choice" nod because it works with Squid, one of my favorite Open Source projects. 12.5.11 IP Masquerading (NAT) ExplainedThese days, almost everyone's internal network is Masqueraded. This means that the IP addresses of the internal systems are private and not addressable from the Internet. Exceptions to this would be DMZs, those few organizations with as many public IP addresses available as machines, and servers at an ISP's collocation facility. Even then, Masquerading of their systems that will not be offering services to the Internet offers some security. Thus, understanding IP Masquerading is necessary for most SysAdmins, even those with home networks. When an IP packet is received, the kernel goes down a list of rules until it finds a rule matching the packet; then it handles the packet in the manner the rule specifies. If no matching rule is found, the default action is taken. It is called a chain instead of a list to confuse everyone, especially those that know this type of data structure is called a list. This concept is similar to TCP Wrappers or lots of other configurable programs as diverse as login and nfsd. For example, when you log in, the login program reads your user name and then goes down the list of user names in /etc/passwd until it finds the matching one and, if the correct password is supplied, executes the rule. This includes setting your UID, GID, home directory, and shell. IP Tables allows Masquerading. This concept, while very powerful, frequently is misunderstood. It means simply that the firewall system can allow the systems behind it (e.g., those on the organization's internal network) to pretend to be the firewall system. This means that if a system behind (inside) the firewall sends a packet to a system outside the firewall, it will appear to that outside system as if the packet originated from the firewall system itself. The firewall system will assign a port number temporarily to serve as the "source" of this packet. That outgoing packet's source address will be that of the firewall system itself rather than that of the originating system, from the point of view of the outside system. When the outside system sends its reply packet, it will have a destination address of the firewall system and a destination port number that the firewall is using as the temporary source. When the firewall receives this packet, it will determine which Masqueraded system and port are associated with this temporary source port and it will send the packet on to that system. Note that the inside system will see the packets as coming from the actual server system but the server system (and all systems along the way outside of the firewall) will see the packets as coming from the firewall system itself. This is illustrated in Figure 12.2. Figure 12.2. Masquerading packets.In Figure 12.2, you see that research.pentacorp.com is on the Corporate Ethernet with a Masqueraded address. In other words, its address was not accessible, or routable, from the Internet. This protects it from almost all Internet attacks.[16] In this figure, we have three machines, the Internet server at www.linuxjournal.com, the firewall at pentacorp.com, and the internal workstation at research.pentacorp.com. We will follow the request packet from research.pentacorp.com (r.p.c.) through the firewall (p.c.) to the Web server at linuxjournal.com (l.c.) and follow the reply packet back to r.p.c.
The r.p.c. system is none the wiser that somebody has been mucking with its packets and neither is l.c. There are two common reasons for using IP Masquerading. The first, particularly common for home networks, is to avoid being trapped by many ISPs that don't allow more than one home system. They do this simply by assigning you a single IP address and only allowing traffic from that address through their site. When you are using IP Masquerading, that is all that the ISP sees. The second reason for using Masquerading is for increased security at your site. Because you are using a private network address, a cracker cannot send packets to any of your systems behind the firewall because packets with private IP address destinations are not routed through the Internet. If you will be Masquerading your entire internal network, it is best to use one of the official network addresses assigned by Internet Assigned Numbers Authority (IANA) in RFC1597 for this purpose. This avoids any danger of accidentally conflicting with an actual network connected to the Internet. There is one private class-A network, 16 class-B networks, and 256 class-C networks available for this purpose. They are shown in Table 12.1.
Note that 172.16.*.* is the first class-B network, 172.17.*.* is the second, etc. The first class-C network is 192.168.0.*, the second one is 192.168.1.*, and so on. IP Tables allows the kernel to do any one of three different things to a packet.
There are three different chains, or lists, of rules. At each stage, if the packet is not accepted then that is the end of the packet (except when the packet is rejected, the kernel will notify the sending system). The first chain (list) is the input chain. Once a packet has been received by the kernel and its checksum checks out and it does not appear to be corrupted, it is subjected to input chain rules. If it is accepted, it is considered for de-Masquerading. If its destination IP is the firewall and the destination port is one of those allocated for Masquerading, then the destination IP and port are changed to those of the machine being Masqueraded and the packet then is sent to be processed by the output chain. If the incoming packet is not being de-Masqueraded, then normal routing takes place. If routing indicates that the destination is the firewall itself, then it is sent to the port requested to be received by the process listening on that port. Packets generated by local processes go directly to the output chain for processing. If the routing table says that the packet should be routed to another machine, the packet then is processed by the forward chain. Any packet that originated from someplace other than the firewall system itself and whose destination is other than the firewall system will be subject to the forward chain rules. Packets that pass the forward chain and packets that are generated on the firewall itself then are processed according to the output chain rules. Those that pass go on their merry way. This is illustrated in Figure 12.3. Figure 12.3. Traversing the firewall using IP Tables.As you see in Figure 12.3, each packet is subject to either the INPUT, OUTPUT, or FORWARD chains, depending on whether the packet is going to or from a process on the firewall. This is a dramatic and incompatible change from IP Chains. It requires a major redesign of almost all firewall rule sets when transitioning from IP Chains to IP Tables. This is because it was common under IP Chains to have the input and output rules handle most filtering and have the forward rule handle only routing and network address translation (NAT).
Under IP Tables, NAT is not done by the FORWARD chain. Instead, it is done by the POSTROUTING chain for the traditional hiding of internal systems. IP Tables introduces the new DNAT target, short for destination address network address translation. This allows the firewall's external IP address to be listed as a server's IP address. It then routes the packet invisible to the real server, possibly on the internal IP Masqueraded network. IP Tables' DNAT facility has more capabilities than IP Chains' REDIRECT target. IP Tables, like IP Chains, is very efficient and requires only a low horsepower system to handle even fairly high bandwidth Internet connections. Even a 486 system should be able to service a T1 or E1. A modern Pentium should handle a T3 (45 Mbps) or larger with ease. 12.5.12 IP Tables CommandsWhile you could issue commands directly to the kernel using the setsockopt() system call, most people will want to use the iptables program. Only the most commonly used features will be covered here. The -P flag allows specifying the default policy for a chain if none of the rules in that chain are matched. The chain names are input, forward, and output. For any chain, the default policy or target may be ACCEPT, DROP, or REJECT. The syntax looks like iptables -P chain target [options] To add a rule to the end of a chain, the -A flag is used. This flag is the most frequently used flag. The syntax looks like iptables -A chain rule [options] A rule may include an interface specification, a source IP address and port, a destination IP address and port, a protocol specification, and a target or disposition for the packet. Each of these is introduced with a dash (-) and the type of item, followed by the value. The value may be preceded by a bang (!) to mean not that value. An interface is specified by -i or --interface, possibly followed by a bang (!), followed by the name of the interface as shown by ifconfig. If the name ends in +, it will act as a wildcard similarly to the way an asterisk (*) does for other programs. These are some typical interface specifications. -i eth0 -i ! ppp0 A source address is specified by -s or --source; a destination address is specified by -d or --destination. Each of these accepts an IP address, specified either by host name or by numeric dotted quad. The quad may be followed by a slash (/) and a number indicating the quantity of high-order bits that should be matched. Instead of this number, a dotted quad may be used with each 1 bit tested. The rest of the bits of the address are ignored and may be anything. This address may be followed by a port name, port number, range of port numbers, or ICMP message number or name. The range is indicated by separating a pair of ports with a colon (:). Port names are looked up in /etc/services. If either the low or high port numbers of a colon-separated range are omitted, it defaults to 0 or 65535, respectively. If no port is specified, then the rule applies to all. If the protocol type is ICMP, then the "port number" instead should be the numeric ICMP code. Some examples are -s www.pentacorp.com 80 -d mail.pentacorp.com ! smtp -s 192.168.0.0/16 1024:65535 Instead of including the source or destination ports with the respective addresses, any of --source-port, --sport, --destination-port, or --dport may be used. Finally, the --icmp-type flag may be used to specify an ICMP message name. The most commonly specified ones are listed in Table 12.2. There are alternate ways to block ICMP echos that may be preferable in some cases, discussed in "Kernel Protocol Switches" on page 80.
A fragment (i.e., the second or subsequent packets of a fragmented message) may be matched with -f. The first fragment may be matched with ! -f. The -t flag will alter the type of service (TOS) that affects the delay, throughput, reliability, and cost in the handling of the packet. This is implemented by having multiple queues; the TOS determines which queue. Thus, telnet requests do not need to get stuck behind a massive queue of FTP data packets. The types of service, the arguments for -t to specify them, and the typical uses are listed in Table 12.3.
Possible rules to implement this are listed below. iptables -A FORWARD -i $INTNET -p tcp --dport ssh -t 0x01 0x10 iptables -A FORWARD -i $INTNET -p tcp --dport payroll -t 0x01 0x04 iptables -A FORWARD -i $INTNET -p tcp --dport nntp -t 0x01 0x02 Finally, what to do if the packet matches this rule may be specified with the -j or --jump flags, each of which requires a target. That target normally is ACCEPT, DROP, REJECT, REDIRECT, MASQUERADE, SNAT, DNAT, or LOG, but may be a user-defined chain or a lesser used target. The target names are case-sensitive. If there is no j, then this rule will cause only side effects, such as logging and updating counts. The --syn flag may be used with -A to require the packet's SYN bit that indicates that it is the first packet of a three-way TCP open. The -F command causes all rules in the specified chain to be flushed (deleted). If no chain was specified, then all rules will be flushed in that table. The -L command will list all rules in the specified chain or in all chains. The -C command, extremely helpful in IP Chains by allowing you to test the specified packet against the rules, was not ported to IP Tables. The -h command offers help. The -v flag causes verbosity. 12.5.13 Starting a Firewall ScriptNow, let us put this information to use. We will build a standard firewall for a small organization that could be a small company or a home network. We will follow the standard convention that eth0 will be the interface going to the Internet and eth1 will be the interface to the internal network. Many home networks now are connected to the Internet via DSL or cable modems, and the interface devices typically offer Ethernet on your side. (For those using PPP, the only difference is that the Internet interface will be ppp0 and the internal interface probably will be eth0.) The number one priority must be protection against crackers. Trying to "allow everything but what we fear" is too prone to errors, so we will "deny or reject everything but what we specifically allow." If this causes us to stop and scratch our heads occasionally when bringing up a new service or system, this is much preferable to kicking ourselves because we let a cracker through. Thus, we will follow the standard procedure of blocking everything and letting in specific types of packets that we consider safe. I prefer to do this before network interfaces are brought up, to avoid race conditions where attackers are lying in wait. On distributions that use the System V style of startup scripts, such as Red Hat and Mandrake, the scripts will be in /etc/rc.d/rc3.d and S10network will be the script that starts networking. Next, we will build on the SOHO firewall discussed in "Cut to the Chase: Protecting a Simple SOHO Network" on page 446. Begin by building on the script that was started in the previous section. The A flag instructs iptables to add the rule to the end of the chain. There are other flags that can insert rules in the middle of chains or can alter existing rules but those will not be needed here. We will allow any packets coming in on the loopback device with a proper source address and any going out to the loopback device with a proper destination address.These may include the IP address of the external, internal, or DMZ interface. Other addresses could be a misconfiguration or bug or could be an attempt at cracking; in any of these cases, blocking bad packets is the purpose of the firewall.
The -A flag causes this rule to be added to the end of the chain. The -i flag specifies the interface to which this rule applies; for systems with more than one interface this is important. The -s flag indicates that the argument that follows it should be used to match source IP addresses. The -d flag will cause the argument that follows it to be matched against the destination address. Finally, the -j flag specifies what the kernel should do with the packet of all the conditions that match. Capitalization is significant to the target (action) specified by -j. It is a good idea to log each rule that detects a security violation. The results will surprise you. The -l flag of IP Chains that causes the matched packet to be logged with syslogd was not ported to IP Tables. Instead, there is the LOG target. Most creators of IP Tables firewalls, including SuSE 8.0's Firewall2 have preceded each DROP or REJECT rule with one that is the same except that the target is LOG. I came up with the idea to create a user-defined chain instead. This chain would be named DROPl (the l is the letter "el") or REJECTl for logging rejected packets. This chain would have an unconditional LOG rule followed by an unconditional DROP. Then, in the 100 other places in the script where we want to LOG and DROP, we merely specify a target of DROPl. There is a small disadvantage to this technique in that the logged entry shows the rule number of the "universal" LOG rule rather than the rule number of the rule that matched the characteristics of the particular packet. To help decide if this will work for you, ask yourself if you can determine from the packet's source and destination IP addresses and ports and related details why the packet was dropped? It has been my experience that once a firewall is debugged, it almost always is easy. During debugging you can sprinkle the script with LOG rules or even watch the packet counts of the individual rules increase. To create and populate these chains, add the following near the beginning of the firewall script as per rc.fwsoho: IPT=/sbin/iptables # Do not complain if already exists # (so restart is clean) $IPT -N DROPl 2> /dev/null $IPT -A DROPl -j LOG $IPT -A DROPl -j DROP # Do not complain if already exists # (so restart is clean) $IPT -N REJECTl 2> /dev/null $IPT -A REJECTl -j LOG $IPT -A REJECTl -j REJECT If one of these targets is referenced later in this section, it is assumed that these rules are part of the script. To use one of these to DROP all packets from the evilhackerguild.org, add the following rule: EXTIF=eth0 $IPT -A INPUT -i $EXTIF -s evilhackerguild.org -j DROPl $IPT -A FORWARD -i $EXTIF -s evilhackerguild.org -j DROPl If any of the conditions do not match, the kernel tests subsequent rules either until a match occurs or until the end of the chain is reached. If the end is reached, the policy is executed; this may result in the packet being executed (dropped or rejected). We take a similar philosophy for the internal network. It is more important here to block packets with incorrect source addresses. On a large network, there is the chance that these are from someone operating from an internal system trying to crack someone else on the Internet. As good net citizens (who also do not want to receive visits from the Men in Black), we will be very careful about this. This is known as Egress filtering; it is explained more thoroughly in "Egress Filtering" on page 81. The rules follow. $IPT -A INPUT -i $INTIF -s $INTNET -j ACCEPT $IPT -A FORWARD -i $INTIF -s $INTNET -j ACCEPT As you can see, packets coming in from the internal interface must have an internal source address and packets destined for the internal interface must have a destination address that is internal or they will not fulfill their destiny. 12.5.14 Creating a DMZWe already have covered most of creating a DMZ. Much of the reasoning and physical organization was discussed in "Intracompany Firewalls to Contain Fires" on page 84. Most of the IP Tables work was done in "Cut to the Chase: Protecting a Simple SOHO Network" on page 446. We will start with that configuration, including installing the iptables_pre file and disabling the IP Tables and IP Chains facility that may have come with your Linux distribution. The rules granting access from the Internet to system stypically found on the DMZ, such as www.pentacorp.com or ftp.pentacorp.com, need to be added and some rules need changing (e.g., those that assume we have only a single external IP address). You will recall that packets are intended to go to these DMZ systems from both the Internet and the internal network. Now, we need to create those rules because they are on a separate interface. Following convention, the DMZ interface will be eth2. Again, we will build on our existing example. Our organization has a class-B network. We will use subnetting to split the lower 16 bits allocated for host bits. We do this so that the uppermost of these lower 16 bits will determine whether the destination is on the network outside the firewall or on the DMZ network. These outside systems include the firewall's external IP address, possibly our upstream router, maybe some VPN boxes, or test systems, etc. Since routers traditionally are host 1, have the uppermost bit be 0 for external addresses and 1 for DMZ addresses. (Certainly, those wanting many subnets can allocate more bits to specify the subnet and can create multiple subnets. One then would add more network cards to the firewall or would use a VLAN card and split out the different subnets here.) If you are working with Red Hat and its progeny, you will want to edit ifcfg-eth0 in /etc/sysconfig/network-scripts; Slackware users will want to edit /etc/rc.d/rc.inet1. The netmask will change from 255.255.0.0 to 255.255.128.0 Similarly, our network and broadcast addresses will gain a network bit and lose a host bit. For Red Hat and friends, or possibly enemies, we then copy ifcfg-eth0 to ifcfg-eth2. Then, in ifcfg-eth2, weincrease the value of the network number by 1. In other words, if the entire class-B network has a network and netmask of 216.247.0.0 255.255.0.0 then eth0 will have a network and netmask of 216.247.0.0 255.255.128.0 and eth2 will have a network and netmask of 216.247.128.0 255.255.128.0 The complete rule set is on the CD-ROM as rc.fwdmz in the book/iptables directory. Following is what had to change from the rc.fwsoho script. First, we need to capture the DMZ interface name and the IP, broadcast, and network addresses: # DMZ interface DMZIF=eth2 DMZIP="`$IFC $DMZIF|$G addr:|$SED 's/.*addr:\([^ ]*\) .*/\1/'`" DMZBC="`$IFC $DMZIF|$G Bcast:|$SED 's/.*Bcast:\([^ ]*\) .*/\1/'`" DMZMSK="`$IFC $DMZIF|$G Mask:|$SED 's/.*Mask:\([^ ]*\)/\1/'`" DMZNET="$DMZIP/$DMZMSK" echo "DMZIP=$DMZIP DMZBC=$DMZBC DMZMSK=$DMZMSK DMZNET=$DMZNET" Recall that evil packets from the Internet (as well as those from the internal network) already have been denied so the OUTPUT rule allows anything to the DMZ. We do want to allow the appropriate services to respond to queries. However, because there have been many security problems with FTP, we do not want to allow our people access to the public FTP server. This is to prevent them from storing confidential company documents on it and risking a security breach that might make those documents public. Instead, we want to provide a separate FTP server on the internal network. We need to mention the DMZ network where we will block broadcasts: # Block broadcasts $IPT -A INPUT -i $DMZIF -d $DMZBC -j DROPl $IPT -A OUTPUT -o $DMZIF -d $DMZBC -j DROPl $IPT -A FORWARD -o $DMZIF -d $DMZBC -j DROPl Next, we must remove the following rule because it only works if we have a single external IP address. We could use user-defined chains to implement it, but since it really is somewhat redundant, we will remove it: # Block Internet from trying to access internal or route $IPT -A INPUT -i $EXTIF -d ! $EXTIP -j DROPl Next, we must add the all-important rule to block outgoing packets with bad source addresses; this is part of Egress filtering. We will add this after the # Block internal with bad network address rules: # Block DMZ with bad network address $IPT -A INPUT -i $DMZIF -s ! $DMZNET -j DROPl $IPT -A OUTPUT -o $DMZIF -d ! $DMZNET -j DROPl $IPT -A FORWARD -i $DMZIF -s ! $DMZNET -j DROPl $IPT -A FORWARD -o $DMZIF -d ! $DMZNET -j DROPl We can allow the firewall to ping systems in the DMZ here, after the position where we allow the firewall to ping internal systems: # Allow firewall to ping DMZ systems $IPT -A OUTPUT -o $DMZIF -p icmp -s $DMZNET \ --icmp-type 8 -m state --state NEW -j ACCEPT The custom part of these rules specifies which systems in the DMZ will be allowed to receive which services. Just edit the appropriate variables here, which should be near the top of the script, to specify the IP address (not the host name) of each server in use. The same system may be listed in multiple variables but only a single system may be listed in each. We will also list the ISP's DNS and mail servers. # DMZ servers DNS1_IP="" HTTP_IP="" HTTPS_IP="" FTP_IP="" MAIL_IP="" POP3_IP="" POP3S_IP="" IMAP3_IP="" IMAP3S_IP="" ISPDNS1="" ISPMAIL1="" This rule redirects any auth requests back to the firewall to handle; this will protect your servers from these attacks. It should be done for any server that sends mail out to the Internet. Unless you have your users use your mail server as a "smart" relay host, this probably will be all of the servers except for the DNS servers. Hence, we will map the whole subnet. # Redirect auth requests to DMZ servers back to firewall # May be limited to servers that send mail out to Internet $IPT -t nat -A PREROUTING -p tcp --dport auth --syn -m state \ --state NEW -d $DMZNET -j DNAT --to-destination $EXTIP The rules to enable access to these servers are below. These rules may be placed after the auth rules. # Enable defined DMZ servers if [ "$DNS1_IP" != "" ] ; then $IPT -A FORWARD -i ! $DMZIF -p udp -d $DNS1_IP \ --dport domain -m state --state NEW -j ACCEPT fi # Usually do not enable TCP DNS to avoid Zone Transfers, etc. if [ "$HTTP_IP" != "" ] ; then $IPT -A FORWARD -i ! $DMZIF -p tcp -d $HTTP_IP \ --dport http --syn -m state --state NEW -j ACCEPT fi if [ "$HTTPS_IP" != "" ] ; then $IPT -A FORWARD -i ! $DMZIF -p tcp -d $HTTPS_IP \ --dport https --syn -m state --state NEW -j ACCEPT fi if [ "$FTP_IP" != "" ] ; then $IPT -A FORWARD -i ! $DMZIF -p tcp -d $FTP_IP \ --dport ftp --syn -m state --state NEW -j ACCEPT fi if [ "$MAIL_IP" != "" ] ; then $IPT -A FORWARD -i ! $DMZIF -p tcp -d $MAIL_IP \ --dport smtp --syn -m state --state NEW -j ACCEPT fi if [ "$POP3_IP" != "" ] ; then $IPT -A FORWARD -i ! $DMZIF -p tcp -d $POP3_IP \ --dport pop3 --syn -m state --state NEW -j ACCEPT fi if [ "$POP3S_IP" != "" ] ; then $IPT -A FORWARD -i ! $DMZIF -p tcp -d $POP3S_IP \ --dport pop3s --syn -m state --state NEW -j ACCEPT fi if [ "$IMAP3_IP" != "" ] ; then $IPT -A FORWARD -i ! $DMZIF -p tcp -d $IMAP3_IP \ --dport imap3 --syn -m state --state NEW -j ACCEPT fi if [ "$IMAP3S_IP" != "" ] ; then $IPT -A FORWARD -i ! $DMZIF -p tcp -d $IMAP3S_IP \ --dport imap3s --syn -m state --state NEW -j ACCEPT fi These rules do not enable access from the firewall itself as that would require an additional rule for each, thanks to IP Tables' cumbersome design.[17] The following would enable access from the firewall itself to the Web server, for example:
$IPT -A INPUT -i $DMZIF -p tcp -s $DMZIP -d $HTTP_IP \ --dport http --syn -m state --state NEW -j ACCEPT Do the servers need to act as clients? The Web server and mail server probably want to do DNS for logging and security checks. At least one of them probably will want to send out mail. The whole purpose of a DMZ is to limit the damage done if a server is compromised. This limitation should take into account the damage that might be done to the rest of the Internet from a cracker using one of your servers to attack other systems. Besides getting you blamed, possibly on the front page of the Wall Street Journal or in court, if you pay for bandwidth by the byte, your costs could go very high. These rules should be as specific as possible. Limiting the destination to only your ISP's DNS and mail servers with -d is an excellent idea. Replacing $DMZNET with addresses of specific systems in your DMZ needing the access is desirable too: # Enable DMZ systems to use the services that they need if [ "$ISPDNS1" != "" ] ; then $IPT -A FORWARD -i $DMZIF -p udp -s $DMZNET \ --dport domain -d $ISPDNS1 -m state --state NEW -j ACCEPT fi if [ "$ISPMAIL1" != "" ] ; then $IPT -A FORWARD -i $DMZIF -p tcp -s $DMZNET \ --dport smtp -d $ISPMAIL1 -m state --state NEW -j ACCEPT fi After our one rule with a MASQUERADE target (for Masquerading initial packets from internal systems to the Internet), we will add a corresponding rule to Masquerade packets from internal systems to the DMZ. (If we are not Masquerading our internal network, do not use this rule.) $IPT -t nat -A POSTROUTING -o $DMZIF -s $INTNET -j MASQUERADE Lastly, let's have a bit of magic to avoid dealing with our upstream router. While a Linux firewall makes a fine easy-to-configure T1/E1/Frame Relay Router with the addition of a Sangoma or similar network card, many organizations are stuck with a Cisco Router. Often, these Cisco Routers are managed by the ISP or others who are hard to deal with and are not always terribly knowledgeable, based on my experience. Something as simple as "we are inserting a firewall whose IP is thus and such, please reconfigure to route all of our traffic through it, except these XYZ outside IP addresses" can be beyond the capability of many. The answer is Proxy ARP. Briefly, with Proxy ARP, when a system on the outside interface assumes that a DMZ system (or non IP Masqueraded inside system) is connected directly to the outside LAN, this outside system will send an ARP request to discover the inside system's MAC address. With Proxy ARP enabled on the firewall, it will provide its own outside interface's MAC address and forward the packets to the DMZ automatically. More details are discussed in "Understanding Address Resolution Protocol (ARP)" on page 145. The following lines will enable this. echo "Enabling Proxy ARP from the External interface" echo 1 > /proc/sys/net/ipv4/conf/$EXTIF/proxy_arp Proxy ARP does no harm to those systems that are configured to route the traffic through the firewall. Where desired, Proxy ARP can be enabled for the other interfaces, too. For example, if enabled from the DMZ with echo "Enabling Proxy ARP from the DMZ interface" echo 1 > /proc/sys/net/ipv4/conf/$DMZIF/proxy_arp the DMZ systems will not need their gateway system's IP updated to the firewall system either. 12.5.15 Routing SecretsMost documentation on firewalls and routers gives the usual spiel about having more bits in the network mask of the internal subnets than in the external network. Back in the days when everyone had at least a full class-C network, that was fine. What about now, where you may get only two or three real IP addresses, after writing off both the host portion of all zeros and all ones to broadcast addresses?[18] What can you do to not waste half of the address space on the external network where only the firewall and possibly the upstream router reside?
The answer: Use the route command to add routes for specific host addresses. It is helpful to keep in mind that an interface's network routing entry only is used if a more specific route is not found first. Routes are sorted, starting with the most specific first (the largest number of 1 bits in the netmask). These host-specific route commands will take priority. This allows using addresses that are outside of the range allocated for your DMZ, for example, to be used for systems that are inside the DMZ, over those that are generated automatically when an interface is brought up. We are not stuck even with giving up two addresses for the external interface's broadcast addresses and another two for the DMZ's broadcast addresses. Have the DMZ use the high half of the address range. Thus, the same broadcast address is used for both. What happens when sending out a broadcast? (You should not be sending broadcasts anyway, but the system won't melt if you do.) What do you do with the DMZ all-zeros broadcast address? Why, use it for a system outside of the firewall that does not need to access systems inside. As it turns out, though undocumented, when deciding how to route a packet, the Linux kernel will check the IP address and broadcast address for each operating interface before checking the routing table. An interesting consequence of this is that if an interface's broadcast address is that of a system to which you are trying to send packets (either intentionally or by mistake), that system had best be on that interface 'cause that's where the packet is going. If you use these routing secrets, your firewall rules probably will need to be changed. This is because of assumptions about network masks and where systems belong that match them. For example, blocking a packet from the DMZ whose source address does not match $DMZNET no longer will work. Instead, add a rule that matches each DMZ system's source IP address on the outside interface (where it should not be) and drop the packet. 12.5.16 IP Tables' Lesser Used FeaturesIP Tables has some other features of interest, primarily for those managing large shops. Perhaps the most useful is the limit module. It allows IP Tables to match only until a packet-rate limit is reached. The manual suggests this is useful with the LOG target to limit the amount of logging done (e.g., when your system is under intense attack). This might help fight Denial of Service (DoS) attacks, especially w.r.t. the time of the SysAdmin. I can see using the logging feature instead to limit how much of one's bandwidth is used for particular services. The syntax is: -m limit --limit rate[/{second,minute,hour,day}] The MAC (or Ethernet) address of a locally connected system can be matched via: -m mac --mac-source [[!] XX:XX:XX:XX:XX:XX] This can be useful to protect against an in-house "script kiddie" who knows enough to change her IP address but not enough to change her MAC address. Instead, I recommend specifying permanent ARP table entries, as discussed in "Preventing ARP Cache Poisoning" on page 146 and peaking ahead to "Using Arpwatch to Catch ARP and MAC Attacks" on page 626. The --tcp-flags option can be used for other matching of TCP flags besides the use of --syn. You can use -m state --state INVALID to detect crackers trying to send packets that violate protocols in order to breach the firewall. Lastly, IP Tables supports IPV6 addressing. IPV6 will happen right after the U.S. and Great Britain adopt the metric system. The latter was going to happen within about five years, according to my third-grade teacher. The -m owner module can be used to match packets originating from a particular user or process on the firewall, using the --uid-owner, --gid-owner, --pid-owner, --sid-owner (or session ID), or --cmd-owner name. This can be useful for collocated systems or for those that violate the important security rule of running different services on different systems. 12.5.17 Stateful FirewallsThe firewall techniques discussed in the previous sections offer excellent protection from many common types of attacks and definitely should be used. Unlike IP Chains, these IP Tables rules allow the protection of a fully capable stateful firewall. Note that if all of your nonserver systems are IP Masqueraded, IP Chains already is providing this stateful capability. Let us examine the protection that this statefulness offers. One of the holes against which IP Tables protects is some violations of protocols, such as the use of echo replies for network mapping and activating DDoS zombies. Another threat that has been increasing is the use of traditionally open ports, such as TCP ports 23 and 80 (i.e., telnet and www) to run services unrelated to the intended purposes of these ports in order to circumvent written policy and firewall rules.
While even Squid (a popular open-source Web-page caching program) can block access to undesirable sites, some people will use "redirecting" Web sites that are not blocked (i.e., unless you specifically block them) to route requests to undesirable sites. Microsoft offers products based on Simple Object Access Protocol (SOAP) as a way to avoid dealing with firewalls limiting access to approved traffic. A typical SOAP request is disguised to look like an ordinary HTTP request. The following is an example that Microsoft quotes.[19]
http://skonnard.com/soaplike/businessobj.asp?param1=hello+world Fortunately, the SOAP specification uses the Content-Type header value text/xml-SOAP; this allows easy blocking using the Squid tools discussed below. (SOAP and some of these other tunnelling techniques were discussed in "Stopping End Runs Around Firewalls" on page 74.) There also is Squidguard, which also offers blocking. Lastly, there is Junkbuster, which is designed specifically to shield the person browsing from ads, intrusive cookies, or Web sites getting information about them. These are available at the following locations and on the CD-ROM and Web site. www.squid-cache.org/ www.squidguard.org/ www.junkbusters.com/ The Linux 2.4 kernel, released in mid-2000, offers a stateful firewall capability with IP Tables, also known as NETFILTER. It allows you to control the rate of various packets being accepted and to shunt certain packets off to user-level programs for further analysis to allow stateful firewalls. Also, there is Phoenix Adaptive Firewall and Checkpoint. While Phoenix is an expensive commercial product costing about U.S.$3,000, it is the first firewall to be ICSA certified for Linux. This makes it a good Linux solution for big and stuffy shops and an excellent alternative to products running on closed-source alternatives. Various stateful firewall possibilities are discussed at these locations: www.netfilter.org/ www.seifried.org/lasg/network-servers/proxy/index.html www.obfuscation.org/ipf/ipf-howto.txt coombs.anu.edu.au/~avalon/ip-filter.html 12.5.18 SSH DangersThe firewall rules typically would block most service requests into the internal network. Certainly, the default should be to block all externally originated requests (or connections) that are trying to get into your internal network, then let in specific services. Under special conditions, you may want to allow some access to particular hardened systems that are on your internal network, though it is preferable to have all such systems in the DMZ. Generally, it should be OK to allow ssh requests to your internal systems so your employees can work from home. For more security, one possibility is to use strong passwords combined with allowing access to ssh only from certain IP addresses or networks. Alternatively, use really strong passwords and a good Intrusion Detection System with at least near real-time pager capability. (See "Using Logcheck to Check Log Files You Never Check" on page 608) Understand that if your organization is a large entity then the probability is good that at least some of your users' home systems will be compromised, usually in exploits unrelated to company activities. Employees who are less knowledgeable about security and using operating systems less secure than Linux are at the greatest risk. Home systems that have continuous connections, such as those with cable modems and DSL, are at the greatest risk of suffering a break-in. Cable modems have the additional risk of being networked with other nearby subscribers in what could be thought of as a LAN. The question is: If a home system is broken, will the cracker simply look around and "hide behind" it to attack other random systems or will he be sophisticated enough to monitor your employee's activities and discover the SSH passkey and then invade your organization's systems? While I have not seen any reports of the latter, it is a real danger. The more attractive your site is to crackers and the larger it is, the more likely this is to happen. A cracker even could target your employees' home systems for such an attack. This targeting is not hard to do. A cracker merely needs to search the Web and News groups for your organization's name and search these pages for employee names. Then he would do the same search on the employees' names looking for e-mail addresses unrelated to your organization. These would be the employees' home e-mail addresses. With some ISPs, the e-mail address may be mapped directly to the fully qualified host name of the subscriber's home system when connected. Then, the cracker merely needs to find one employee who has not bothered to secure his system. This is the risk you must contend with if you allow employees to connect from their home systems. Clearly, the more employees you let in, the greater the risk of this sort of attack, and the greater the risk of a cracker breaking into an employee's system and attacking your organization's network. This, alone, would be a justification for denying even SSH. Except for those installations that need high security, it might be reasonable for you to evaluate the security of the home system of each employee that requests SSH access to her office system. It is very important to have written management approval to conduct this home-system security audit, as some users might complain and this otherwise could result in problems for the SysAdmin. Additionally, there may be laws in your area affecting this activity that need to be reviewed. This audit might involve a list of questions the employee must answer, either verbally or in electronic or written form. It is suggested that you e-mail the list of questions to the employee, offer the option of responding electronically or in writing, print out the responses, then have the employee review and sign the printout. This signature also should guarantee that the employee will contact a SysAdmin prior to doing anything that reduces home security and therefore possibly affecting the organization's security. Once you have management approval, SysAdmins will want to make this check of security of each home system by seeing what ports are open, asking the user what services are supported and what systems are allowed to use them, examining what versions of critical software are running, and looking at how secure the passwords are. For home Linux systems, you will be particularly interested in what versions of telnet, FTP, sendmail (unless blocked by the ISP), named, and Netscape are in use. In short, review those programs where buggy versions allow break-ins, as discussed in "Quick Fixes for Common Problems" on page 17. You will also be interested in the use of intracompany firewalls and similar techniques. These are discussed in "Intracompany Firewalls to Contain Fires" on page 84. Certainly, by allowing this SSH connection, or a similar connection such as TCP Wrapper access, between the organization's network and a user's home system, you are adding the user's home system to the organization's network. It is important, therefore, to educate each home user on security. Even those of you running other operating systems could benefit from some of the information in the book. Also, you may want to write up some notes on security to be supplied to users seeking SSH access. You might even want to have a quiz on the material before granting access. While this might seem excessive, the organization's security depends on it. The alternative would be to forbid SSH access, and certainly you will be blamed if someone breaks into the organization's network this way. 12.5.19 Encrypted Mail AccessA major question that needs to be answered is whether there should be a single mail server that accumulates e-mail and allows client systems to download e-mail via POP3 or IMAP. The other option is to allow e-mail to be delivered directly to users' own systems via SMTP. If the clients are Windows and Macs then POP3 and IMAP are popular and reasonably safe. Certainly, the Windows users will be vulnerable to the various e-mail viruses and worms regardless of how they receive e-mail. See "Using Sendmail to Block E-Mail Attacks" on page 393 for some help fighting known viruses and worms, though the real solution is disabling the execution of foreign code. Even if the clients are Linux and UNIX boxes, this is a safe and easy solution. Also, it protects even these clients against the vulnerabilities of sendmail. Certainly, POP3 and IMAP requests originating from outside of the organization should be blocked by the firewall unless wrapped in SSL or a similar secure protocol. Many of the new mail readers can receive SSL-wrapped mail from POP3 or IMAP mailboxes. This would involve allowing the spop3 and simap services, sometimes called pop3s and imaps. These would be TCP ports 995 and 993, respectively. If the IP address of your mail server is 216.247.56.62 then the following IP Chains commands will allow access. $IPT -A FORWARD -i $EXTIF -p tcp -j ACCEPT -s 0.0.0.0/0 \ -d 216.247.56.62/32 995 $IPT -A FORWARD -i $EXTIF -p tcp -j ACCEPT -s 0.0.0.0/0 \ -d 216.247.56.62/32 993 You may want to allow e-mail directly to some of your Linux and UNIX client boxes whose sendmail versions are kept up-to-date. In either case, the firewall rules would block all incoming service requests to the Web server except http, https, and ssh. Similarly, the firewall would block all services to the external DNS server[20] and mail server except DNS and SMTP, respectively, and ssh.
|
Top |